Extract kiln-ui crate

This commit is contained in:
2026-07-11 00:11:35 -05:00
parent ad95a9cd8d
commit cdeae455dc
17 changed files with 33 additions and 2380 deletions
+9 -3
View File
@@ -1,9 +1,11 @@
# kiln-tui
Module reference for the `kiln-tui` crate — a terminal **player + world
editor** built on **ratatui 0.30 / crossterm**, depending on both `kiln-core`
and `kiln-ui`. See the repository-root `CLAUDE.md` for project-wide guidance,
code style, the world file format, and key design decisions.
editor** built on **ratatui 0.30 / crossterm**, depending on `kiln-core`
and the external, game-agnostic **`kiln-ui`** widget crate (a git dependency:
`Dialog`/`CodeEditor`/`TextField`, plus `render_overlay`/`dim_area`/`CursorOverlay`).
See the repository-root `CLAUDE.md` for project-wide guidance, code style, the
world file format, and key design decisions.
Renders the board as text: each `Glyph.tile` index is reinterpreted as a character (the default kiln font is CP437, where the tile index equals the code point) and drawn with the glyph's RGB colors. No bitmap font or UV mapping is involved. The app is one of two top-level [`Mode`]s — `Play` (live, ticking game) or `Edit` (a freshly reloaded, non-ticking world) — and the active mode plus a `Ui` value are threaded through the loop.
@@ -27,6 +29,10 @@ Renders the board as text: each `Glyph.tile` index is reinterpreted as a charact
- Drawing: `set_current(arch)` sets `current_archetype` and resets `current_glyph` to its default; `open_glyph_picker()` seeds a `GlyphDialog` from `current_glyph` and writes the chosen glyph back (bound to **`g`**); `place_current()` stamps the current archetype+glyph at the cursor via `Board::place_archetype`; `toggle_draw_mode()` flips `draw_mode`. `place_current` is bound to **`space`** and `toggle_draw_mode` to **`tab`** in `handle_editor_input`; `move_cursor`/`set_cursor_at_screen` also call `place_current` when `draw_mode` is on and the cursor enters a new cell. The sidebar's bottom **drawing-controls footer** (`draw_footer_lines`) shows the archetype name, `[g] Glyph` + a live colored preview, `[spc] Place`, and `[tab] Draw mode (on/off)`.
- `editor_menu_items()` — the overlay editor menu (`[p]` play, `[q]` quit, `[esc]` resume), opened at the root of the menu tree. `handle_dialog_input(event, ed)` — forwards to the open dialog and, on `Submit`/`Cancel`, `take`s it out and calls `finish(.., ed)`. `handle_glyph_dialog_input(event, ed)` — the same pattern for the open `glyph_dialog`. `handle_code_editor_input(event, ed)` — forwards to the open code editor and, on `Exit` (Esc), calls `close_script_editor()`. `draw_editor(frame, ed, ui)` / `editor_layout(..)` — the **code editor (when open) else** the board (with blinking cursor + coord readout) in the left area, a resizable right-hand sidebar (breadcrumb title + the menu choices, each with its optional current-value line), and the optional full-width log panel.
**`kiln-tui/src/glyph_dialog.rs`** — the modal **glyph picker** (`GlyphDialog<Ctx>`):
- A modal picker for a `kiln_core::glyph::Glyph` (CP437 tile index + fg/bg colors), same API shape as `kiln_ui::dialog::Dialog`: `GlyphDialog::new(title, initial: Glyph, on_done)`, `handle_event(&Event) -> DialogResult`, `finish(result, &mut Ctx)`. A 32×8 char grid plus two `ColorPicker`s (a strip of the 16 `kiln_core::colors::NAMED_COLORS` swatches + a custom `#RRGGBB` `TextField` that is the source of truth). Draws via a `CursorOverlay` impl (host renders it through `kiln_ui::render_overlay`), rendering the grid with `kiln_core::cp437::tile_to_char`.
- **This is the one game-coupled UI widget.** It depends on `kiln-core` (`Glyph`/`Rgba8`, `NAMED_COLORS`, `tile_to_char`), so it lives here rather than in the game-agnostic external `kiln-ui` crate — it reuses `kiln-ui`'s public `DialogResult`, `TextField`, `CursorOverlay`, and `dim_area`. Seeded/read by the editor's `open_glyph_picker()` (bound to `g`); unit-tested with a dummy `Ctx`.
**`kiln-tui/src/ui.rs`** — front-end presentation state (not on `GameState`):
- `Ui { log: LogState, overlay: ScrollOverlayState, pending_transition, active_animation: Option<Box<dyn Animation>>, menu: Option<MenuState>, should_quit, world_path, pending_mode, suspended_editor: Option<EditorState>, exit_playtest: bool }` (the last two drive the editor playtest: the parked editor and its `Esc`-to-exit signal). While `active_animation` is `Some` all input is suppressed. `tick(dt, mode)` advances the active animation (and, on completion, clears scroll/menu state when returning to `Board`), then ticks the active mode — the game only in `Play` + `Board` input mode (so an open scroll/menu pauses it), the editor's cursor blink in `Edit`; a scroll that appears from a tick starts an open animation.
- `open_menu(items)` / `begin_close_menu()` — start the menu open/close animations (snapshotting `MenuState`). `begin_close(choice, game)` — set the player's scroll choice and start the scroll close animation. `start_transition(old, new, area)` — build the board-wipe once the inner area is known. `scroll_lines(delta)` / `scroll_menu(delta)` — clamped overlay/menu scrolling.