local icons = require("lib.utils.sprite_atlas").load(Tree.assets.files.dev_icons) local Element = require "lib.simple_ui.element" local Rect = require "lib.simple_ui.rect" local UI_SCALE = require "lib.simple_ui.level.scale" --- @class SkillButton : UIElement --- @field hovered boolean --- @field selected boolean --- @field onClick function? --- @field icon? string local skillButton = setmetatable({}, Element) skillButton.__index = skillButton function skillButton:update(dt) if not self.icon then return end 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 end function skillButton:draw() love.graphics.setLineWidth(2) if not self.icon then love.graphics.setColor(0.05, 0.05, 0.05) love.graphics.rectangle("fill", self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height) self:drawBorder("inner") return end local quad = icons:pickQuad(self.icon) love.graphics.push() love.graphics.translate(self.bounds.x, self.bounds.y) love.graphics.scale(self.bounds.width / icons.tileSize, self.bounds.height / icons.tileSize) love.graphics.draw(icons.atlas, quad) love.graphics.pop() self:drawBorder("inner") if self.selected then love.graphics.setColor(0.3, 1, 0.3, 0.5) love.graphics.rectangle("fill", self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height) elseif self.hovered then love.graphics.setColor(0.7, 1, 0.7, 0.5) love.graphics.rectangle("fill", self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height) end love.graphics.setColor(1, 1, 1) end -------------------------------------------------------------------------------- --- @class SkillRow : UIElement --- @field characterId Id --- @field selected SkillButton? --- @field children SkillButton[] local skillRow = setmetatable({}, Element) skillRow.__index = skillRow --- @param characterId Id --- @return SkillRow 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 { icon = 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) for i = #t.children + 1, 7, 1 do t.children[i] = skillButton:new {} end return t end function skillRow:update(dt) local iconSize = 64 * UI_SCALE local screenW, screenH = love.graphics.getDimensions() local padding, margin = 8, 4 local count = #self.children -- слоты под скиллы self.bounds = Rect { width = iconSize * count + (count + 1) * margin, height = iconSize + 2 * margin, } self.bounds.y = screenH - self.bounds.height - padding -- отступ снизу self.bounds.x = screenW / 2 - self.bounds.width / 2 for i, skb in ipairs(self.children) do skb.bounds = Rect { x = self.bounds.x + margin + (i - 1) * (iconSize + margin), -- друг за другом, включая первый отступ от границы y = self.bounds.y + margin, height = iconSize, width = iconSize } skb:update(dt) end end local c = love.graphics.newCanvas(1280, 720) --- @TODO: выставлять канвасу правильный размер в зависимости от окна function skillRow:draw() local oldCanvas = love.graphics.getCanvas() love.graphics.setCanvas({ c, stencil = true }) love.graphics.clear() love.graphics.setColor(1, 1, 1) -- сначала иконки скиллов for _, skb in ipairs(self.children) do skb:draw() end -- маска для вырезов под иконки love.graphics.setShader(Tree.assets.files.shaders.alpha_mask) love.graphics.stencil(function() local mask = Tree.assets.files.masks.rrect32 local maskSize = mask:getWidth() for _, skb in ipairs(self.children) do love.graphics.draw(mask, skb.bounds.x, skb.bounds.y, 0, skb.bounds.width / maskSize, skb.bounds.height / maskSize) end end, "replace", 1) love.graphics.setShader() -- дальше рисуем панель, перекрывая иконки love.graphics.setStencilTest("less", 1) -- шум love.graphics.setShader(Tree.assets.files.shaders.soft_uniform_noise) love.graphics.rectangle("fill", self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height) love.graphics.setShader() -- фон love.graphics.setColor(38 / 255, 50 / 255, 56 / 255) love.graphics.setBlendMode("multiply", "premultiplied") love.graphics.rectangle("fill", self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height) love.graphics.setBlendMode("alpha") love.graphics.setStencilTest() --затенение self:drawGradientOverlay() love.graphics.setColor(1, 1, 1) love.graphics.setCanvas(oldCanvas) love.graphics.draw(c) end return skillRow.new