tiny-ecs-love-template/systems/draw.lua

78 lines
2.5 KiB
Lua

local world = require("world")
local gfx = love.graphics
---@generic T
---@param shape T | fun()
---@param process fun(entity: T, dt: number, system: System) | nil
---@return System | { entities: T[] }
local function drawSystem(name, shape, process)
local system = world:filteredSystem(name, shape, process, function(_, a, b)
if a.z ~= nil and b.z ~= nil then
return a.z < b.z
end
if a.z ~= nil then
return true
end
return false
end)
system.isDrawSystem = true
return system
end
local spriteDrawSystem = drawSystem(
"drawSprites",
{ position = T.XyPair, drawAsSprite = T.Drawable, rotation = Maybe(T.number) },
function(e)
if not e.drawAsSprite then
return
end
gfx.draw(e.drawAsSprite, e.position.x, e.position.y)
end
)
function spriteDrawSystem:preProcess()
gfx.setColor(1, 1, 1)
end
local margin = 8
drawSystem(
"drawText",
{ position = T.XyPair, drawAsText = { text = T.str, style = Maybe(T.str), font = Maybe(T.FontData) } },
function(e)
local font
if e.drawAsText.font then
font = e.drawAsText.font
gfx.setFont(font)
else
font = gfx.getFont()
end
local textHeight = font:getHeight()
local textWidth = font:getWidth(e.drawAsText.text)
local bgLeftEdge = e.position.x - margin -- - (textWidth / 2)
local bgTopEdge = e.position.y - 2
local bgWidth, bgHeight = textWidth + (margin * 2), textHeight + 2
if e.drawAsText.style == TextStyle.Inverted then
gfx.setColor(0, 0, 0)
gfx.rectangle("fill", bgLeftEdge, bgTopEdge, textWidth + margin, textHeight + 2)
gfx.setColor(1, 1, 1)
elseif e.drawAsText.style == TextStyle.Bordered then
gfx.setColor(1, 1, 1)
gfx.rectangle("fill", bgLeftEdge, bgTopEdge, bgWidth, bgHeight)
gfx.setColor(0, 0, 0)
gfx.rectangle("line", bgLeftEdge, bgTopEdge, bgWidth, bgHeight)
end
gfx.print(e.drawAsText.text, bgLeftEdge + margin, bgTopEdge + margin)
end
)
drawSystem("drawRectangles", { position = T.XyPair, drawAsRectangle = { size = T.XyPair } }, function(e, _, _)
gfx.setColor(1, 1, 1, 0.5)
local mode = e.drawAsRectangle.mode or "line" -- (e.highlighted and "fill" or "line")
gfx.rectangle(mode, e.position.x, e.position.y, e.drawAsRectangle.size.x, e.drawAsRectangle.size.y)
end)