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