Compare commits

...

30 Commits

Author SHA1 Message Date
calic
7c9e481a6c fix(deps): cascade composition 0.4.0 + crafting 0.5.0 pins
Phase J (2026-08-03) bumped lib-core.composition 0.3.0->0.4.0 and
lib-core.crafting 0.3.0->0.5.0, but only vagrant-skeleton and
lib-core.crafting themselves were updated. Dependent manifests kept the
old pins, so dep-fetcher saw disagreeing pins on the same lib and
refused to start both spine-prototype (ENGINE_ERR_LIB_DEP_MISSING,
rc=19) and vagrant-skeleton ("dep check failed", conflict on
lib-core.composition + lib-core.crafting).

Unify all pins on the on-disk versions. No code changes required:
composition 0.4.0 is purely additive (the quality/condition loud-error
was removed; no signature changed), and crafting-display only consumes
crafting.can_craft + crafting.list_recipes, both still present, and
never referenced the `form` field retired by ADR-0055.

README "Requires:" lines synced to match the manifests (Gate 3).

milestone-check.sh: GREEN (build, ctest, smoke, devwrap-ci,
test-all-modules + anomaly scan). vagrant-skeleton headless run clean
at 60 CI frames.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 11:27:22 +02:00
calic
f1cddc3948 chore(deps): bump lib-core.render to 0.3.0 (cascade — additive sprite_scale)
No code change. v0.3.0 adds an optional sprite_scale property on
draw_entities path-1; map-editor doesn't set it, so default 1.0
preserves v0.2.0 behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-21 11:44:28 +02:00
Calic
75655be72d docs: CR-5 — README+launcher-card auf v0.4.0 (3 Paint-Modi), Requires-Block ergaenzt
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:47:57 +00:00
Calic
4b8abc8502 chore: bump lib-core.panel dep to 0.4.0
Engine resolver does exact strcmp on dep versions, so consumer manifests
must pin the new lib-core.panel 0.4.0 to keep load-time resolution green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-15 03:05:30 +02:00
Calic
176305e35b feat: v0.4.0 migrate to lib-core.panel persistent widgets
Migrate the top toolbar, right-side Layers panel, and bottom palette
strip to lib-core.panel v0.3.0 persistent widgets (W.2 of the
panel-window-manager plan):

  map-editor.toolbar -- top strip (full width, ~290 px tall)
  map-editor.layers  -- right side-panel (160 px wide)
  map-editor.palette -- bottom strip (full width, 64 px tall)

All three registered as persistent=true (open from module-init, not
dismissed by ESC), input_block='self' (hit-test claims clicks within
own bounds; misses fall through to canvas), and chromeless=true
(panel-lib skips its title-bar/border/X — widgets keep their own
visual style).

Existing draw_menu_bar / draw_side_panel / draw_palette and
handle_click logic is wrapped via thin widget render + handle_input
fns (M.draw_toolbar_widget / M.handle_toolbar_click etc.); no
behavioural change to the widget interiors.

Map-canvas remains module-rendered. Canvas drag-paint is now gated on
panel.point_in_any_panel(mx, my) so widget clicks no longer bleed
through into map paint.

Removed state.show_layers_panel / show_palette and their toggle
helpers (panel-lib manages widget visibility; Window menu items now
flip panel.is_open/toggle on the widget ids directly). Modals stay
module-rendered + module-routed (handled by handle_modal_click
before panel.update).

