make ui use screen space dimensions add some fancy looks to the skill

row
This commit is contained in:
PeaAshMeter 2025-12-06 20:13:55 +03:00
parent 411c435e7a
commit bcc376030c
7 changed files with 133 additions and 46 deletions

View File

@ -0,0 +1,17 @@
#pragma language glsl3
vec2 hash(vec2 p) {
p = fract(p * vec2(123.34, 456.21));
p += dot(p, p + 34.345);
return fract(vec2(p.x * p.y, p.x + p.y));
}
vec4 effect(vec4 color, Image tex, vec2 uv, vec2 px)
{
vec2 cell = floor(px / 2.0);
float n = hash(cell).x; // 0..1
float v = 0.9 + n * 0.2; // 0.9..1.0
return vec4(v, v, v, 1.0);
}

View File

@ -11,8 +11,7 @@ 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)
return self.bounds:hasPoint(screenX, screenY)
end
--- @generic T : UIElement
@ -21,8 +20,43 @@ end
--- @return T
function uiElement.new(self, values)
values.bounds = values.bounds or Rect {}
values.transform = values.transform or love.math.newTransform()
return setmetatable(values, self)
end
--- Рисует границу вокруг элемента (с псевдо-затенением)
--- @param type "outer" | "inner"
function uiElement:drawBorder(type)
if type == "inner" then
love.graphics.setColor(0.2, 0.2, 0.2)
love.graphics.line({
self.bounds.x, self.bounds.y + self.bounds.height,
self.bounds.x, self.bounds.y,
self.bounds.x + self.bounds.width, self.bounds.y,
})
love.graphics.setColor(0.3, 0.3, 0.3)
love.graphics.line({
self.bounds.x + self.bounds.width, self.bounds.y,
self.bounds.x + self.bounds.width, self.bounds.y + self.bounds.height,
self.bounds.x, self.bounds.y + self.bounds.height,
})
else
love.graphics.setColor(0.2, 0.2, 0.2)
love.graphics.line({
self.bounds.x + self.bounds.width, self.bounds.y,
self.bounds.x + self.bounds.width, self.bounds.y + self.bounds.height,
self.bounds.x, self.bounds.y + self.bounds.height,
})
love.graphics.setColor(0.3, 0.3, 0.3)
love.graphics.line({
self.bounds.x, self.bounds.y + self.bounds.height,
self.bounds.x, self.bounds.y,
self.bounds.x + self.bounds.width, self.bounds.y,
})
end
love.graphics.setColor(1, 1, 1)
end
return uiElement

View File

@ -64,26 +64,26 @@ function bottomBars.new(cid)
end
function bottomBars:update(dt)
local padding = 16
local padding = 8
local screenW, screenH = love.graphics.getDimensions()
self.bounds = Rect {
height = 10,
width = 200 + 200 + padding,
y = screenH - 96 - padding
height = 40 + 2 * padding,
width = screenW * 0.25,
y = screenH - 64 - 1 - 2 * padding - 40
}
self.transform = love.math.newTransform():translate(-self.bounds.width / 2 + screenW / 2, self.bounds.y)
for i = 1, #self.children do
self.children[i].bounds = Rect {
width = 200,
width = screenW * 0.25,
height = 20
}
self.children[i].transform = self.transform:clone():translate(padding * (i - 1) + (i - 1) * 200, 0)
self.children[i].transform = self.transform:clone():translate(0,
self.children[i].bounds.height * (i - 1) + (i - 1) * padding)
end
for _, el in ipairs(self.children) do
el:update(dt)
end
@ -101,18 +101,18 @@ function layout:update(dt)
if cid then
self.skillRow = SkillRow(cid)
self.skillRow:show()
self.bottomBars = bottomBars.new(cid)
-- self.bottomBars = bottomBars.new(cid)
elseif Tree.level.selector:deselected() then
self.skillRow:hide()
self.bottomBars = nil
-- self.bottomBars = nil
end
if self.skillRow then self.skillRow:update(dt) end
if self.bottomBars then self.bottomBars:update(dt) end
-- if self.bottomBars then self.bottomBars:update(dt) end
end
function layout:draw()
if self.skillRow then self.skillRow:draw() end
if self.bottomBars then self.bottomBars:draw() end
-- if self.bottomBars then self.bottomBars:draw() end
end
return layout

