dm2-gui: egui app shell + save editor (MVP) #303

Open
opened 2026-07-23 20:52:09 +02:00 by jqueuniet · 1 comment
Owner

Stand up a dm2-gui crate (egui) and build the first surface: a savegame editor on the dm2-saves edit API (champions, party, inventory, object/creature/door edits) - not a read-only viewer. Also lands the shared app shell (asset loading, file open) that the graphics and dungeon surfaces reuse. See docs/cli-save-editing.md.

Stand up a `dm2-gui` crate (egui) and build the first surface: a savegame **editor** on the `dm2-saves` edit API (champions, party, inventory, object/creature/door edits) - not a read-only viewer. Also lands the shared app shell (asset loading, file open) that the graphics and dungeon surfaces reuse. See docs/cli-save-editing.md.
jqueuniet added this to the dm2-tools project 2026-07-23 21:43:33 +02:00
Author
Owner

Architecture note: impose the edit discipline egui leaves optional

egui is the right framework for this crate — two of the three planned
surfaces (#304 graphics browser, #305 dungeon editor) are canvas-dominated,
and since they reuse this shell, the shell should sit in the framework that
makes custom rendering cheap. The one cost we take is that egui won't hand us
the message/update/undo structure a retained framework (iced) gives for free.
This surface is the form-heavy one, so it's worth deciding that structure up
front rather than growing frame-local state ad hoc.

Concretely, before building the save-editor forms:

  • Explicit AppState. Loaded asset handles, per-document dirty flags,
    and current selection live in one owned struct — not scattered across
    frame-local ui closures. The graphics/dungeon surfaces will hang their
    own document state off the same shell state.

  • A Command trait + undo/redo stack between the UI and the edit APIs.
    Every mutation (champion/party/inventory/object/creature/door edit) is a
    reified, reversible command applied through the stack, never a direct
    poke at the dm2-saves fields from a widget callback. This is the same
    "typed records + write-back" shape #305 already calls for, so a shared
    command/undo layer in the shell serves all three editors — the save editor
    is just the first consumer.

  • Write-back stays in the edit API, not the UI. The command's apply /
    revert call the existing dm2-saves edit surface (see
    docs/cli-save-editing.md); the GUI only builds and dispatches commands.
    Keeps the bit-exact re-encode path and its tests authoritative and shared
    with the CLI.

Suggested crates for the shell: egui_dock for the multi-panel layout,
egui_extras for the record/inventory tables.

Net: the shell (this issue) should land the AppState + Command/undo
scaffolding as first-class pieces, with the save editor as the first thing
built on top — not bolt undo on afterwards once #304/#305 also need it.

## Architecture note: impose the edit discipline egui leaves optional egui is the right framework for this crate — two of the three planned surfaces (#304 graphics browser, #305 dungeon editor) are canvas-dominated, and since they reuse *this* shell, the shell should sit in the framework that makes custom rendering cheap. The one cost we take is that egui won't hand us the message/update/undo structure a retained framework (iced) gives for free. This surface is the form-heavy one, so it's worth deciding that structure up front rather than growing frame-local state ad hoc. Concretely, before building the save-editor forms: - **Explicit `AppState`.** Loaded asset handles, per-document dirty flags, and current selection live in one owned struct — not scattered across frame-local `ui` closures. The graphics/dungeon surfaces will hang their own document state off the same shell state. - **A `Command` trait + undo/redo stack between the UI and the edit APIs.** Every mutation (champion/party/inventory/object/creature/door edit) is a reified, reversible command applied *through* the stack, never a direct poke at the `dm2-saves` fields from a widget callback. This is the same "typed records + write-back" shape #305 already calls for, so a shared command/undo layer in the shell serves all three editors — the save editor is just the first consumer. - **Write-back stays in the edit API, not the UI.** The command's `apply` / `revert` call the existing `dm2-saves` edit surface (see `docs/cli-save-editing.md`); the GUI only builds and dispatches commands. Keeps the bit-exact re-encode path and its tests authoritative and shared with the CLI. Suggested crates for the shell: `egui_dock` for the multi-panel layout, `egui_extras` for the record/inventory tables. Net: the shell (this issue) should land the `AppState` + `Command`/undo scaffolding as first-class pieces, with the save editor as the first thing built on top — not bolt undo on afterwards once #304/#305 also need it.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jqueuniet/dm2-tools#303
No description provided.