Add editor state module with accessor API
Singleton table covering map id+path, active layer/atlas/tile/rot, roof-mode flag, per-layer visibility flags, dirty flag, and picker open/close state. Mutations go through setters so the test module can verify state transitions without poking the internal table. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
96
src/state.lua
Normal file
96
src/state.lua
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
-- src/state.lua
|
||||||
|
-- Editor state singleton + accessors.
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
-- =====================================================================
|
||||||
|
-- State (module-singleton)
|
||||||
|
-- =====================================================================
|
||||||
|
local state = {
|
||||||
|
map_id = nil, -- set by init.lua after maps.load()
|
||||||
|
map_path = "maps/work.map.json",
|
||||||
|
active_layer = "surface", -- one of VALID_LAYER_NAMES
|
||||||
|
active_atlas = 0, -- atlas_index 0..N-1
|
||||||
|
active_tile = 1, -- tile_id
|
||||||
|
active_rot = 0, -- 0..3
|
||||||
|
roof_mode = false, -- if true, paint targets roof
|
||||||
|
layer_visible = {
|
||||||
|
foundation=true, subsurface=true, surface=true, topsurface=true,
|
||||||
|
lower_wall=true, wall=true, upper_wall=true, canopy=true,
|
||||||
|
},
|
||||||
|
dirty = false,
|
||||||
|
picker_open = false, -- atlas+tile picker expanded?
|
||||||
|
mouse_cell = nil, -- {x, y} or nil if mouse off-map
|
||||||
|
}
|
||||||
|
|
||||||
|
-- =====================================================================
|
||||||
|
-- Setters / getters (encapsulate state for testability)
|
||||||
|
-- =====================================================================
|
||||||
|
|
||||||
|
function M.set_map(map_id, path)
|
||||||
|
state.map_id = map_id
|
||||||
|
state.map_path = path
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.get_map_id() return state.map_id end
|
||||||
|
function M.get_map_path() return state.map_path end
|
||||||
|
|
||||||
|
function M.set_active_layer(name) state.active_layer = name end
|
||||||
|
function M.get_active_layer() return state.active_layer end
|
||||||
|
|
||||||
|
function M.set_active_atlas(idx) state.active_atlas = idx end
|
||||||
|
function M.get_active_atlas() return state.active_atlas end
|
||||||
|
|
||||||
|
function M.set_active_tile(id) state.active_tile = id end
|
||||||
|
function M.get_active_tile() return state.active_tile end
|
||||||
|
|
||||||
|
function M.cycle_rotation()
|
||||||
|
state.active_rot = (state.active_rot + 1) % 4
|
||||||
|
end
|
||||||
|
function M.get_active_rot() return state.active_rot end
|
||||||
|
|
||||||
|
function M.toggle_roof_mode()
|
||||||
|
state.roof_mode = not state.roof_mode
|
||||||
|
end
|
||||||
|
function M.is_roof_mode() return state.roof_mode end
|
||||||
|
|
||||||
|
function M.toggle_layer_visible(name)
|
||||||
|
state.layer_visible[name] = not state.layer_visible[name]
|
||||||
|
end
|
||||||
|
function M.is_layer_visible(name) return state.layer_visible[name] ~= false end
|
||||||
|
|
||||||
|
function M.mark_dirty() state.dirty = true end
|
||||||
|
function M.mark_clean() state.dirty = false end
|
||||||
|
function M.is_dirty() return state.dirty end
|
||||||
|
|
||||||
|
function M.toggle_picker_open()
|
||||||
|
state.picker_open = not state.picker_open
|
||||||
|
end
|
||||||
|
function M.is_picker_open() return state.picker_open end
|
||||||
|
|
||||||
|
function M.set_mouse_cell(x, y)
|
||||||
|
if x == nil then
|
||||||
|
state.mouse_cell = nil
|
||||||
|
else
|
||||||
|
state.mouse_cell = { x = x, y = y }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function M.get_mouse_cell() return state.mouse_cell end
|
||||||
|
|
||||||
|
-- Used by tests to reset between asserts
|
||||||
|
function M.reset()
|
||||||
|
state.map_id = nil
|
||||||
|
state.active_layer = "surface"
|
||||||
|
state.active_atlas = 0
|
||||||
|
state.active_tile = 1
|
||||||
|
state.active_rot = 0
|
||||||
|
state.roof_mode = false
|
||||||
|
state.dirty = false
|
||||||
|
state.picker_open = false
|
||||||
|
state.mouse_cell = nil
|
||||||
|
for name in pairs(state.layer_visible) do
|
||||||
|
state.layer_visible[name] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
Reference in New Issue
Block a user