Files
sporel-module-map-editor/README.md
Calic 2734efa1a9 chore(map-editor): bump to v0.3.1; cheatsheet + README sync
Bumps the module version to v0.3.1 (lib-core.maps dep pin was
already bumped to 0.5.7 in CT6 to allow the editor to load).
Updates the file header, startup banner, cheatsheet Tab entry
(now mentions all three modes), and appends a Cell-Tile Mode
subsection to the README.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 23:10:30 +02:00

156 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# sporel-module-map-editor
Interactive map editor for Sporel `.map.json` files. v0.2 series ships
the Rev 4 UX architecture (see design paper
`design/2026-05-28-autotile-blob-styles-design.md` §11 in `sporel-meta`):
top toolbar with mode-switch + actions, right Layers side-panel, bottom
palette strip of material slot thumbnails, mouse drag-paint, and two
mutually-exclusive paint modes (Auto-Tile vs Direct).
## Run
Default — edit the module's in-place work map (`maps/work.map.json`,
a 16×16 schema-v3 map bound to the `blob_rect_stone` material):
```bash
bash scripts/run-map-editor.sh
```
With a target — copy a real map in, edit, copy back out:
```bash
bash scripts/run-map-editor.sh ~/Projects/Sporel/sporel-modules/spine-prototype/maps/demo.map.json
```
Or via the install layer (per `install-reference.sh`):
```text
Doubleclick C:/Games/Sporel/bin/Sporel.exe → launcher → map-editor
```
## UI
- **Top toolbar** (full-width): `Auto-Tile`/`Direct` mode buttons (mutually
exclusive, Tab toggles), `Save` (S), `Erase` (E), `Rotate` (R),
`Flip` (H), `Reset` (0), `Help` (I). Each button shows its hotkey
label inline. The active mode is highlighted.
- **Right Layers side-panel** (8 rows top-down: `canopy`, `upper_wall`,
`wall`, `lower_wall`, `topsurface`, `surface`, `subsurface`,
`foundation`). Per row: visibility eye + active marker + layer name.
- **Left-click name** → set active layer
- **Left-click eye** → toggle layer visibility
- **Right-click row** → also toggles visibility
- **Bottom palette strip**: 14 swatches (slots 1-14). Real tile
thumbnails rendered from the active atlas via
`maps.atlas_tile_uv`. Active slot has a gold border.
- **Left-click** → set active slot
- **Status chip** (bottom-left of palette band): mouse-cell, dirty flag
(`*` when unsaved), and current transform indicator
(`slot=N rot=N flip=N`) for Direct-mode awareness.
- **Auto-Tile-mode world overlay**: cell grid (1 px), vertex dots (4 px
squares), and a snapped-vertex highlight ring (green) at the nearest
vertex to the cursor.
- **Cheatsheet modal** (I): centered dim-overlay listing all hotkeys
+ LMB/RMB drag semantics.
## Modes
| Mode | LMB on canvas | RMB on canvas | Notes |
|---|---|---|---|
| **Auto-Tile** | Paints vertex at snap target — `maps.set_vertex(layer, vx, vy, true)`. Any-corner rule flips up to 4 surrounding cells to material; renderer derives slot/rot/flip from neighbour bitmask. | Clears vertex — `set_vertex(..., false)` | Transform controls ignored (slot is derived from neighbours). |
| **Direct** | Writes per-cell override — `maps.set_override(layer, x, y, {slot, rot, flip})`. Bare slot int when canonical (rot=0+flip=0). | Clears override — `maps.clear_override(layer, x, y)` | Honours active Rot/Flip from toolbar. Use to force-place a specific orientation that the auto-derived slot wouldn't pick. |
Both modes support **drag-paint**: hold LMB (or RMB) and stroke across
the canvas to apply the action at every hovered vertex/cell. UI hits
on the toolbar / side-panel / palette never enter drag-mode.
## Hotkeys
| Key | Action |
|---|---|
| `Tab` | Toggle mode (Auto-Tile ↔ Direct) |
| `I` | Show / hide cheatsheet |
| `S` | Save current map to `work.map.json` |
| `E` | Erase tile at mouse cell |
| `R` | Cycle rotation 0 → 1 → 2 → 3 → 0 (Direct-mode override) |
| `H` | Toggle flip 0 ↔ 1 (Direct-mode override) |
| `0` | Reset transform (rot=0, flip=0) |
| `Esc` | Quit |
| `LMB-drag` | Stroke-paint (mode-dependent) |
| `RMB-drag` | Stroke-clear |
## Headless / smoke
`ci_frames = 30` in `manifest.module`. The editor reads
`SPOREL_CI=1` and auto-exits after 30 frames so the smoke harness
can run it without a window-close click.
```bash
SPOREL_CI=1 ./Sporel.exe --module=map-editor # exits with rc=0 after ~0.5 s
```
## Limitations (current scope)
- **Single-atlas palette**: the palette draws from `atlas_idx=0` only.
Multi-atlas selector is a future slice. Workaround: keep one material
atlas per map for now.
- **Single Flip flag**: design paper mentions Flip-H + Flip-V as
separate controls, but the override format only stores one `flip`
field; combined with `rot` (0-3) the single flip covers all 8 D4
orientations, so the second button would be redundant.
- **No modifier hotkeys**: `lib-core.input` doesn't expose modifier
combos, so Shift+R for CCW rotation isn't supported. Workaround:
press R three times.
- **No Decal / Entity sub-selectors**: Direct mode on non-terrain
layers is unimplemented (lands in `0.2.0d`).
- **No Material-Properties modal**: `base_color` re-bake trigger
+ tint editor are deferred (also `0.2.0d`).
- **No multi-vertex brush sizes / procedural fill / undo-redo** — see
design paper §11 "Out of scope" for the full list.
## Plan + spec
- Design paper: `docs/design/2026-05-28-autotile-blob-styles-design.md`
§11 in `sporel-meta`
- Plan: `docs/superpowers/plans/2026-05-28-map-editor-blob-v2.md`
## Menu UI (v0.3.0)
Top toolbar replaced with a seven-category menu bar (File, Edit, View,
Map, Tools, Window, Help) plus a sticky two-segment Mode-pill on the
right end. Item types: action, modal, toggle, submenu, separator;
items can be conditionally disabled. A single-stack modal framework
hosts the existing Cheatsheet (I) and three new modals: Save As, Map
Properties (read-only), About. The Esc key cascades modal -> menu ->
quit.
New Map and Open Map appear in the File menu as disabled placeholders
pending a v3-aware maps.create and an engine.asset.list_dir in a
future engine + lib slice.
All previous hotkeys (Tab, S, E, R, H, 0, D, G, I, Esc) continue to
work; their bindings are documented in the items where applicable
and in the in-editor Cheatsheet modal.
## Cell-Tile Mode (v0.3.1)
Third painting mechanic alongside Auto-Tile and Direct. LMB paints a
per-cell material flag at the cursor cell; RMB clears it. The
renderer uses the classical 47-blob 8-neighbour bitmask for
cell-tile cells, unlocking the 9 atlas slots that Auto-Tile's
dual-grid 4-corner rule structurally cannot reach (isolated, end,
corner_open, straight, tee_open, tee_half, cross_open, cross_q1,
cross_q2adj).
Auto-Tile (vertex-paint, 5 reachable slots, dual-grid look) and
Direct (manual override placement, all 14 slots via explicit pick)
are unchanged. Tab cycles through all three modes.
For clean visuals, use a single painting mode per layer. Mixing
Vertex-Tile and Cell-Tile material in the same layer is allowed but
produces an asymmetric seam at the boundary because vertex-tile
cells are structurally blind to their cell-tile neighbours.
See `sporel-meta/docs/superpowers/specs/2026-06-01-map-editor-cell-tile-mode-design.md`
for the full design rationale and the Boris-taxonomy background.