PeaAshMeter d4e351b080 Introduce Rect class and UIElement base class for layout
Refactor skill button and row to use UIElement with Rect bounds and
transform Update layout references and coordinate calculations
accordingly
2025-11-04 06:59:03 +03:00

171 lines
4.8 KiB
Lua

local icons = require("lib.utils.sprite_atlas").load(Tree.assets.files.dev_icons)
local easing = require "lib.utils.easing"
local AnimationNode = require "lib.animation_node"
local Element = require "lib.simple_ui.element"
local Rect = require "lib.simple_ui.rect"
--- @class SkillButton : UIElement
--- @field showNode AnimationNode?
--- @field showT number
--- @field hovered boolean
--- @field selected boolean
--- @field onClick function?
--- @field icon string
local skillButton = setmetatable({}, Element)
skillButton.__index = skillButton
function skillButton.new(icon)
return setmetatable({
icon = icon
}, skillButton)
end
function skillButton:update(dt)
local mx, my = love.mouse.getPosition()
if self:hitTest(mx, my) then
self.hovered = true
if Tree.controls:isJustPressed("select") then
if self.onClick then self.onClick() end
Tree.controls:consume("select")
end
else
self.hovered = false
end
if self.showT < 1 then
self.showT = self.showT + dt * 1 / 0.3 -- в знаменателе продолжительность анимации в секундах
self.y = 10 * easing.easeInCubic(1 - self.showT)
return
end
if self.showNode then
self.showNode:finish()
self.showNode = nil
end
end
--- @param animationNode AnimationNode
function skillButton:show(animationNode)
if self.showNode then
self.showNode:finish()
end
self.showT = 0
self.showNode = animationNode
end
function skillButton:draw()
love.graphics.push()
love.graphics.applyTransform(self.transform)
local alpha = easing.easeInSine(self.showT)
if self.selected then
love.graphics.setColor(0.3, 1, 0.3, alpha)
elseif self.hovered then
love.graphics.setColor(0.7, 1, 0.7, alpha)
else
love.graphics.setColor(1, 1, 1, alpha)
end
love.graphics.translate(0, self.y)
love.graphics.draw(icons.atlas, icons:pickQuad(self.icon))
love.graphics.setColor(1, 1, 1)
love.graphics.pop()
end
--- @class SkillRow : UIElement
--- @field characterId Id
--- @field selected SkillButton?
--- @field children SkillButton[]
local skillRow = setmetatable({}, Element)
skillRow.__index = skillRow
--- @param characterId Id
function skillRow.new(characterId)
local t = {
characterId = characterId,
children = {}
}
setmetatable(t, skillRow)
local char = Tree.level.characters[characterId]
char:try(Tree.behaviors.spellcaster, function(behavior)
for i, spell in ipairs(behavior.spellbook) do
local skb = skillButton.new(spell.tag)
skb.onClick = function()
skb.selected = not skb.selected
if t.selected then t.selected.selected = false end
t.selected = skb
if not behavior.cast then
behavior.cast = behavior.spellbook[i]
behavior.state = "casting"
else
behavior.state = "idle"
behavior.cast = nil
end
end
t.children[i] = skb
end
end)
return t
end
function skillRow:show()
for _, skb in ipairs(self.children) do
AnimationNode {
function(animationNode)
skb:show(animationNode)
end,
}:run()
end
end
function skillRow:update(dt)
local iconSize = icons.tileSize
local scale = (64 / iconSize)
local screenW, screenH = love.graphics.getDimensions()
local padding = 8
local count = #self.children
self.bounds = Rect {
width = count * icons.tileSize + (count - 1) * padding,
height = iconSize
}
self.transform = love.math.newTransform():translate(screenW / 2,
screenH - 16):scale(scale, scale):translate(-self.bounds.width / 2, -iconSize)
for i, skb in ipairs(self.children) do
skb.bounds = Rect { height = iconSize, width = iconSize }
skb.transform = self.transform:clone():translate(self.bounds.x + (i - 1) * iconSize +
(i - 1) *
padding, -- левый край ряда + размер предыдущих иконок + размер предыдущих отступов
0 -- высота не меняется
)
skb:update(dt)
end
end
function skillRow:draw()
for _, skb in ipairs(self.children) do
skb:draw()
end
end
local layout = {}
function layout:update(dt)
local cid = Tree.level.selector:selected()
if cid then
self.skillRow = skillRow.new(cid)
self.skillRow:show()
end
if Tree.level.selector:deselected() then self.skillRow = nil end
if self.skillRow then self.skillRow:update(dt) end
end
function layout:draw()
if self.skillRow then self.skillRow:draw() end
end
return layout