phantasmal-world/src/quest_editor/gui/RegistersView.ts

174 lines
6.0 KiB
TypeScript
Raw Normal View History

2019-11-22 05:04:16 +08:00
import { ResizableWidget } from "../../core/gui/ResizableWidget";
import { REGISTER_COUNT } from "../scripting/vm/VirtualMachine";
2019-11-22 05:04:16 +08:00
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";
2019-11-22 05:04:16 +08:00
enum RegisterDisplayType {
Signed,
Unsigned,
Word,
Byte,
Float,
}
type RegisterGetterFunction = (register: number) => number;
export class RegistersView extends ResizableWidget {
private readonly type_select = this.disposable(
new Select({
label: "Display type:",
tooltip: "Select which data type register values should be displayed as.",
items: [
2019-11-22 05:04:16 +08:00
RegisterDisplayType.Signed,
RegisterDisplayType.Unsigned,
RegisterDisplayType.Word,
RegisterDisplayType.Byte,
RegisterDisplayType.Float,
],
to_label: type => RegisterDisplayType[type],
}),
2019-11-22 05:04:16 +08:00
);
private register_getter: RegisterGetterFunction = this.get_register_getter(
RegisterDisplayType.Unsigned,
);
private readonly hex_checkbox = this.disposable(
new CheckBox(false, {
label: "Hex",
tooltip: "Display register values in hexadecimal.",
}),
);
private readonly settings_bar = this.disposable(
new ToolBar(this.type_select, this.hex_checkbox),
2019-11-22 05:04:16 +08:00
);
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" },
2019-11-22 05:04:16 +08:00
this.list_element,
);
public readonly element = div(
{ className: "quest_editor_RegistersView" },
2019-11-22 05:04:16 +08:00
this.settings_bar.element,
this.container_element,
);
constructor(private readonly quest_runner: QuestRunner) {
2019-11-22 05:04:16 +08:00
super();
this.type_select.selected.val = RegisterDisplayType.Unsigned;
2019-11-22 05:04:16 +08:00
// create register elements
const register_els: TextInput[] = Array(REGISTER_COUNT);
for (let i = 0; i < REGISTER_COUNT; i++) {
const value_el = this.disposable(
new TextInput("", {
class: "quest_editor_RegistersView_value",
label: "r" + i,
readonly: true,
}),
);
const wrapper_el = div(
{ className: "quest_editor_RegistersView_register" },
2019-11-22 05:04:16 +08:00
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;
2019-11-22 05:04:16 +08:00
// 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(() =>
2019-11-22 05:04:16 +08:00
this.update(should_use_placeholders(), this.hex_checkbox.checked.val),
),
this.quest_runner.paused.observe(() =>
2019-11-22 05:04:16 +08:00
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);
}
2019-11-22 05:04:16 +08:00
}),
this.hex_checkbox.checked.observe(change =>
this.update(should_use_placeholders(), change.value),
),
);
this.finalize_construction();
2019-11-22 05:04:16 +08:00
}
private get_register_getter(type: RegisterDisplayType): RegisterGetterFunction {
2019-11-22 05:04:16 +08:00
let getter: RegisterGetterFunction;
switch (type) {
2019-11-22 05:04:16 +08:00
case RegisterDisplayType.Signed:
getter = this.quest_runner.vm.get_register_signed;
2019-11-22 05:04:16 +08:00
break;
case RegisterDisplayType.Unsigned:
getter = this.quest_runner.vm.get_register_unsigned;
2019-11-22 05:04:16 +08:00
break;
case RegisterDisplayType.Word:
getter = this.quest_runner.vm.get_register_word;
2019-11-22 05:04:16 +08:00
break;
case RegisterDisplayType.Byte:
getter = this.quest_runner.vm.get_register_byte;
2019-11-22 05:04:16 +08:00
break;
case RegisterDisplayType.Float:
getter = this.quest_runner.vm.get_register_float;
2019-11-22 05:04:16 +08:00
break;
}
return getter.bind(this.quest_runner.vm);
2019-11-22 05:04:16 +08:00
}
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);
2019-11-22 05:04:16 +08:00
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 });
}
}
}
}