-- 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