feat(map-editor): v0.2.0c.3 — debug overlay (D toggle, per-cell slot/rot)

Diagnostic for the dual-grid + blob-14 painting model: D-key toggles
a per-cell text annotation rendered over the map. For each material
cell on the active layer, draws "S<slot>r<rot>" (and "f" when flip=1)
in green at the cell's top-left, sourced from the new lib-core.maps
0.5.5 cell_material_slot getter.

Use case: confirm that the renderer actually picks distinct slots
(corner_full / tee_full / cross / etc.) for painted regions rather
than always picking slot 13 solid — the rectilinear style fills enough
of each cell that visually adjacent slots 3/7/13 are hard to
distinguish without numerical labels.

Inline today; plan-stub
`docs/superpowers/plans/2026-05-29-debug-overlay-extract-to-lib.md`
deferred until a 2nd consumer (vagrant debug-render, puppet-editor,
etc.) appears.

Also bumps lib-core.maps dep 0.5.4 -> 0.5.5.
This commit is contained in:
calic
2026-05-29 09:56:52 +02:00
parent c66e670336
commit cf5771a573
2 changed files with 43 additions and 4 deletions

View File

@@ -1,4 +1,4 @@
-- sporel-module-map-editor v0.2.0c.2
-- sporel-module-map-editor v0.2.0c.3
-- Interactive map editor — Rev 4 UX architecture (see design paper
-- 2026-05-28-autotile-blob-styles-design.md §11 + plan stub
-- 2026-05-28-map-editor-blob-v2.md). 0.2.0b adds the bottom palette
@@ -18,6 +18,10 @@
-- 0.2.0c.2 makes the palette show real tile thumbnails via the new
-- lib-core.maps 0.5.4 atlas-handle / tile-UV getters. Falls back to
-- the legacy colour swatch when atlas isn't loaded.
-- 0.2.0c.3 adds the D-toggle debug overlay: per material cell on the
-- active layer renders "S<slot>r<rot>" (and "f" when flip=1) via the
-- new lib-core.maps 0.5.5 cell_material_slot getter. Inline today;
-- extract to lib-sporel.debug-overlay when a 2nd consumer appears.
-- Decal/Entity sub-selectors + Material-Properties modal land in 0.2.0d.
--
-- All editor logic in this single file: engine sandbox only allows
@@ -66,6 +70,7 @@ local state = (function()
mouse_cell = nil, -- {x, y} or nil if mouse off-map
snap_vertex = nil, -- 0.2.0b: {vx, vy} or nil (auto-tile mode snap target)
drag_paint = nil, -- 0.2.0c.1: nil | "paint" | "erase" (active drag-stroke mode)
debug_overlay = false, -- 0.2.0c.3: D toggles per-cell slot/rot annotations
}
-- =====================================================================
@@ -157,6 +162,9 @@ local state = (function()
function M.set_drag_paint(mode) state.drag_paint = mode end -- 0.2.0c.1
function M.get_drag_paint() return state.drag_paint end
function M.toggle_debug_overlay() state.debug_overlay = not state.debug_overlay end
function M.is_debug_overlay() return state.debug_overlay end
-- Used by tests to reset between asserts
function M.reset()
state.map_id = nil
@@ -173,6 +181,7 @@ local state = (function()
state.mouse_cell = nil
state.snap_vertex = nil
state.drag_paint = nil
state.debug_overlay = false
for name in pairs(state.layer_visible) do
state.layer_visible[name] = true
end
@@ -302,6 +311,9 @@ local actions = (function()
function M.toggle_flip() state.toggle_flip() end
function M.reset_transform() state.reset_transform() end
-- 0.2.0c.3 actions
function M.toggle_debug_overlay() state.toggle_debug_overlay() end
return M
end)()
@@ -410,6 +422,7 @@ local ui = (function()
{ key="R", action="Cycle tile rotation 0->90->180->270 (Direct-mode override)" },
{ key="H", action="Toggle tile flip 0<->1 (Direct-mode override)" },
{ key="0", action="Reset transform (rot=0, flip=0)" },
{ key="D", action="Toggle debug overlay (per-cell slot/rot labels)" },
{ key="Esc", action="Quit editor" },
{ key="LMB-drag canvas (Auto-Tile)", action="Stroke-paint vertices (any-corner fill)" },
{ key="RMB-drag canvas (Auto-Tile)", action="Stroke-clear vertices" },
@@ -715,6 +728,27 @@ local ui = (function()
draw_cheatsheet(mx, my) -- last so it overlays everything when open
end
-- 0.2.0c.3 debug overlay: per-cell slot/rot annotation. Independent
-- of mode toggle — useful in both Auto-Tile (verify bitmask path)
-- and Direct (verify override write). Iterates the active layer.
function M.draw_debug_overlay(map_w, map_h, t_size)
if not state.is_debug_overlay() then return end
local layer = state.get_active_layer()
for y = 0, map_h - 1 do
for x = 0, map_w - 1 do
local rec = maps.cell_material_slot(layer, x, y)
if rec then
-- text at cell center, e.g. "S7r1" or "S13r0f1"
local txt = string.format("S%dr%d%s",
rec.slot, rec.rot, rec.flip == 1 and "f" or "")
engine.render.draw_text(txt,
x * t_size + 4, y * t_size + 4, 9,
rgba(COL_VERTEX_SNAP, 0xFF))
end
end
end
end
-- World-space overlay rendered between maps.draw_map and camera.finish.
-- Auto-Tile mode only — shows the cell grid + vertex dots + snapped
-- vertex highlight so the painter can see where a click will land.
@@ -850,8 +884,9 @@ input.bind("toggle_mode", { "tab" }) -- 0.2.0a
input.bind("toggle_cheatsheet", { "i" }) -- 0.2.0a — `i` for Info/help (no shifted-key support in input lib)
input.bind("flip", { "h" }) -- 0.2.0c
input.bind("reset_transform", { "0" }) -- 0.2.0c
input.bind("toggle_debug_overlay", { "d" }) -- 0.2.0c.3
engine.print("map-editor v0.2.0c.2: ready. Tab=mode, I=help, S=save, E=erase, R=rotate, H=flip, 0=reset, ESC=quit")
engine.print("map-editor v0.2.0c.3: ready. Tab=mode, I=help, D=debug, S=save, E=erase, R=rotate, H=flip, 0=reset, ESC=quit")
-- =====================================================================
-- Frame hooks
@@ -930,6 +965,9 @@ function update(ctx, dt)
if input.was_action_pressed("reset_transform") then
actions.reset_transform()
end
if input.was_action_pressed("toggle_debug_overlay") then
actions.toggle_debug_overlay()
end
-- Mouse clicks + drag: hit-test UI on press; if consumed we never
-- enter drag-mode for this stroke. Otherwise the press initiates a
@@ -985,6 +1023,7 @@ function render(ctx)
camera.begin()
maps.draw_map()
ui.draw_world_overlay(m_size.w, m_size.h, t_size, state.get_snap_vertex())
ui.draw_debug_overlay(m_size.w, m_size.h, t_size)
camera.finish()
ui.draw() -- screen-space overlays after camera ends
end