Manifest bumped 0.3.4 -> 0.4.0; lib-core.panel dep added at 0.3.0.
2026-06-15 02:26:20 +02:00
Calic
a150dd8dc5 chore: bump lib-core.composition dep to 0.3.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 11:57:40 +02:00
Calic
61e7d5192f chore: bump lib-core.composition dep to 0.2.0 2026-06-13 14:07:46 +02:00
Calic
451da04cbd feat: ship manifest.launcher.md for master-detail launcher 2026-06-11 07:57:58 +02:00
Calic
bde1f7acfa chore(deps): bump lib-core.render 0.1.0 to 0.2.0, declare lib-core.composition
render 0.2.0 added a transitive dep on lib-core.composition.
Engine resolver is strict-strcmp (no semver expansion), so
consumers must declare every transitive lib in deps[].
2026-06-10 23:28:52 +02:00
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
Calic
340dd5f700 test(map-editor): t11 confirms Edit-menu disable covers Cell-Tile
The existing `disabled = function() return not mode_is("direct")
end` predicate already covers Cell-Tile mode (which is also
non-direct). Self-test t11 enumerates the three transform items
across all three modes and confirms each is disabled in
auto-tile AND cell-tile, enabled only in direct.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 23:07:31 +02:00
Calic
46d1e78758 feat(map-editor): world-overlay variant for Cell-Tile mode
draw_world_overlay gains a cell-tile branch that renders a faint
render-cell grid and a 1-px hover-cell outline around the cursor
cell. The existing G-toggle continues to gate the entire overlay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 23:05:22 +02:00
Calic
51138e257f feat(map-editor): paint actions + LMB/RMB routing for Cell-Tile
paint_cell_material_at and erase_cell_material_at wrap
maps.set_cell_material with a mark_dirty. The canvas-click
dispatch in M.handle_click and the per-frame drag handler both
route through these actions when state.mode == "cell-tile". Self-
test t10 confirms a paint round-trips through maps.get_cell_material.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 23:02:53 +02:00
Calic
6eacde3eaa feat(map-editor): mode-pill 3 segments for Auto/Cell/Direct
MODE_PILL_W widens 130 -> 195 (3 x 65). mode_pill_layout returns
the new cell segment between auto and direct; draw_mode_pill
iterates the new triple; the click-handler dispatches the cell
segment to actions.set_mode("cell-tile"). Self-test t9 confirms
the three segments sit at consecutive SEG_W offsets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 23:00:12 +02:00
Calic
e745be8d07 feat(map-editor): cell-tile as third state.mode + Tools menu entry
state.set_mode now accepts "cell-tile"; toggle_mode is renamed
cycle_mode (with a backwards-compat alias) and now advances
auto-tile -> cell-tile -> direct -> auto-tile. Tools > Mode
submenu gains a third entry between Auto-Tile and Direct.
Self-test gains t8 (set/get round-trip) and t12 (cycle order).
Startup banner updated to "Tab=cycle mode". Manifest dep pin
bumped to lib-core.maps 0.5.7 to match installed version.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 22:56:04 +02:00
Calic
f06ef5e2cb test(map-editor): seven menu-UI assertions on first CI frame
Adds a self_test() entry-point that the editor invokes once when
SPOREL_CI=1 is set, exercising the seven §7.1 acceptance checks
from the menu-UI spec: open/close, toggle flip, modal absorb,
disabled-item no-op, mode switch, category switch, and layer
visibility submenu round-trip. Any failed engine.test assertion
exits with non-zero.

