mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-04 22:58:29 +08:00

- Widget now has a children array - Widgets can be activated and deactivated (this recurses over child widgets) - Renderers are now turned on and off in activate/deactivate methods - It is now possible to set a tool-local path (this path is appended to the tool's base path) - TabContainer can now automatically set a path based on paths given in its tab configuration - It's now possible to directly link to subviews of the viewer and the hunt optimizer
173 lines
6.0 KiB
TypeScript
173 lines
6.0 KiB
TypeScript
import { REGISTER_COUNT } from "../scripting/vm/VirtualMachine";
|
|
import { TextInput } from "../../core/gui/TextInput";
|
|
import { ToolBar } from "../../core/gui/ToolBar";
|
|
import { CheckBox } from "../../core/gui/CheckBox";
|
|
import { number_to_hex_string } from "../../core/util";
|
|
import "./RegistersView.css";
|
|
import { Select } from "../../core/gui/Select";
|
|
import { QuestRunner } from "../QuestRunner";
|
|
import { div } from "../../core/gui/dom";
|
|
import { ResizableView } from "../../core/gui/ResizableView";
|
|
|
|
enum RegisterDisplayType {
|
|
Signed,
|
|
Unsigned,
|
|
Word,
|
|
Byte,
|
|
Float,
|
|
}
|
|
|
|
type RegisterGetterFunction = (register: number) => number;
|
|
|
|
export class RegistersView extends ResizableView {
|
|
private readonly type_select = this.add(
|
|
new Select({
|
|
label: "Display type:",
|
|
tooltip: "Select which data type register values should be displayed as.",
|
|
items: [
|
|
RegisterDisplayType.Signed,
|
|
RegisterDisplayType.Unsigned,
|
|
RegisterDisplayType.Word,
|
|
RegisterDisplayType.Byte,
|
|
RegisterDisplayType.Float,
|
|
],
|
|
to_label: type => RegisterDisplayType[type],
|
|
}),
|
|
);
|
|
private register_getter: RegisterGetterFunction = this.get_register_getter(
|
|
RegisterDisplayType.Signed,
|
|
);
|
|
|
|
private readonly hex_checkbox = this.add(
|
|
new CheckBox(false, {
|
|
label: "Hex",
|
|
tooltip: "Display register values in hexadecimal.",
|
|
}),
|
|
);
|
|
|
|
private readonly settings_bar = this.add(new ToolBar(this.type_select, this.hex_checkbox));
|
|
|
|
private readonly register_els: TextInput[];
|
|
private readonly list_element = div({ className: "quest_editor_RegistersView_list" });
|
|
private readonly container_element = div(
|
|
{ className: "quest_editor_RegistersView_container" },
|
|
this.list_element,
|
|
);
|
|
|
|
readonly element = div(
|
|
{ className: "quest_editor_RegistersView" },
|
|
this.settings_bar.element,
|
|
this.container_element,
|
|
);
|
|
|
|
constructor(private readonly quest_runner: QuestRunner) {
|
|
super();
|
|
|
|
this.type_select.selected.val = RegisterDisplayType.Signed;
|
|
|
|
// create register elements
|
|
const register_els: TextInput[] = Array(REGISTER_COUNT);
|
|
for (let i = 0; i < REGISTER_COUNT; i++) {
|
|
const value_el = this.add(
|
|
new TextInput("", {
|
|
class: "quest_editor_RegistersView_value",
|
|
label: `r${i}:`,
|
|
readonly: true,
|
|
}),
|
|
);
|
|
|
|
const wrapper_el = div(
|
|
{ className: "quest_editor_RegistersView_register" },
|
|
value_el.label!.element,
|
|
value_el.element,
|
|
);
|
|
|
|
register_els[i] = value_el;
|
|
|
|
this.list_element.appendChild(wrapper_el);
|
|
}
|
|
this.register_els = register_els;
|
|
|
|
// predicate that indicates whether to display
|
|
// placeholder text or the actual register values
|
|
const should_use_placeholders = (): boolean =>
|
|
!this.quest_runner.paused.val || !this.quest_runner.running.val;
|
|
|
|
// set initial values
|
|
this.update(should_use_placeholders(), this.hex_checkbox.checked.val);
|
|
|
|
this.disposables(
|
|
// check if values need to be updated
|
|
// when QuestRunner execution state changes
|
|
this.quest_runner.running.observe(() =>
|
|
this.update(should_use_placeholders(), this.hex_checkbox.checked.val),
|
|
),
|
|
this.quest_runner.paused.observe(() =>
|
|
this.update(should_use_placeholders(), this.hex_checkbox.checked.val),
|
|
),
|
|
|
|
this.type_select.selected.observe(({ value }) => {
|
|
if (value != undefined) {
|
|
this.register_getter = this.get_register_getter(value);
|
|
this.update(should_use_placeholders(), this.hex_checkbox.checked.val);
|
|
}
|
|
}),
|
|
|
|
this.hex_checkbox.checked.observe(change =>
|
|
this.update(should_use_placeholders(), change.value),
|
|
),
|
|
);
|
|
|
|
this.finalize_construction();
|
|
}
|
|
|
|
private get_register_getter(type: RegisterDisplayType): RegisterGetterFunction {
|
|
let getter: RegisterGetterFunction;
|
|
|
|
switch (type) {
|
|
case RegisterDisplayType.Signed:
|
|
getter = this.quest_runner.vm.get_register_signed;
|
|
break;
|
|
case RegisterDisplayType.Unsigned:
|
|
getter = this.quest_runner.vm.get_register_unsigned;
|
|
break;
|
|
case RegisterDisplayType.Word:
|
|
getter = this.quest_runner.vm.get_register_word;
|
|
break;
|
|
case RegisterDisplayType.Byte:
|
|
getter = this.quest_runner.vm.get_register_byte;
|
|
break;
|
|
case RegisterDisplayType.Float:
|
|
getter = this.quest_runner.vm.get_register_float;
|
|
break;
|
|
}
|
|
|
|
return getter.bind(this.quest_runner.vm);
|
|
}
|
|
|
|
private update(use_placeholders: boolean, use_hex: boolean): void {
|
|
if (use_placeholders) {
|
|
const placeholder_text = "??";
|
|
for (let i = 0; i < REGISTER_COUNT; i++) {
|
|
const reg_el = this.register_els[i];
|
|
|
|
reg_el.value.set_val(placeholder_text, { silent: true });
|
|
}
|
|
} else if (use_hex) {
|
|
for (let i = 0; i < REGISTER_COUNT; i++) {
|
|
const reg_el = this.register_els[i];
|
|
const reg_val = this.quest_runner.vm.get_register_unsigned(i);
|
|
|
|
reg_el.value.set_val(number_to_hex_string(reg_val), { silent: true });
|
|
}
|
|
} else {
|
|
for (let i = 0; i < REGISTER_COUNT; i++) {
|
|
const reg_el = this.register_els[i];
|
|
const reg_val = this.register_getter(i);
|
|
|
|
reg_el.value.set_val(reg_val.toString(), { silent: true });
|
|
}
|
|
}
|
|
}
|
|
}
|