chroma_solstice/level_editor/layout.lua

64 lines
2.7 KiB
Lua
Raw Normal View History

-- A dead-simple layout helper for the editor sidebar. Everything works in the
-- sidebar's local coordinate space (0,0 = top-left of sideBarCanvas) — the same
-- space editorDraw / editorMouseHandler already use — so section rects double as
-- love.graphics.setScissor rects and as hit boxes. No dependencies, no state of
-- its own beyond the scroll table the caller hands in.
Layout = {}
-- point-in-rect
function Layout.hit(r, x, y)
return x >= r.x and x < r.x + r.w and y >= r.y and y < r.y + r.h
end
-- Clip drawing to a section. setScissor ignores the active graphics transform,
-- so multiply the virtual-space rect by editorRenderScale to hit real canvas
-- pixels. Clamp to non-negative: a too-narrow/short sidebar (e.g. a square
-- window with no room for it) would otherwise hand setScissor a negative size.
function Layout.clip(r)
local s = editorRenderScale or 1
love.graphics.setScissor(r.x * s, r.y * s, math.max(0, r.w * s), math.max(0, r.h * s))
end
function Layout.unclip() love.graphics.setScissor() end
-- A vertical scrolling list confined to rect `r`. `state` is any table the
-- caller keeps between frames to hold `state.scroll`; it is clamped here.
-- Returns helpers to place / cull / hit-test `count` items of height `itemH`.
function Layout.list(state, r, itemH, count, gap)
gap = gap or 6
local step = itemH + gap
local content = count * step
local maxScroll = math.max(0, content - r.h)
state.scroll = math.max(0, math.min(state.scroll or 0, maxScroll))
local scroll = state.scroll
return {
rect = r, itemH = itemH, step = step, count = count, maxScroll = maxScroll, scroll = scroll,
-- top-left corner of item i (1-based), in sidebar space
pos = function(i) return r.x, r.y + (i - 1) * step - scroll end,
-- is item i at all inside the visible window? (cheap cull)
visible = function(i)
local y = r.y + (i - 1) * step - scroll
return y + itemH > r.y and y < r.y + r.h
end,
-- index at a sidebar-space point, or nil if outside the list / no item
at = function(x, y)
if not Layout.hit(r, x, y) then return nil end
local i = math.floor((y - r.y + scroll) / step) + 1
if i >= 1 and i <= count then return i end
return nil
end,
}
end
-- Thin scrollbar thumb on the right edge of a list, drawn only when it scrolls.
function Layout.scrollbar(list)
if list.maxScroll <= 0 then return end
local r = list.rect
local thumb = math.max(16, r.h * (r.h / (r.h + list.maxScroll)))
local ty = r.y + (r.h - thumb) * (list.scroll / list.maxScroll)
local pr, pg, pb, pa = love.graphics.getColor()
love.graphics.setColor(255, 255, 255, 90)
love.graphics.rectangle("fill", r.x + r.w - 4, ty, 3, thumb)
love.graphics.setColor(pr, pg, pb, pa)
end