Fixes cheatsheet modal on_click to close only on inside-bounds
click (was closing on any click, breaking t3 outside-click-absorb
assertion).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 20:14:29 +02:00
Calic
398d3b4dd9 chore(map-editor): bump to v0.3.0; cheatsheet + README sync
Updates the in-editor Cheatsheet to reflect the new G binding and
the Esc cascade; bumps manifest.module and the file header to
v0.3.0; adds a Menu UI section to README.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 20:10:32 +02:00
Calic
1945e91441 refactor(map-editor): retire legacy toolbar
Removes the eight-button top toolbar, its layout helpers, click
dispatcher and all TOOLBAR_* constants. Side-panel and palette
offsets now anchor to MENU_BAR_H. Mode-pill no longer overlaps a
parallel toolbar element.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 20:07:57 +02:00
Calic
107eade2fa feat(map-editor): wire Window toggles to hide side panel + palette
Both render and click handlers are now gated by the
is_layers_panel_shown / is_palette_shown predicates, so the new
Window menu toggles produce visible effects in the editor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 20:04:55 +02:00
Calic
f2123ba79c feat(map-editor): save_as, map_properties, about modals
Three new modal entries plugged into the unified modal stack.
save_as accepts a typed filename and writes via
maps.save_to_disk; map_properties shows current map id, size and
atlas list as a read-only inspector; about is static text only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 20:02:17 +02:00
Calic
9213d3f91b feat(map-editor): submenu support — View > Layers, Tools > Mode
One level of submenu nesting. View > Layers exposes all eight
terrain-stack layers as toggles, sharing state with the right-side
Layers panel. Tools > Mode mirrors the Mode-pill's auto/direct
toggle with a Tab hotkey shown on Direct. Submenu opens by clicking
the parent item; clicking elsewhere closes everything.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:58:30 +02:00
Calic
211056ac8c feat(map-editor): fill all seven menu categories with initial items
Items in File / Edit / View / Map / Tools / Window / Help. New Map
and Open Map appear as disabled placeholders pending a v3-aware
maps.create and engine.asset.list_dir. Undo/Redo are disabled
pending an edit-stack. Cycle Rotation / Toggle Flip / Reset
Transform disable themselves in Auto-Tile mode via a mode_is()
callback. Submenus for View > Layers and Tools > Mode are
declared but their items array stays nil until the submenu render
slice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:55:06 +02:00
Calic
b5afe35df8 feat(map-editor): dropdown click dispatch
Routes clicks on dropdown items to their per-type handler:
action.fire, open_modal for modal items, toggle.fire for toggles.
Disabled items absorb without closing; separators are inert.
Clicks outside the open dropdown close the menu and fall through to
canvas handling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:51:58 +02:00
Calic
2c3015685c feat(map-editor): dropdown render for action/modal/toggle/separator
Renders the open dropdown for the active menu category with a
three-column item layout (indicator | label | hotkey). Toggle items
show their bound is_on() state with a [v]/[ ] indicator, modal
items append "...", separators draw as thin rules, disabled items
render in a muted colour. Submenu chevron is wired but submenus
themselves land in a later slice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:49:53 +02:00
Calic
2eebd3d2d5 feat(map-editor): menu-bar top-level labels render + click
Adds the seven category labels (File, Edit, View, Map, Tools,
Window, Help) at the top of the screen with hover highlight and
click-to-open / click-to-close behaviour. Item arrays are still
empty stubs; dropdown rendering lands in the next slice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:47:11 +02:00
Calic
1a9daa8ce1 feat(map-editor): Mode-pill render + click handler
Sticky two-segment pill anchored to the menu bar's right edge.
Click on a segment calls actions.set_mode; Tab hotkey continues to
toggle and the pill reflects the new state next frame. Pill
visually overlaps the legacy toolbar in this slice; the toolbar is
removed in a later commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:43:39 +02:00
Calic
6956919414 feat(map-editor): Esc cascades modal -> menu -> quit
Esc no longer immediately exits the editor; it first dismisses any
open modal, then any open dropdown menu, and only falls through to
engine.exit() when no overlay is up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:41:51 +02:00
Calic
15159d7fd5 refactor(map-editor): generalize cheatsheet into MODALS framework
Introduces a single-stack modal table where each entry declares
title, dimensions, render fn and on_click fn. The existing
Cheatsheet becomes the framework's first entry; behaviour is
preserved exactly. Dispatcher absorbs clicks while any modal is
open and routes them to the modal's on_click for close-decision.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:38:42 +02:00
Calic
e373aa8a1f refactor(map-editor): unify modal/menu state, drop cheatsheet_open
Adds menu_open, modal_open, show_layers_panel, show_palette to the
editor's state singleton; removes the now-redundant cheatsheet_open
flag. All cheatsheet-toggle paths route through the new generic
modal_open API. Visible behaviour unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:31:00 +02:00
Calic
1bf5f46924 feat(map-editor): layout constants for menu-bar UI
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 19:26:17 +02:00
4 changed files with 1227 additions and 189 deletions

View File

