mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-04 22:58:29 +08:00
Renamed "Debug Log" to "Debug" and moved all debugging related buttons to its toolbar.
This commit is contained in:
parent
da64ad93c5
commit
38f4bdd484
@ -155,7 +155,7 @@ Features that are in ***bold italics*** are planned but not yet implemented.
|
||||
## Bugs
|
||||
|
||||
- [Load Quest](#load-quest): Can't parse quest 125 White Day
|
||||
- [Script Assembly Editor](#script-assembly-editor): Go to definition doesn't work in RT (#231)
|
||||
- [Script Assembly Editor](#script-assembly-editor): Go to definition doesn't work in RT (#231) and PW2 (#234)
|
||||
- When a modal dialog is open, global keybindings should be disabled
|
||||
- Entities with rendering issues:
|
||||
- Caves 4 Button door
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-empty-function,@typescript-eslint/explicit-function-return-type */
|
||||
class Editor {
|
||||
addCommand() {}
|
||||
getAction() {}
|
||||
@ -72,6 +73,7 @@ exports.languages = {
|
||||
registerSignatureHelpProvider() {},
|
||||
setLanguageConfiguration() {},
|
||||
registerDefinitionProvider() {},
|
||||
registerHoverProvider() {},
|
||||
};
|
||||
|
||||
exports.KeyMod = {
|
||||
|
@ -92,7 +92,7 @@ exports[`Should render correctly.: It should render a button per tool, the selec
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="core_Menu"
|
||||
class="core_Menu disabled"
|
||||
hidden=""
|
||||
tabindex="-1"
|
||||
>
|
||||
|
@ -57,10 +57,7 @@ export function parse_xj_model(cursor: Cursor): XjModel {
|
||||
};
|
||||
|
||||
if (vertex_info_count >= 1) {
|
||||
if (vertex_info_count > 1) {
|
||||
logger.warn(`Vertex info count of ${vertex_info_count} was larger than expected.`);
|
||||
}
|
||||
|
||||
// TODO: parse all vertex info tables.
|
||||
model.vertices.push(...parse_vertex_info_table(cursor, vertex_info_table_offset));
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import { VirtualMachineIO } from "./scripting/vm/io";
|
||||
import { WritableProperty } from "../core/observable/property/WritableProperty";
|
||||
import { list_property, property } from "../core/observable";
|
||||
import { Property } from "../core/observable/property/Property";
|
||||
import { log_store } from "./stores/LogStore";
|
||||
import { Breakpoint, Debugger } from "./scripting/vm/Debugger";
|
||||
import { WritableListProperty } from "../core/observable/property/list/WritableListProperty";
|
||||
import { ListProperty } from "../core/observable/property/list/ListProperty";
|
||||
@ -15,6 +14,9 @@ import { QuestObjectModel } from "./model/QuestObjectModel";
|
||||
import { AreaStore } from "./stores/AreaStore";
|
||||
import { InstructionPointer } from "./scripting/vm/InstructionPointer";
|
||||
import { clone_segment } from "../core/data_formats/asm/instructions";
|
||||
import { Logger } from "../core/Logger";
|
||||
import { LogStore } from "./stores/LogStore";
|
||||
import { Severity } from "../core/Severity";
|
||||
|
||||
export enum QuestRunnerState {
|
||||
/**
|
||||
@ -54,7 +56,7 @@ export type GameState = Readonly<GameStateInternal>;
|
||||
* delegates to {@link Debugger}.
|
||||
*/
|
||||
export class QuestRunner {
|
||||
private logger = log_store.get_logger("quest_editor/QuestRunner");
|
||||
private logger: Logger;
|
||||
private animation_frame?: number;
|
||||
private startup = true;
|
||||
private readonly _state: WritableProperty<QuestRunnerState> = property(
|
||||
@ -101,7 +103,9 @@ export class QuestRunner {
|
||||
return this._game_state;
|
||||
}
|
||||
|
||||
constructor(private readonly area_store: AreaStore) {
|
||||
constructor(private readonly area_store: AreaStore, log_store: LogStore) {
|
||||
this.logger = log_store.get_logger("quest_editor/QuestRunner");
|
||||
this.logger.severity = Severity.Trace;
|
||||
this.vm = new VirtualMachine(this.create_vm_io());
|
||||
this.debugger = new Debugger(this.vm);
|
||||
}
|
||||
|
62
src/quest_editor/controllers/DebugController.test.ts
Normal file
62
src/quest_editor/controllers/DebugController.test.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { with_disposer } from "../../../test/src/core/observables/disposable_helpers";
|
||||
import { GuiStore } from "../../core/stores/GuiStore";
|
||||
import { create_area_store } from "../../../test/src/quest_editor/stores/store_creation";
|
||||
import { QuestEditorStore } from "../stores/QuestEditorStore";
|
||||
import { Episode } from "../../core/data_formats/parsing/quest/Episode";
|
||||
import { DebugController } from "./DebugController";
|
||||
import { LogStore } from "../stores/LogStore";
|
||||
import { create_new_quest } from "../stores/quest_creation";
|
||||
import { next_animation_frame } from "../../../test/src/utils";
|
||||
|
||||
test("Some widgets should only be enabled when a quest is loaded.", async () =>
|
||||
with_disposer(async disposer => {
|
||||
const gui_store = disposer.add(new GuiStore());
|
||||
const area_store = create_area_store(disposer);
|
||||
const log_store = disposer.add(new LogStore());
|
||||
const quest_editor_store = disposer.add(
|
||||
new QuestEditorStore(gui_store, area_store, log_store),
|
||||
);
|
||||
const ctrl = disposer.add(new DebugController(gui_store, quest_editor_store, log_store));
|
||||
|
||||
expect(ctrl.can_debug.val).toBe(false);
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
|
||||
await quest_editor_store.set_current_quest(create_new_quest(area_store, Episode.I));
|
||||
|
||||
expect(ctrl.can_debug.val).toBe(true);
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
}));
|
||||
|
||||
test("Debugging controls should be enabled and disabled at the right times.", async () =>
|
||||
with_disposer(async disposer => {
|
||||
const gui_store = disposer.add(new GuiStore());
|
||||
const area_store = create_area_store(disposer);
|
||||
const log_store = disposer.add(new LogStore());
|
||||
const quest_editor_store = disposer.add(
|
||||
new QuestEditorStore(gui_store, area_store, log_store),
|
||||
);
|
||||
const ctrl = disposer.add(new DebugController(gui_store, quest_editor_store, log_store));
|
||||
|
||||
await quest_editor_store.set_current_quest(create_new_quest(area_store, Episode.I));
|
||||
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
expect(ctrl.can_stop.val).toBe(false);
|
||||
|
||||
ctrl.debug();
|
||||
await next_animation_frame();
|
||||
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
expect(ctrl.can_stop.val).toBe(true);
|
||||
|
||||
ctrl.stop();
|
||||
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
expect(ctrl.can_stop.val).toBe(false);
|
||||
|
||||
quest_editor_store.quest_runner.set_breakpoint(5);
|
||||
ctrl.debug();
|
||||
await next_animation_frame();
|
||||
|
||||
expect(ctrl.can_step.val).toBe(true);
|
||||
expect(ctrl.can_stop.val).toBe(true);
|
||||
}));
|
98
src/quest_editor/controllers/DebugController.ts
Normal file
98
src/quest_editor/controllers/DebugController.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { Controller } from "../../core/controllers/Controller";
|
||||
import { Property } from "../../core/observable/property/Property";
|
||||
import { ListProperty } from "../../core/observable/property/list/ListProperty";
|
||||
import { QuestEditorStore } from "../stores/QuestEditorStore";
|
||||
import { GuiStore, GuiTool } from "../../core/stores/GuiStore";
|
||||
import { LogEntry } from "../../core/Logger";
|
||||
import { LogStore } from "../stores/LogStore";
|
||||
import { Severity } from "../../core/Severity";
|
||||
import { property } from "../../core/observable";
|
||||
|
||||
export class DebugController extends Controller {
|
||||
readonly can_debug: Property<boolean>;
|
||||
readonly can_step: Property<boolean>;
|
||||
readonly can_stop: Property<boolean>;
|
||||
readonly thread_ids: ListProperty<number>;
|
||||
readonly debugging_thread_id: Property<number | undefined>;
|
||||
readonly active_thread_id: Property<number | undefined>;
|
||||
readonly can_select_thread: Property<boolean>;
|
||||
readonly log: ListProperty<LogEntry>;
|
||||
readonly severity: Property<Severity>;
|
||||
|
||||
constructor(
|
||||
gui_store: GuiStore,
|
||||
private readonly quest_editor_store: QuestEditorStore,
|
||||
private readonly log_store: LogStore,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.can_debug = quest_editor_store.current_quest.map(q => q != undefined);
|
||||
|
||||
this.can_step = quest_editor_store.quest_runner.paused;
|
||||
|
||||
this.can_stop = quest_editor_store.quest_runner.running;
|
||||
|
||||
this.thread_ids = quest_editor_store.quest_runner.thread_ids;
|
||||
|
||||
this.debugging_thread_id = quest_editor_store.quest_runner.debugging_thread_id;
|
||||
|
||||
this.active_thread_id = quest_editor_store.quest_runner.active_thread_id;
|
||||
|
||||
this.can_select_thread = quest_editor_store.quest_runner.thread_ids.map(
|
||||
ids => ids.length > 0 && quest_editor_store.quest_runner.running.val,
|
||||
);
|
||||
|
||||
this.log = log_store.log;
|
||||
this.severity = log_store.severity;
|
||||
|
||||
this.disposables(
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "F5", this.debug),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "Shift-F5", this.stop),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "F6", this.resume),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "F8", this.step_over),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "F7", this.step_in),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "Shift-F8", this.step_out),
|
||||
);
|
||||
}
|
||||
|
||||
debug = (): void => {
|
||||
const quest = this.quest_editor_store.current_quest.val;
|
||||
|
||||
if (quest) {
|
||||
this.quest_editor_store.quest_runner.run(quest);
|
||||
}
|
||||
};
|
||||
|
||||
resume = (): void => {
|
||||
this.quest_editor_store.quest_runner.resume();
|
||||
};
|
||||
|
||||
step_over = (): void => {
|
||||
this.quest_editor_store.quest_runner.step_over();
|
||||
};
|
||||
|
||||
step_in = (): void => {
|
||||
this.quest_editor_store.quest_runner.step_into();
|
||||
};
|
||||
|
||||
step_out = (): void => {
|
||||
this.quest_editor_store.quest_runner.step_out();
|
||||
};
|
||||
|
||||
stop = (): void => {
|
||||
this.quest_editor_store.quest_runner.stop();
|
||||
};
|
||||
|
||||
set_severity = (severity: Severity): void => {
|
||||
this.log_store.set_severity(severity);
|
||||
};
|
||||
|
||||
select_thread = (thread_id: number): void => {
|
||||
this.quest_editor_store.quest_runner.set_debugging_thread(thread_id);
|
||||
};
|
||||
}
|
@ -1,62 +1,26 @@
|
||||
import { GuiStore } from "../../core/stores/GuiStore";
|
||||
import { create_area_store } from "../../../test/src/quest_editor/stores/store_creation";
|
||||
import { QuestEditorStore } from "../stores/QuestEditorStore";
|
||||
import {
|
||||
create_area_store,
|
||||
create_quest_editor_store,
|
||||
} from "../../../test/src/quest_editor/stores/store_creation";
|
||||
import { QuestEditorToolBarController } from "./QuestEditorToolBarController";
|
||||
import { Episode } from "../../core/data_formats/parsing/quest/Episode";
|
||||
import { next_animation_frame } from "../../../test/src/utils";
|
||||
import { with_disposer } from "../../../test/src/core/observables/disposable_helpers";
|
||||
|
||||
test("Some widgets should only be enabled when a quest is loaded.", async () =>
|
||||
with_disposer(async disposer => {
|
||||
const gui_store = disposer.add(new GuiStore());
|
||||
const area_store = create_area_store(disposer);
|
||||
const quest_editor_store = disposer.add(new QuestEditorStore(gui_store, area_store));
|
||||
const quest_editor_store = create_quest_editor_store(disposer, area_store);
|
||||
const ctrl = disposer.add(
|
||||
new QuestEditorToolBarController(gui_store, area_store, quest_editor_store),
|
||||
);
|
||||
|
||||
expect(ctrl.can_save.val).toBe(false);
|
||||
expect(ctrl.can_debug.val).toBe(false);
|
||||
expect(ctrl.can_select_area.val).toBe(false);
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
|
||||
await ctrl.create_new_quest(Episode.I);
|
||||
|
||||
expect(ctrl.can_save.val).toBe(true);
|
||||
expect(ctrl.can_debug.val).toBe(true);
|
||||
expect(ctrl.can_select_area.val).toBe(true);
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
}));
|
||||
|
||||
test("Debugging controls should be enabled and disabled at the right times.", async () =>
|
||||
with_disposer(async disposer => {
|
||||
const gui_store = disposer.add(new GuiStore());
|
||||
const area_store = create_area_store(disposer);
|
||||
const quest_editor_store = disposer.add(new QuestEditorStore(gui_store, area_store));
|
||||
const ctrl = disposer.add(
|
||||
new QuestEditorToolBarController(gui_store, area_store, quest_editor_store),
|
||||
);
|
||||
|
||||
await ctrl.create_new_quest(Episode.I);
|
||||
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
expect(ctrl.can_stop.val).toBe(false);
|
||||
|
||||
ctrl.debug();
|
||||
await next_animation_frame();
|
||||
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
expect(ctrl.can_stop.val).toBe(true);
|
||||
|
||||
ctrl.stop();
|
||||
|
||||
expect(ctrl.can_step.val).toBe(false);
|
||||
expect(ctrl.can_stop.val).toBe(false);
|
||||
|
||||
quest_editor_store.quest_runner.set_breakpoint(5);
|
||||
ctrl.debug();
|
||||
await next_animation_frame();
|
||||
|
||||
expect(ctrl.can_step.val).toBe(true);
|
||||
expect(ctrl.can_stop.val).toBe(true);
|
||||
}));
|
||||
|
@ -24,7 +24,6 @@ import { Version } from "../../core/data_formats/parsing/quest/Version";
|
||||
import { WritableProperty } from "../../core/observable/property/WritableProperty";
|
||||
import { failure, Result } from "../../core/Result";
|
||||
import { Severity } from "../../core/Severity";
|
||||
import { ListProperty } from "../../core/observable/property/list/ListProperty";
|
||||
|
||||
const logger = LogManager.get("quest_editor/controllers/QuestEditorToolBarController");
|
||||
|
||||
@ -45,20 +44,12 @@ export class QuestEditorToolBarController extends Controller {
|
||||
readonly result_problems_message: Property<string> = this._result_problems_message;
|
||||
readonly result_error_message: Property<string> = this._result_error_message;
|
||||
|
||||
readonly vm_feature_active: boolean;
|
||||
readonly areas: Property<readonly AreaAndLabel[]>;
|
||||
readonly current_area: Property<AreaAndLabel>;
|
||||
readonly can_save: Property<boolean>;
|
||||
readonly can_undo: Property<boolean>;
|
||||
readonly can_redo: Property<boolean>;
|
||||
readonly can_select_area: Property<boolean>;
|
||||
readonly can_debug: Property<boolean>;
|
||||
readonly can_step: Property<boolean>;
|
||||
readonly can_stop: Property<boolean>;
|
||||
readonly thread_ids: ListProperty<number>;
|
||||
readonly debugging_thread_id: Property<number | undefined>;
|
||||
readonly active_thread_id: Property<number | undefined>;
|
||||
readonly can_select_thread: Property<boolean>;
|
||||
readonly save_as_dialog_visible: Property<boolean> = this._save_as_dialog_visible;
|
||||
readonly filename: Property<string> = this._filename;
|
||||
readonly version: Property<Version> = this._version;
|
||||
@ -70,8 +61,6 @@ export class QuestEditorToolBarController extends Controller {
|
||||
) {
|
||||
super();
|
||||
|
||||
this.vm_feature_active = gui_store.feature_active("vm");
|
||||
|
||||
// Ensure the areas list is updated when entities are added or removed (the count in the
|
||||
// label should update).
|
||||
this.areas = quest_editor_store.current_quest.flat_map(quest => {
|
||||
@ -102,7 +91,6 @@ export class QuestEditorToolBarController extends Controller {
|
||||
const quest_loaded = quest_editor_store.current_quest.map(q => q != undefined);
|
||||
this.can_save = quest_loaded;
|
||||
this.can_select_area = quest_loaded;
|
||||
this.can_debug = quest_loaded;
|
||||
|
||||
this.can_undo = map(
|
||||
(c, r) => c && !r,
|
||||
@ -116,17 +104,6 @@ export class QuestEditorToolBarController extends Controller {
|
||||
quest_editor_store.quest_runner.running,
|
||||
);
|
||||
|
||||
this.can_step = quest_editor_store.quest_runner.paused;
|
||||
|
||||
this.can_stop = quest_editor_store.quest_runner.running;
|
||||
|
||||
this.thread_ids = quest_editor_store.quest_runner.thread_ids;
|
||||
this.debugging_thread_id = quest_editor_store.quest_runner.debugging_thread_id;
|
||||
this.active_thread_id = quest_editor_store.quest_runner.active_thread_id;
|
||||
this.can_select_thread = quest_editor_store.quest_runner.thread_ids.map(
|
||||
ids => ids.length > 0 && quest_editor_store.quest_runner.running.val,
|
||||
);
|
||||
|
||||
this.disposables(
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "Ctrl-O", async () => {
|
||||
const files = await open_files({ accept: ".bin, .dat, .qst", multiple: true });
|
||||
@ -146,18 +123,6 @@ export class QuestEditorToolBarController extends Controller {
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "Ctrl-Y", () => {
|
||||
undo_manager.redo();
|
||||
}),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "F5", this.debug),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "Shift-F5", this.stop),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "F6", this.resume),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "F8", this.step_over),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "F7", this.step_in),
|
||||
|
||||
gui_store.on_global_keydown(GuiTool.QuestEditor, "Shift-F8", this.step_out),
|
||||
);
|
||||
}
|
||||
|
||||
@ -272,42 +237,10 @@ export class QuestEditorToolBarController extends Controller {
|
||||
}
|
||||
};
|
||||
|
||||
debug = (): void => {
|
||||
const quest = this.quest_editor_store.current_quest.val;
|
||||
|
||||
if (quest) {
|
||||
this.quest_editor_store.quest_runner.run(quest);
|
||||
}
|
||||
};
|
||||
|
||||
resume = (): void => {
|
||||
this.quest_editor_store.quest_runner.resume();
|
||||
};
|
||||
|
||||
step_over = (): void => {
|
||||
this.quest_editor_store.quest_runner.step_over();
|
||||
};
|
||||
|
||||
step_in = (): void => {
|
||||
this.quest_editor_store.quest_runner.step_into();
|
||||
};
|
||||
|
||||
step_out = (): void => {
|
||||
this.quest_editor_store.quest_runner.step_out();
|
||||
};
|
||||
|
||||
stop = (): void => {
|
||||
this.quest_editor_store.quest_runner.stop();
|
||||
};
|
||||
|
||||
dismiss_result_dialog = (): void => {
|
||||
this._result_dialog_visible.val = false;
|
||||
};
|
||||
|
||||
select_thread = (thread_id: number): void => {
|
||||
this.quest_editor_store.quest_runner.set_debugging_thread(thread_id);
|
||||
};
|
||||
|
||||
private set_result(result: Result<unknown>): void {
|
||||
this._result.val = result;
|
||||
|
||||
|
48
src/quest_editor/gui/DebugView.css
Normal file
48
src/quest_editor/gui/DebugView.css
Normal file
@ -0,0 +1,48 @@
|
||||
.quest_editor_DebugView {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.quest_editor_DebugView_severity {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.quest_editor_DebugView_list_container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
background-color: #181818;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.quest_editor_DebugView_message_list {
|
||||
font-family: monospace;
|
||||
margin: 2px 0;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.quest_editor_DebugView_message {
|
||||
display: flex;
|
||||
padding: 0 2px;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.quest_editor_DebugView_message > * {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.quest_editor_DebugView_message > .quest_editor_DebugView_message_timestamp {
|
||||
color: var(--text-color-disabled);
|
||||
}
|
||||
|
||||
.quest_editor_DebugView_message > .quest_editor_DebugView_message_contents {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.quest_editor_DebugView .quest_editor_DebugView_Error_message .quest_editor_DebugView_message_severity {
|
||||
color: hsl(0, 80%, 50%);
|
||||
}
|
||||
|
||||
.quest_editor_DebugView .quest_editor_DebugView_Warning_message .quest_editor_DebugView_message_severity {
|
||||
color: hsl(30, 80%, 50%);
|
||||
}
|
175
src/quest_editor/gui/DebugView.ts
Normal file
175
src/quest_editor/gui/DebugView.ts
Normal file
@ -0,0 +1,175 @@
|
||||
import { bind_children_to, div, Icon } from "../../core/gui/dom";
|
||||
import { ToolBar } from "../../core/gui/ToolBar";
|
||||
import "./DebugView.css";
|
||||
import { Select } from "../../core/gui/Select";
|
||||
import { LogEntry, time_to_string } from "../../core/Logger";
|
||||
import { ResizableView } from "../../core/gui/ResizableView";
|
||||
import { Severities, Severity } from "../../core/Severity";
|
||||
import { Button } from "../../core/gui/Button";
|
||||
import { DebugController } from "../controllers/DebugController";
|
||||
|
||||
const AUTOSCROLL_TRESHOLD = 5;
|
||||
|
||||
export class DebugView extends ResizableView {
|
||||
readonly element: HTMLElement;
|
||||
|
||||
// container is needed to get a scrollbar in the right place
|
||||
private readonly list_container: HTMLElement;
|
||||
private readonly list_element: HTMLElement;
|
||||
|
||||
private readonly settings_bar: ToolBar;
|
||||
|
||||
private should_scroll_to_bottom = true;
|
||||
|
||||
constructor(ctrl: DebugController) {
|
||||
super();
|
||||
|
||||
const debug_button = new Button({
|
||||
text: "Debug",
|
||||
icon_left: Icon.Play,
|
||||
tooltip: "Debug the current quest in a virtual machine (F5)",
|
||||
});
|
||||
const resume_button = new Button({
|
||||
text: "Continue",
|
||||
icon_left: Icon.SquareArrowRight,
|
||||
tooltip: "Resume execution (F6)",
|
||||
});
|
||||
const step_over_button = new Button({
|
||||
text: "Step over",
|
||||
icon_left: Icon.LongArrowRight,
|
||||
tooltip: "Execute the next line and step over any function calls (F8)",
|
||||
});
|
||||
const step_in_button = new Button({
|
||||
text: "Step into",
|
||||
icon_left: Icon.LevelDown,
|
||||
tooltip: "Execute the next line and step inside any function calls (F7)",
|
||||
});
|
||||
const step_out_button = new Button({
|
||||
text: "Step out",
|
||||
icon_left: Icon.LevelUp,
|
||||
tooltip: "Execute until outside of current call frame (Shift-F8)",
|
||||
});
|
||||
const stop_button = new Button({
|
||||
text: "Stop",
|
||||
icon_left: Icon.Stop,
|
||||
tooltip: "Stop execution (Shift-F5)",
|
||||
});
|
||||
const severity_filter = new Select({
|
||||
class: "quest_editor_DebugView_severity",
|
||||
label: "Severity:",
|
||||
items: Severities,
|
||||
selected: ctrl.severity,
|
||||
to_label: severity => Severity[severity],
|
||||
});
|
||||
// TODO: ensure label is up-to-date.
|
||||
const thread_select = new Select({
|
||||
label: "Thread:",
|
||||
items: ctrl.thread_ids,
|
||||
to_label: id => {
|
||||
const status = ctrl.active_thread_id.val === id ? "Active" : "Yielded";
|
||||
return `Thread #${id} (${status})`;
|
||||
},
|
||||
});
|
||||
|
||||
this.settings_bar = this.add(
|
||||
new ToolBar(
|
||||
{ class: "quest_editor_DebugView_settings" },
|
||||
debug_button,
|
||||
resume_button,
|
||||
step_over_button,
|
||||
step_in_button,
|
||||
step_out_button,
|
||||
stop_button,
|
||||
severity_filter,
|
||||
thread_select,
|
||||
),
|
||||
);
|
||||
|
||||
this.list_element = div({ className: "quest_editor_DebugView_message_list" });
|
||||
|
||||
this.list_container = div(
|
||||
{ className: "quest_editor_DebugView_list_container" },
|
||||
this.list_element,
|
||||
);
|
||||
|
||||
this.element = div(
|
||||
{
|
||||
className: "quest_editor_DebugView",
|
||||
tabIndex: -1,
|
||||
},
|
||||
this.settings_bar.element,
|
||||
this.list_container,
|
||||
);
|
||||
|
||||
this.list_container.addEventListener("scroll", this.scrolled);
|
||||
|
||||
this.disposables(
|
||||
bind_children_to(this.list_element, ctrl.log, this.create_message_element, {
|
||||
after: this.scroll_to_bottom,
|
||||
}),
|
||||
|
||||
debug_button.onclick.observe(ctrl.debug),
|
||||
debug_button.enabled.bind_to(ctrl.can_debug),
|
||||
|
||||
resume_button.onclick.observe(ctrl.resume),
|
||||
resume_button.enabled.bind_to(ctrl.can_step),
|
||||
|
||||
step_over_button.onclick.observe(ctrl.step_over),
|
||||
step_over_button.enabled.bind_to(ctrl.can_step),
|
||||
|
||||
step_in_button.onclick.observe(ctrl.step_in),
|
||||
step_in_button.enabled.bind_to(ctrl.can_step),
|
||||
|
||||
step_out_button.onclick.observe(ctrl.step_out),
|
||||
step_out_button.enabled.bind_to(ctrl.can_step),
|
||||
|
||||
stop_button.onclick.observe(ctrl.stop),
|
||||
stop_button.enabled.bind_to(ctrl.can_stop),
|
||||
|
||||
severity_filter.selected.observe(
|
||||
({ value }) => value != undefined && ctrl.set_severity(value),
|
||||
),
|
||||
|
||||
thread_select.selected.observe(({ value }) => ctrl.select_thread(value!)),
|
||||
thread_select.selected.bind_to(ctrl.debugging_thread_id),
|
||||
thread_select.enabled.bind_to(ctrl.can_select_thread),
|
||||
);
|
||||
|
||||
this.finalize_construction();
|
||||
}
|
||||
|
||||
private scrolled = (): void => {
|
||||
this.should_scroll_to_bottom =
|
||||
this.list_container.scrollTop >=
|
||||
this.list_container.scrollHeight -
|
||||
this.list_container.offsetHeight -
|
||||
AUTOSCROLL_TRESHOLD;
|
||||
};
|
||||
|
||||
private scroll_to_bottom = (): void => {
|
||||
if (this.should_scroll_to_bottom) {
|
||||
this.list_container.scrollTo({
|
||||
top: this.list_container.scrollHeight,
|
||||
left: 0,
|
||||
behavior: "auto",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private create_message_element = ({ time, severity, message }: LogEntry): HTMLElement => {
|
||||
return div(
|
||||
{
|
||||
className: [
|
||||
"quest_editor_DebugView_message",
|
||||
"quest_editor_DebugView_" + Severity[severity] + "_message",
|
||||
].join(" "),
|
||||
},
|
||||
div({ className: "quest_editor_DebugView_message_timestamp" }, time_to_string(time)),
|
||||
div(
|
||||
{ className: "quest_editor_DebugView_message_severity" },
|
||||
`[${Severity[severity]}]`,
|
||||
),
|
||||
div({ className: "quest_editor_DebugView_message_contents" }, message),
|
||||
);
|
||||
};
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
.quest_editor_LogView {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.quest_editor_LogView_list_container {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
background-color: #181818;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.quest_editor_LogView_message_list {
|
||||
font-family: monospace;
|
||||
margin: 2px 0;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.quest_editor_LogView_message {
|
||||
display: flex;
|
||||
padding: 0 2px;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.quest_editor_LogView_message > * {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.quest_editor_LogView_message > .quest_editor_LogView_message_timestamp {
|
||||
color: var(--text-color-disabled);
|
||||
}
|
||||
|
||||
.quest_editor_LogView_message > .quest_editor_LogView_message_contents {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.quest_editor_LogView .quest_editor_LogView_Error_message .quest_editor_LogView_message_level {
|
||||
color: hsl(0, 80%, 50%);
|
||||
}
|
||||
|
||||
.quest_editor_LogView .quest_editor_LogView_Warning_message .quest_editor_LogView_message_level {
|
||||
color: hsl(30, 80%, 50%);
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
import { bind_children_to, div } from "../../core/gui/dom";
|
||||
import { ToolBar } from "../../core/gui/ToolBar";
|
||||
import "./LogView.css";
|
||||
import { log_store } from "../stores/LogStore";
|
||||
import { Select } from "../../core/gui/Select";
|
||||
import { LogEntry, time_to_string } from "../../core/Logger";
|
||||
import { ResizableView } from "../../core/gui/ResizableView";
|
||||
import { Severities, Severity } from "../../core/Severity";
|
||||
|
||||
const AUTOSCROLL_TRESHOLD = 5;
|
||||
|
||||
export class LogView extends ResizableView {
|
||||
readonly element = div({ className: "quest_editor_LogView", tabIndex: -1 });
|
||||
|
||||
// container is needed to get a scrollbar in the right place
|
||||
private readonly list_container: HTMLElement;
|
||||
private readonly list_element: HTMLElement;
|
||||
|
||||
private readonly level_filter: Select<Severity>;
|
||||
private readonly settings_bar: ToolBar;
|
||||
|
||||
private should_scroll_to_bottom = true;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.list_container = div({ className: "quest_editor_LogView_list_container" });
|
||||
this.list_element = div({ className: "quest_editor_LogView_message_list" });
|
||||
|
||||
this.level_filter = this.add(
|
||||
new Select({
|
||||
class: "quest_editor_LogView_level_filter",
|
||||
label: "Level:",
|
||||
items: Severities,
|
||||
to_label: level => Severity[level],
|
||||
}),
|
||||
);
|
||||
|
||||
this.settings_bar = this.add(
|
||||
new ToolBar({ class: "quest_editor_LogView_settings" }, this.level_filter),
|
||||
);
|
||||
|
||||
this.list_container.addEventListener("scroll", this.scrolled);
|
||||
|
||||
this.disposables(
|
||||
bind_children_to(this.list_element, log_store.log, this.create_message_element, {
|
||||
after: this.scroll_to_bottom,
|
||||
}),
|
||||
|
||||
this.level_filter.selected.observe(
|
||||
({ value }) => value != undefined && log_store.set_severity(value),
|
||||
),
|
||||
|
||||
log_store.severity.observe(
|
||||
({ value }) => {
|
||||
this.level_filter.selected.val = value;
|
||||
},
|
||||
{ call_now: true },
|
||||
),
|
||||
);
|
||||
|
||||
this.list_container.appendChild(this.list_element);
|
||||
this.element.appendChild(this.settings_bar.element);
|
||||
this.element.appendChild(this.list_container);
|
||||
|
||||
this.finalize_construction();
|
||||
}
|
||||
|
||||
private scrolled = (): void => {
|
||||
this.should_scroll_to_bottom =
|
||||
this.list_container.scrollTop >=
|
||||
this.list_container.scrollHeight -
|
||||
this.list_container.offsetHeight -
|
||||
AUTOSCROLL_TRESHOLD;
|
||||
};
|
||||
|
||||
private scroll_to_bottom = (): void => {
|
||||
if (this.should_scroll_to_bottom) {
|
||||
this.list_container.scrollTo({
|
||||
top: this.list_container.scrollHeight,
|
||||
left: 0,
|
||||
behavior: "auto",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private create_message_element = ({ time, severity, message }: LogEntry): HTMLElement => {
|
||||
return div(
|
||||
{
|
||||
className: [
|
||||
"quest_editor_LogView_message",
|
||||
"quest_editor_LogView_" + Severity[severity] + "_message",
|
||||
].join(" "),
|
||||
},
|
||||
div({ className: "quest_editor_LogView_message_timestamp" }, time_to_string(time)),
|
||||
div({ className: "quest_editor_LogView_message_level" }, `[${Severity[severity]}]`),
|
||||
div({ className: "quest_editor_LogView_message_contents" }, message),
|
||||
);
|
||||
};
|
||||
}
|
@ -4,12 +4,16 @@ import { GuiStore } from "../../core/stores/GuiStore";
|
||||
import { create_area_store } from "../../../test/src/quest_editor/stores/store_creation";
|
||||
import { QuestEditorStore } from "../stores/QuestEditorStore";
|
||||
import { with_disposer } from "../../../test/src/core/observables/disposable_helpers";
|
||||
import { LogStore } from "../stores/LogStore";
|
||||
|
||||
test("Renders correctly.", () =>
|
||||
with_disposer(disposer => {
|
||||
const gui_store = disposer.add(new GuiStore());
|
||||
const area_store = create_area_store(disposer);
|
||||
const quest_editor_store = disposer.add(new QuestEditorStore(gui_store, area_store));
|
||||
const log_store = disposer.add(new LogStore());
|
||||
const quest_editor_store = disposer.add(
|
||||
new QuestEditorStore(gui_store, area_store, log_store),
|
||||
);
|
||||
const tool_bar = disposer.add(
|
||||
new QuestEditorToolBarView(
|
||||
disposer.add(
|
||||
|
@ -16,7 +16,6 @@ import { TextInput } from "../../core/gui/TextInput";
|
||||
import "./QuestEditorToolBarView.css";
|
||||
import { Version } from "../../core/data_formats/parsing/quest/Version";
|
||||
import { ResultDialog } from "../../core/gui/ResultDialog";
|
||||
import { Widget } from "../../core/gui/Widget";
|
||||
|
||||
export class QuestEditorToolBarView extends View {
|
||||
private readonly toolbar: ToolBar;
|
||||
@ -72,36 +71,6 @@ export class QuestEditorToolBarView extends View {
|
||||
items: ctrl.areas,
|
||||
to_label: ({ label }) => label,
|
||||
});
|
||||
const debug_button = new Button({
|
||||
text: "Debug",
|
||||
icon_left: Icon.Play,
|
||||
tooltip: "Debug the current quest in a virtual machine (F5)",
|
||||
});
|
||||
const resume_button = new Button({
|
||||
text: "Continue",
|
||||
icon_left: Icon.SquareArrowRight,
|
||||
tooltip: "Resume execution (F6)",
|
||||
});
|
||||
const step_over_button = new Button({
|
||||
text: "Step over",
|
||||
icon_left: Icon.LongArrowRight,
|
||||
tooltip: "Execute the next line and step over any function calls (F8)",
|
||||
});
|
||||
const step_in_button = new Button({
|
||||
text: "Step into",
|
||||
icon_left: Icon.LevelDown,
|
||||
tooltip: "Execute the next line and step inside any function calls (F7)",
|
||||
});
|
||||
const step_out_button = new Button({
|
||||
text: "Step out",
|
||||
icon_left: Icon.LevelUp,
|
||||
tooltip: "Execute until outside of current call frame (Shift-F8)",
|
||||
});
|
||||
const stop_button = new Button({
|
||||
text: "Stop",
|
||||
icon_left: Icon.Stop,
|
||||
tooltip: "Stop execution (Shift-F5)",
|
||||
});
|
||||
const dialog = this.disposable(
|
||||
new ResultDialog({
|
||||
visible: ctrl.result_dialog_visible,
|
||||
@ -110,39 +79,18 @@ export class QuestEditorToolBarView extends View {
|
||||
error_message: ctrl.result_error_message,
|
||||
}),
|
||||
);
|
||||
const thread_select = this.disposable(
|
||||
new Select({
|
||||
items: ctrl.thread_ids,
|
||||
to_label: id => {
|
||||
const status = ctrl.active_thread_id.val === id ? "Active" : "Yielded";
|
||||
return `Thread #${id} (${status})`;
|
||||
},
|
||||
}),
|
||||
|
||||
this.toolbar = this.disposable(
|
||||
new ToolBar(
|
||||
new_quest_button,
|
||||
open_file_button,
|
||||
save_as_button,
|
||||
undo_button,
|
||||
redo_button,
|
||||
area_select,
|
||||
),
|
||||
);
|
||||
|
||||
const children: Widget[] = [
|
||||
new_quest_button,
|
||||
open_file_button,
|
||||
save_as_button,
|
||||
undo_button,
|
||||
redo_button,
|
||||
area_select,
|
||||
];
|
||||
|
||||
if (ctrl.vm_feature_active) {
|
||||
children.push(
|
||||
debug_button,
|
||||
resume_button,
|
||||
step_over_button,
|
||||
step_in_button,
|
||||
step_out_button,
|
||||
stop_button,
|
||||
thread_select,
|
||||
);
|
||||
}
|
||||
|
||||
this.toolbar = this.disposable(new ToolBar(...children));
|
||||
|
||||
// "Save As" dialog.
|
||||
const filename_input = this.disposable(
|
||||
new TextInput(ctrl.filename.val, { label: "File name:" }),
|
||||
@ -222,30 +170,6 @@ export class QuestEditorToolBarView extends View {
|
||||
area_select.selected.observe(({ value }) => ctrl.set_area(value!)),
|
||||
area_select.enabled.bind_to(ctrl.can_select_area),
|
||||
|
||||
debug_button.onclick.observe(ctrl.debug),
|
||||
debug_button.enabled.bind_to(ctrl.can_debug),
|
||||
|
||||
resume_button.onclick.observe(ctrl.resume),
|
||||
resume_button.enabled.bind_to(ctrl.can_step),
|
||||
|
||||
step_over_button.onclick.observe(ctrl.step_over),
|
||||
step_over_button.enabled.bind_to(ctrl.can_step),
|
||||
|
||||
step_in_button.onclick.observe(ctrl.step_in),
|
||||
step_in_button.enabled.bind_to(ctrl.can_step),
|
||||
|
||||
step_out_button.onclick.observe(ctrl.step_out),
|
||||
step_out_button.enabled.bind_to(ctrl.can_step),
|
||||
|
||||
stop_button.onclick.observe(ctrl.stop),
|
||||
stop_button.enabled.bind_to(ctrl.can_stop),
|
||||
|
||||
thread_select.selected.observe(({ value }) => ctrl.select_thread(value!)),
|
||||
thread_select.selected.bind_to(
|
||||
ctrl.active_thread_id.map(() => ctrl.debugging_thread_id.val),
|
||||
),
|
||||
thread_select.enabled.bind_to(ctrl.can_select_thread),
|
||||
|
||||
dialog.ondismiss.observe(ctrl.dismiss_result_dialog),
|
||||
);
|
||||
|
||||
|
@ -12,7 +12,7 @@ import { NpcListView } from "./NpcListView";
|
||||
import { ObjectListView } from "./ObjectListView";
|
||||
import { EventsView } from "./EventsView";
|
||||
import { RegistersView } from "./RegistersView";
|
||||
import { LogView } from "./LogView";
|
||||
import { DebugView } from "./DebugView";
|
||||
import { QuestRunnerRendererView } from "./QuestRunnerRendererView";
|
||||
import { QuestEditorStore } from "../stores/QuestEditorStore";
|
||||
import { QuestEditorUiPersister } from "../persistence/QuestEditorUiPersister";
|
||||
@ -73,6 +73,7 @@ export class QuestEditorView extends ResizableView {
|
||||
create_object_list_view: () => ObjectListView,
|
||||
create_events_view: () => EventsView,
|
||||
create_quest_runner_renderer_view: () => QuestRunnerRendererView,
|
||||
create_debug_view: () => DebugView,
|
||||
create_registers_view: () => RegistersView,
|
||||
) {
|
||||
super();
|
||||
@ -133,7 +134,7 @@ export class QuestEditorView extends ResizableView {
|
||||
name: "quest_runner",
|
||||
create: create_quest_runner_renderer_view,
|
||||
});
|
||||
this.view_map.set(LogView, { name: "log_view", create: () => new LogView() });
|
||||
this.view_map.set(DebugView, { name: "log_view", create: create_debug_view });
|
||||
this.view_map.set(RegistersView, {
|
||||
name: "registers_view",
|
||||
create: create_registers_view,
|
||||
@ -369,9 +370,9 @@ export class QuestEditorView extends ResizableView {
|
||||
...(this.gui_store.feature_active("vm")
|
||||
? [
|
||||
{
|
||||
title: "Debug Log",
|
||||
title: "Debug",
|
||||
type: "component",
|
||||
componentName: this.view_map.get(LogView)!.name,
|
||||
componentName: this.view_map.get(DebugView)!.name,
|
||||
isClosable: false,
|
||||
},
|
||||
{
|
||||
|
@ -177,7 +177,7 @@ exports[`Renders correctly. 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="core_Menu"
|
||||
class="core_Menu disabled"
|
||||
hidden=""
|
||||
tabindex="-1"
|
||||
>
|
||||
|
@ -27,6 +27,9 @@ import { Disposable } from "../core/observable/Disposable";
|
||||
import { EntityInfoController } from "./controllers/EntityInfoController";
|
||||
import { NpcCountsController } from "./controllers/NpcCountsController";
|
||||
import { EventsController } from "./controllers/EventsController";
|
||||
import { DebugView } from "./gui/DebugView";
|
||||
import { DebugController } from "./controllers/DebugController";
|
||||
import { LogStore } from "./stores/LogStore";
|
||||
|
||||
export function initialize_quest_editor(
|
||||
http_client: HttpClient,
|
||||
@ -41,7 +44,8 @@ export function initialize_quest_editor(
|
||||
|
||||
// Stores
|
||||
const area_store = disposer.add(new AreaStore(area_asset_loader));
|
||||
const quest_editor_store = disposer.add(new QuestEditorStore(gui_store, area_store));
|
||||
const log_store = disposer.add(new LogStore());
|
||||
const quest_editor_store = disposer.add(new QuestEditorStore(gui_store, area_store, log_store));
|
||||
const asm_editor_store = disposer.add(new AsmEditorStore(quest_editor_store));
|
||||
|
||||
// Persisters
|
||||
@ -86,6 +90,10 @@ export function initialize_quest_editor(
|
||||
entity_asset_loader,
|
||||
create_three_renderer(),
|
||||
),
|
||||
() =>
|
||||
new DebugView(
|
||||
disposer.add(new DebugController(gui_store, quest_editor_store, log_store)),
|
||||
),
|
||||
() => new RegistersView(quest_editor_store.quest_runner),
|
||||
),
|
||||
);
|
||||
|
@ -1,21 +1,17 @@
|
||||
import { ListProperty } from "../../core/observable/property/list/ListProperty";
|
||||
import { Property } from "../../core/observable/property/Property";
|
||||
import { list_property, property } from "../../core/observable";
|
||||
import { Disposable } from "../../core/observable/Disposable";
|
||||
import { Disposer } from "../../core/observable/Disposer";
|
||||
import { LogEntry, Logger, LogHandler, LogManager } from "../../core/Logger";
|
||||
import { Severity } from "../../core/Severity";
|
||||
import { Store } from "../../core/stores/Store";
|
||||
|
||||
const logger = LogManager.get("quest_editor/stores/LogStore");
|
||||
|
||||
export class LogStore implements Disposable {
|
||||
private readonly disposer = new Disposer();
|
||||
private readonly default_log_severity = Severity.Info;
|
||||
|
||||
export class LogStore extends Store {
|
||||
private readonly log_buffer: LogEntry[] = [];
|
||||
private readonly logger_name_buffer: string[] = [];
|
||||
|
||||
private readonly _severity = property<Severity>(this.default_log_severity);
|
||||
private readonly _severity = property<Severity>(Severity.Info);
|
||||
private readonly _log = list_property<LogEntry>();
|
||||
|
||||
private readonly handler: LogHandler = (entry: LogEntry, logger_name: string): void => {
|
||||
@ -33,10 +29,6 @@ export class LogStore implements Disposable {
|
||||
return logger;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposer.dispose();
|
||||
}
|
||||
|
||||
set_severity(severity: Severity): void {
|
||||
this._severity.val = severity;
|
||||
}
|
||||
@ -101,5 +93,3 @@ export class LogStore implements Disposable {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const log_store = new LogStore();
|
||||
|
@ -15,6 +15,7 @@ import { disposable_listener } from "../../core/gui/dom";
|
||||
import { Store } from "../../core/stores/Store";
|
||||
import { LogManager } from "../../core/Logger";
|
||||
import { WaveModel } from "../model/WaveModel";
|
||||
import { LogStore } from "./LogStore";
|
||||
|
||||
const logger = LogManager.get("quest_editor/gui/QuestEditorStore");
|
||||
|
||||
@ -32,10 +33,10 @@ export class QuestEditorStore extends Store {
|
||||
readonly selected_wave: Property<WaveModel | undefined> = this._selected_wave;
|
||||
readonly selected_entity: Property<QuestEntityModel | undefined> = this._selected_entity;
|
||||
|
||||
constructor(gui_store: GuiStore, private readonly area_store: AreaStore) {
|
||||
constructor(gui_store: GuiStore, private readonly area_store: AreaStore, log_store: LogStore) {
|
||||
super();
|
||||
|
||||
this.quest_runner = new QuestRunner(area_store);
|
||||
this.quest_runner = new QuestRunner(area_store, log_store);
|
||||
|
||||
this.disposables(
|
||||
gui_store.tool.observe(
|
||||
|
@ -4,6 +4,7 @@ import { AreaStore } from "../../../../src/quest_editor/stores/AreaStore";
|
||||
import { AreaAssetLoader } from "../../../../src/quest_editor/loading/AreaAssetLoader";
|
||||
import { FileSystemHttpClient } from "../../core/FileSystemHttpClient";
|
||||
import { Disposer } from "../../../../src/core/observable/Disposer";
|
||||
import { LogStore } from "../../../../src/quest_editor/stores/LogStore";
|
||||
|
||||
export function create_area_store(disposer: Disposer): AreaStore {
|
||||
return disposer.add(
|
||||
@ -14,6 +15,7 @@ export function create_area_store(disposer: Disposer): AreaStore {
|
||||
export function create_quest_editor_store(
|
||||
disposer: Disposer,
|
||||
area_store: AreaStore = create_area_store(disposer),
|
||||
log_store: LogStore = new LogStore(),
|
||||
): QuestEditorStore {
|
||||
return disposer.add(new QuestEditorStore(disposer.add(new GuiStore()), area_store));
|
||||
return disposer.add(new QuestEditorStore(disposer.add(new GuiStore()), area_store, log_store));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user