View File

@ -0,0 +1,2 @@
local UI_SCALE = 0.8 -- выдуманное значение для dependency injection
return UI_SCALE

View File

@ -4,15 +4,18 @@ local AnimationNode = require "lib.animation_node"
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
--- @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
@ -26,22 +29,32 @@ function skillButton:update(dt)
end
function skillButton:draw()
love.graphics.push()
love.graphics.applyTransform(self.transform)
love.graphics.setLineWidth(2)
local r, g, b, a = love.graphics.getColor()
if self.selected then
love.graphics.setColor(0.3, 1, 0.3, a)
elseif self.hovered then
love.graphics.setColor(0.7, 1, 0.7, a)
else
love.graphics.setColor(1, 1, 1, a)
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
love.graphics.translate(0, self.bounds.y)
love.graphics.draw(icons.atlas, icons:pickQuad(self.icon))
if self.selected then
love.graphics.setColor(0.3, 1, 0.3)
elseif self.hovered then
love.graphics.setColor(0.7, 1, 0.7)
else
love.graphics.setColor(1, 1, 1)
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")
end
--------------------------------------------------------------------------------
@ -88,6 +101,10 @@ function skillRow.new(characterId)
end
end)
for i = #t.children + 1, 7, 1 do
t.children[i] = skillButton:new {}
end
return t
end
@ -121,32 +138,51 @@ end
function skillRow:update(dt)
if self.animationNode then self.animationNode:update(dt) end
local iconSize = icons.tileSize
local scale = (64 / iconSize)
local iconSize = 64 * UI_SCALE
local screenW, screenH = love.graphics.getDimensions()
local padding = 8
local count = #self.children
local padding, margin = 8, 4
local count = #self.children -- слоты под скиллы
self.bounds = Rect {
width = count * icons.tileSize + (count - 1) * padding,
height = iconSize,
y = self.state == "show" and 10 * (1 - self.animationNode:getValue()) or 0
width = iconSize * count + (count + 1) * margin,
height = iconSize + 2 * margin,
}
self.transform = love.math.newTransform():translate(screenW / 2,
screenH - 16):scale(scale, scale):translate(-self.bounds.width / 2, -iconSize)
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 { height = iconSize, width = iconSize }
skb.transform = self.transform:clone():translate(self.bounds.x + (i - 1) * iconSize +
(i - 1) *
padding, -- левый край ряда + размер предыдущих иконок + размер предыдущих отступов
self.bounds.y -- высота не меняется
)
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()
love.graphics.setCanvas(c)
love.graphics.clear()
-- шум
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")
--граница
self:drawBorder("outer")
love.graphics.setColor(1, 1, 1)
for _, skb in ipairs(self.children) do
skb:draw()
end
love.graphics.setCanvas()
local alpha = 1
if self.state == "show" then
alpha = self.animationNode:getValue()
@ -154,9 +190,7 @@ function skillRow:draw()
alpha = 1 - self.animationNode:getValue()
end
love.graphics.setColor(1, 1, 1, alpha)
for _, skb in ipairs(self.children) do
skb:draw()
end
love.graphics.draw(c)
end
return skillRow.new

View File

@ -18,7 +18,7 @@ function rect.new(table)
end
function rect:hasPoint(x, y)
return x >= self.x and x < self.width and y >= self.y and y < self.height
return x >= self.x and x < self.x + self.width and y >= self.y and y < self.y + self.height
end
return rect.new

View File

@ -18,7 +18,7 @@ function love.load()
end
Tree.level.turnOrder:endRound()
print("Now playing:", Tree.level.turnOrder.current)
love.window.setMode(1080, 720, { resizable = true, msaa = 4, vsync = true })
love.window.setMode(1280, 720, { resizable = false, msaa = 0, vsync = true })
end
local lt = "0"