@@ -1,11 +1,19 @@
# sporel-module-map-editor
Interactive map editor for Sporel `.map.json` files. v0.2 series ships
the Rev 4 UX architecture (see design paper
Interactive map editor for Sporel `.map.json` files. Aufsetzend auf der
Rev-4-UX-Architektur (siehe 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).
Top-Toolbar mit Mode-Switch + Actions, rechtes Layers-Side-Panel, untere
Palette-Strip mit Material-Slot-Thumbnails, Maus-Drag-Paint und drei
Paint-Modi (Auto-Tile / Direct / Cell-Tile, mit Tab umschaltbar). Die
v0.3.0- bis v0.4.0-Iterationen sind eingeflossen: v0.3.0 ersetzte die
Toolbar durch eine Menu-Bar, v0.3.1 ergänzte den Cell-Tile-Modus, und
v0.4.0 migrierte Toolbar, Layers-Panel und Palette auf
`lib-core.panel`-Persistent-Widgets (Details siehe unten).
**Version:** 0.4.0
**Module-ID:** map-editor
**Requires:** lib-core.maps v0.5.7, lib-core.render v0.2.0, lib-core.composition v0.4.0, lib-core.camera v0.3.0, lib-core.input v0.4.0, lib-core.panel v0.4.0, lib-asset.prototype-blob-geom v0.1.0
## Run
@@ -113,3 +121,71 @@ SPOREL_CI=1 ./Sporel.exe --module=map-editor # exits with rc=0 after ~0.5 s
- 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.
## Panel-Lib Migration (v0.4.0)
The top toolbar, right-side Layers panel, and bottom palette strip
have been migrated to `lib-core.panel` v0.3.0 persistent widgets
(W.2 of the panel-window-manager plan):
| Widget ID | Layout slot | Role |
|-----------|-------------|------|
| `map-editor.toolbar` | top strip (full width, 290 px) | Menu bar + mode-pill + open-dropdown |
| `map-editor.layers` | right side-panel (160 px wide) | Layer rows + roof toggle |
| `map-editor.palette` | bottom strip (full width, 64 px) | Tile-thumbnail swatches |
All three are registered as `persistent=true` (open from module-init,
not dismissed by ESC), `input_block="self"` (hit-test claims clicks
within own bounds; misses fall through to canvas), and `chromeless=true`
(panel-lib skips its title-bar / border / close-X — the widgets paint
their own existing style). The map-canvas is NOT a panel widget — it
remains module-rendered between `camera.begin/finish`. Canvas drag-paint
is gated on `panel.point_in_any_panel(mx, my)` so widget clicks no
longer bleed through into the underlying map cells.
The Window menu's `Layers Panel` / `Palette` toggles now flip the
persistent widgets' open-state via `panel.toggle(id)` directly.
Modals (cheatsheet, save-as, map-properties, about) and the bottom-left
status chip stay module-rendered (drawn AFTER `panel.render()` so they
appear on top of widget panels).

1301
init.lua

File diff suppressed because it is too large Load Diff

21
manifest.launcher.md Normal file
View File

@@ -0,0 +1,21 @@
---
{"summary":"Map editor — menu-bar toolbar, three paint modes, Layers-Panel + Palette","author":"calic","tags":["tool","map-editor"],"teaser_images":[]}
---
# Map Editor
Click-to-paint tile editor with a top menu-bar (File / Edit / View / Map / Tools / Window / Help) plus Mode-pill, a right-side Layers-Panel and a bottom Palette-Strip with atlas-tile thumbnails. Three paint modes — Auto-Tile, Direct and Cell-Tile — cycle with Tab.
## Controls
- Mouse-left on canvas: paint (mode-dependent)
- Mouse-right on canvas: clear/erase
- Mouse-left on layer row: switch active layer
- Mouse-right on layer row: toggle visibility
- Mouse-left on palette swatch: select active slot
- Tab: cycle paint mode (Auto-Tile / Direct / Cell-Tile)
- E: erase tile at cursor
- R: rotate · H: flip · 0: reset transform
- S: save
- I: cheatsheet
- ESC: close modal / menu, else quit to launcher

View File

@@ -1,6 +1,6 @@
{
"id": "map-editor",
"version": "0.2.0c.4",
"version": "0.4.0",
"kind": "module",
"api": "^0.1",
"ci_frames": 30,
@@ -9,10 +9,12 @@
"blob_rect_stone": "lib-asset.prototype-blob-geom"
},
"deps": [
{"id":"lib-core.maps","version":"0.5.6"},
{"id":"lib-core.render","version":"0.1.0"},
{"id":"lib-core.maps","version":"0.5.7"},
{"id":"lib-core.render","version":"0.3.0"},
{"id":"lib-core.composition","version":"0.4.0"},
{"id":"lib-core.camera","version":"0.3.0"},
{"id":"lib-core.input","version":"0.4.0"},
{"id":"lib-core.panel","version":"0.4.0"},
{"id":"lib-asset.prototype-blob-geom","version":"0.1.0"}
]
}