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
This commit is contained in:
PeaAshMeter 2025-11-04 06:59:03 +03:00
parent 175062a452
commit d4e351b080
4 changed files with 57 additions and 34 deletions

21
lib/simple_ui/element.lua Normal file
View File

@ -0,0 +1,21 @@
local Rect = require "lib.simple_ui.rect"
--- @class UIElement
--- @field bounds Rect Прямоугольник, в границах которого размещается элемент. Размеры и положение в *локальных* координатах
--- @field transform love.Transform Преобразование из локальных координат элемента (bounds) в экранные координаты
local uiElement = {
bounds = Rect {},
transform = love.math.newTransform()
}
uiElement.__index = uiElement
function uiElement:update(dt) end
function uiElement:draw() end
function uiElement:hitTest(screenX, screenY)
local lx, ly = self.transform:inverseTransformPoint(screenX, screenY)
return self.bounds:hasPoint(lx, ly)
end
return uiElement

View File

@ -1,32 +1,8 @@
local icons = require("lib.utils.sprite_atlas").load(Tree.assets.files.dev_icons) local icons = require("lib.utils.sprite_atlas").load(Tree.assets.files.dev_icons)
local easing = require "lib.utils.easing" local easing = require "lib.utils.easing"
local AnimationNode = require "lib.animation_node" local AnimationNode = require "lib.animation_node"
local Element = require "lib.simple_ui.element"
--- @class UIElement local Rect = require "lib.simple_ui.rect"
local uiElement = {
x = 0,
y = 0,
width = 0,
height = 0,
transform = love.math.newTransform()
}
uiElement.__index = uiElement
function uiElement:update(dt) end
function uiElement:draw() end
function uiElement:show(animationNode) end
function uiElement:hide(animationNode) end
function uiElement:hitTest(screenX, screenY)
local lx, ly = self.transform:inverseTransformPoint(screenX, screenY)
local belongs = function(value, lower, upper)
return value >= lower and value < upper
end
return belongs(lx, self.x, self.x + self.width) and belongs(ly, self.y, self.y + self.height)
end
--- @class SkillButton : UIElement --- @class SkillButton : UIElement
--- @field showNode AnimationNode? --- @field showNode AnimationNode?
@ -35,7 +11,7 @@ end
--- @field selected boolean --- @field selected boolean
--- @field onClick function? --- @field onClick function?
--- @field icon string --- @field icon string
local skillButton = setmetatable({}, uiElement) local skillButton = setmetatable({}, Element)
skillButton.__index = skillButton skillButton.__index = skillButton
function skillButton.new(icon) function skillButton.new(icon)
@ -99,7 +75,7 @@ end
--- @field characterId Id --- @field characterId Id
--- @field selected SkillButton? --- @field selected SkillButton?
--- @field children SkillButton[] --- @field children SkillButton[]
local skillRow = setmetatable({}, uiElement) local skillRow = setmetatable({}, Element)
skillRow.__index = skillRow skillRow.__index = skillRow
--- @param characterId Id --- @param characterId Id
@ -151,15 +127,17 @@ function skillRow:update(dt)
local screenW, screenH = love.graphics.getDimensions() local screenW, screenH = love.graphics.getDimensions()
local padding = 8 local padding = 8
local count = #self.children local count = #self.children
self.width, self.height, self.x, self.y = count * icons.tileSize + (count - 1) * padding, iconSize, 0,
0 -- в локальных координатах
self.bounds = Rect {
width = count * icons.tileSize + (count - 1) * padding,
height = iconSize
}
self.transform = love.math.newTransform():translate(screenW / 2, self.transform = love.math.newTransform():translate(screenW / 2,
screenH - 16):scale(scale, scale):translate(-self.width / 2, -iconSize) screenH - 16):scale(scale, scale):translate(-self.bounds.width / 2, -iconSize)
for i, skb in ipairs(self.children) do for i, skb in ipairs(self.children) do
skb.width, skb.height = iconSize, iconSize skb.bounds = Rect { height = iconSize, width = iconSize }
skb.transform = self.transform:clone():translate(self.x + (i - 1) * iconSize + skb.transform = self.transform:clone():translate(self.bounds.x + (i - 1) * iconSize +
(i - 1) * (i - 1) *
padding, -- левый край ряда + размер предыдущих иконок + размер предыдущих отступов padding, -- левый край ряда + размер предыдущих иконок + размер предыдущих отступов
0 -- высота не меняется 0 -- высота не меняется

24
lib/simple_ui/rect.lua Normal file
View File

@ -0,0 +1,24 @@
--- @class Rect
--- @field x number
--- @field y number
--- @field width number
--- @field height number
local rect = {}
rect.__index = rect
--- @param table {x: number, y: number, width: number, height: number}
function rect.new(table)
local r = {
x = table.x or 0,
y = table.y or 0,
width = table.width or 0,
height = table.height or 0
}
return setmetatable(r, rect)
end
function rect:hasPoint(x, y)
return x >= self.x and x < self.width and y >= self.y and y < self.height
end
return rect.new

View File

@ -2,7 +2,7 @@
local character = require "lib/character/character" local character = require "lib/character/character"
require "lib/tree" require "lib/tree"
local testLayout = require "lib.simple_ui.level_layout" local testLayout = require "lib.simple_ui.level.layout"
function love.conf(t) function love.conf(t)
t.console = true t.console = true