feat(map-editor): v0.2.0c.4 — G-toggle mode-aware world overlay
Adds a G key that toggles the world-space overlay on and off (default on). The overlay adapts to the active painting mode: - Auto-Tile mode shows the map-grid (paint-tile boundaries, which sit at half-tile offsets from the render-cell boundaries in dual-grid), the per-map-tile vertex dots, and the snapped paint-target highlight. - Direct mode shows only a subtle render-cell grid, since LMB strokes write directly to render-cells in that mode. Bumps the lib-core.maps dep pin to 0.5.6 to pick up the dual-grid bitmask fix that makes the auto-tile output match the dual-grid mental model. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
89
init.lua
89
init.lua
@@ -1,4 +1,4 @@
|
||||
-- sporel-module-map-editor v0.2.0c.3
|
||||
-- sporel-module-map-editor v0.2.0c.4
|
||||
-- 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
|
||||
@@ -71,6 +71,7 @@ local state = (function()
|
||||
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
|
||||
world_overlay = true, -- 0.2.0c.4: G toggles render-grid + map-grid + coords
|
||||
}
|
||||
|
||||
-- =====================================================================
|
||||
@@ -165,6 +166,9 @@ local state = (function()
|
||||
function M.toggle_debug_overlay() state.debug_overlay = not state.debug_overlay end
|
||||
function M.is_debug_overlay() return state.debug_overlay end
|
||||
|
||||
function M.toggle_world_overlay() state.world_overlay = not state.world_overlay end
|
||||
function M.is_world_overlay() return state.world_overlay end
|
||||
|
||||
-- Used by tests to reset between asserts
|
||||
function M.reset()
|
||||
state.map_id = nil
|
||||
@@ -182,6 +186,7 @@ local state = (function()
|
||||
state.snap_vertex = nil
|
||||
state.drag_paint = nil
|
||||
state.debug_overlay = false
|
||||
state.world_overlay = true
|
||||
for name in pairs(state.layer_visible) do
|
||||
state.layer_visible[name] = true
|
||||
end
|
||||
@@ -313,6 +318,7 @@ local actions = (function()
|
||||
|
||||
-- 0.2.0c.3 actions
|
||||
function M.toggle_debug_overlay() state.toggle_debug_overlay() end
|
||||
function M.toggle_world_overlay() state.toggle_world_overlay() end
|
||||
|
||||
return M
|
||||
end)()
|
||||
@@ -423,6 +429,7 @@ local ui = (function()
|
||||
{ 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="G", action="Toggle world overlay (Auto-Tile: map-grid + dots; Direct: cell-grid)" },
|
||||
{ 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" },
|
||||
@@ -750,37 +757,59 @@ local ui = (function()
|
||||
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.
|
||||
-- 0.2.0c.4: G-toggle gates the overlay; the displayed grid is
|
||||
-- mode-aware. Auto-tile mode paints map-tiles, so we show the
|
||||
-- map-grid (paint-tile boundaries, offset by half a tile from
|
||||
-- render-cell boundaries) plus the vertex dots and snap target.
|
||||
-- Direct mode paints cells, so we show the render-cell grid with
|
||||
-- a lighter stroke and skip the dots / snap.
|
||||
-- snap = { vx, vy } or nil when the cursor is off-map.
|
||||
function M.draw_world_overlay(map_w, map_h, t_size, snap)
|
||||
if state.get_mode() ~= "auto-tile" then return end
|
||||
if not state.is_world_overlay() then return end
|
||||
local mode = state.get_mode()
|
||||
|
||||
-- Grid lines (1 px) at every cell boundary.
|
||||
local grid_col = rgba(COL_VERTEX_GRID, 0x40)
|
||||
for x = 0, map_w do
|
||||
engine.render.draw_line(x * t_size, 0, x * t_size, map_h * t_size, grid_col)
|
||||
end
|
||||
for y = 0, map_h do
|
||||
engine.render.draw_line(0, y * t_size, map_w * t_size, y * t_size, grid_col)
|
||||
end
|
||||
|
||||
-- Vertex dots (small 4 px squares centered on each vertex).
|
||||
local dot_col = rgba(COL_VERTEX_DOT, 0xC0)
|
||||
for vy = 0, map_h do
|
||||
for vx = 0, map_w do
|
||||
local cx = vx * t_size - 2
|
||||
local cy = vy * t_size - 2
|
||||
engine.render.draw_rect(cx, cy, 4, 4, dot_col)
|
||||
if mode == "auto-tile" then
|
||||
-- Map-grid lines: boundaries between adjacent map-tiles, which
|
||||
-- in dual-grid sit at half-tile offsets from render-cell
|
||||
-- boundaries (= at render-cell centres).
|
||||
local map_col = rgba(COL_VERTEX_GRID, 0x60)
|
||||
local half = t_size / 2
|
||||
for x = 0, map_w - 1 do
|
||||
local px = x * t_size + half
|
||||
engine.render.draw_line(px, 0, px, map_h * t_size, map_col)
|
||||
end
|
||||
for y = 0, map_h - 1 do
|
||||
local py = y * t_size + half
|
||||
engine.render.draw_line(0, py, map_w * t_size, py, map_col)
|
||||
end
|
||||
end
|
||||
|
||||
-- Snapped vertex highlight (larger ring around the snap target).
|
||||
if snap then
|
||||
local px = snap.vx * t_size
|
||||
local py = snap.vy * t_size
|
||||
engine.render.draw_rect_lines(px - 6, py - 6, 12, 12,
|
||||
rgba(COL_VERTEX_SNAP, 0xFF))
|
||||
-- Vertex dots (paint snap-targets, one per map-tile centre).
|
||||
local dot_col = rgba(COL_VERTEX_DOT, 0xC0)
|
||||
for vy = 0, map_h do
|
||||
for vx = 0, map_w do
|
||||
local cx = vx * t_size - 2
|
||||
local cy = vy * t_size - 2
|
||||
engine.render.draw_rect(cx, cy, 4, 4, dot_col)
|
||||
end
|
||||
end
|
||||
|
||||
-- Snapped vertex highlight (where LMB will paint).
|
||||
if snap then
|
||||
local px = snap.vx * t_size
|
||||
local py = snap.vy * t_size
|
||||
engine.render.draw_rect_lines(px - 6, py - 6, 12, 12,
|
||||
rgba(COL_VERTEX_SNAP, 0xFF))
|
||||
end
|
||||
else
|
||||
-- Direct mode: subtle render-cell grid only — that's the
|
||||
-- grid LMB strokes write to.
|
||||
local cell_col = rgba(COL_VERTEX_GRID, 0x25)
|
||||
for x = 0, map_w do
|
||||
engine.render.draw_line(x * t_size, 0, x * t_size, map_h * t_size, cell_col)
|
||||
end
|
||||
for y = 0, map_h do
|
||||
engine.render.draw_line(0, y * t_size, map_w * t_size, y * t_size, cell_col)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -885,8 +914,9 @@ input.bind("toggle_cheatsheet", { "i" }) -- 0.2.0a — `i` for Info/help (no
|
||||
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
|
||||
input.bind("toggle_world_overlay", { "g" }) -- 0.2.0c.4
|
||||
|
||||
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")
|
||||
engine.print("map-editor v0.2.0c.4: ready. Tab=mode, I=help, G=grid, D=debug, S=save, E=erase, R=rotate, H=flip, 0=reset, ESC=quit")
|
||||
|
||||
-- =====================================================================
|
||||
-- Frame hooks
|
||||
@@ -968,6 +998,9 @@ function update(ctx, dt)
|
||||
if input.was_action_pressed("toggle_debug_overlay") then
|
||||
actions.toggle_debug_overlay()
|
||||
end
|
||||
if input.was_action_pressed("toggle_world_overlay") then
|
||||
actions.toggle_world_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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "map-editor",
|
||||
"version": "0.2.0c.3",
|
||||
"version": "0.2.0c.4",
|
||||
"kind": "module",
|
||||
"api": "^0.1",
|
||||
"ci_frames": 30,
|
||||
@@ -9,7 +9,7 @@
|
||||
"blob_rect_stone": "lib-asset.prototype-blob-geom"
|
||||
},
|
||||
"deps": [
|
||||
{"id":"lib-core.maps","version":"0.5.5"},
|
||||
{"id":"lib-core.maps","version":"0.5.6"},
|
||||
{"id":"lib-core.render","version":"0.1.0"},
|
||||
{"id":"lib-core.camera","version":"0.3.0"},
|
||||
{"id":"lib-core.input","version":"0.4.0"},
|
||||
|
||||
Reference in New Issue
Block a user