Refactor skill button and row to use UIElement with Rect bounds and transform Update layout references and coordinate calculations accordingly
171 lines
4.8 KiB
Lua
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
|