- implemement Scale and virtual screen size for ScreenArea

- fix state management
- WIP
This commit is contained in:
PeaAshMeter 2026-06-10 02:57:28 +03:00
parent 1febc65922
commit 93a4d189da
6 changed files with 97 additions and 18 deletions

View File

@ -62,6 +62,7 @@ function builder:build_step(cur)
local storedState = self:getStateOf(cur) local storedState = self:getStateOf(cur)
if not storedState then if not storedState then
self.states[key] = self:initStateOf(cur) self.states[key] = self:initStateOf(cur)
cur.state = self.states[key]
else else
cur.state = storedState cur.state = storedState
end end

View File

@ -15,11 +15,12 @@ function element:layout()
end end
function element:draw() function element:draw()
love.graphics.rectangle("line", self._offset_.x, self._offset_.y, self._size_.x, self._size_.y) love.graphics.setLineStyle("rough")
love.graphics.line(self._offset_.x, self._offset_.y, self._offset_.x + self._size_.x, self._offset_.y + self._size_ love.graphics.rectangle("line", 0, 0, self._size_.x, self._size_.y)
.y)
love.graphics.line(self._offset_.x, self._offset_.y + self._size_.y, self._offset_.x + self._size_.x, self._offset_ love.graphics.line(0, 0, self._size_.x, self._size_.y)
.y) love.graphics.line(0, self._size_.y, self._size_.x, 0)
love.graphics.setLineStyle("smooth")
end end
--- @return Placeholder --- @return Placeholder

View File

@ -0,0 +1,26 @@
local SingleChildElement = require "lib.simple_ui.core.single_child_element"
--- @class Scale : SingleChildElement
--- @field sx number
--- @field sy number
local element = setmetatable({}, SingleChildElement)
element.__index = element
element.type = "Scale"
function element:draw()
love.graphics.push("transform")
love.graphics.translate(self._offset_.x, self._offset_.y)
love.graphics.scale(self.sx, self.sy)
if self._child_ then self._child_:draw() end
love.graphics.pop()
end
--- @return Scale
--- @param values {sx: number?, sy: number?, child: UIElement?}
function element:new(values)
values.sx = values.sx or 1
values.sy = values.sy or 1
return SingleChildElement.new(self, values)
end
return element

View File

@ -1,13 +1,26 @@
local Constraints = require "lib.simple_ui.core.constraints" local Constraints = require "lib.simple_ui.core.constraints"
local SingleChildElement = require "lib.simple_ui.core.single_child_element" local Rect = require "lib.simple_ui.core.rect"
local StatefulElement = require "lib.simple_ui.core.stateful_element"
--- @class ScreenArea : SingleChildElement
local element = setmetatable({}, SingleChildElement) --- @class ScreenArea : StatefulElement
--- @field dimensions Rect
--- @field filter "nearest" | "linear"
local element = setmetatable({}, StatefulElement)
element.__index = element element.__index = element
element.type = "ScreenArea" element.type = "ScreenArea"
function element:build()
local cw, ch = self.state.canvas:getDimensions()
if cw ~= self.dimensions.width or ch ~= self.dimensions.height then
self.state.canvas = self:initState().canvas -- в реальном мире оно не будет пересоздаваться каждый кадр
end
return self.child
end
function element:layout() function element:layout()
local screenW, screenH = love.graphics.getWidth(), love.graphics.getHeight() local screenW, screenH = self.state.canvas:getDimensions()
self._constraints_ = Constraints { self._constraints_ = Constraints {
maxWidth = screenW, maxWidth = screenW,
maxHeight = screenH maxHeight = screenH
@ -20,10 +33,37 @@ function element:layout()
self._child_._offset_ = Vec3 {} self._child_._offset_ = Vec3 {}
end end
function element:draw()
local oldCanvas = love.graphics.getCanvas()
love.graphics.push()
love.graphics.origin()
love.graphics.setCanvas(self.state.canvas)
love.graphics.clear()
if self._child_ then self._child_:draw() end
love.graphics.pop()
love.graphics.setCanvas(oldCanvas)
love.graphics.push("transform")
love.graphics.translate(self._offset_.x, self._offset_.y)
love.graphics.draw(self.state.canvas)
love.graphics.pop()
end
function element:initState()
local canvas = love.graphics.newCanvas(self.dimensions.width, self.dimensions.height)
canvas:setFilter(self.filter, self.filter)
return {
canvas = canvas
}
end
--- @return ScreenArea --- @return ScreenArea
--- @param values {child: UIElement?} --- @param values {key: any, dimensions: Rect?, filter: "nearest" | "linear" | nil, child: UIElement?}
function element:new(values) function element:new(values)
return SingleChildElement.new(self, values) if not values.dimensions then values.dimensions = Rect { width = love.graphics.getWidth(), height = love.graphics.getHeight() } end
if not values.filter then values.filter = "linear" end
return StatefulElement.new(self, values)
end end
return element return element

View File

@ -1,9 +1,10 @@
local Rect = require "lib.simple_ui.core.rect"
local ScreenArea = require "lib.simple_ui.elements.screen_area" local ScreenArea = require "lib.simple_ui.elements.screen_area"
local Placeholder = require "lib.simple_ui.elements.placeholder" local Placeholder = require "lib.simple_ui.elements.placeholder"
local Padding = require "lib.simple_ui.elements.padding" local Padding = require "lib.simple_ui.elements.padding"
local Builder = require "lib.simple_ui.core.builder" local Builder = require "lib.simple_ui.core.builder"
local Flex = require "lib.simple_ui.elements.flex" local Flex = require "lib.simple_ui.elements.flex"
local Center = require "lib.simple_ui.elements.center" local Scale = require "lib.simple_ui.elements.scale"
local SizedBox = require "lib.simple_ui.elements.sized_box" local SizedBox = require "lib.simple_ui.elements.sized_box"
local StatefulElement = require "lib.simple_ui.core.stateful_element" local StatefulElement = require "lib.simple_ui.core.stateful_element"
@ -77,7 +78,6 @@ function MyWidget:build()
height = 100, height = 100,
child = Placeholder:new {} child = Placeholder:new {}
}, },
SizedBox:new { SizedBox:new {
width = 100, width = 100,
height = 100, height = 100,
@ -86,20 +86,29 @@ function MyWidget:build()
SizedBox:new { SizedBox:new {
width = 100, width = 100,
height = 100, height = 100,
child = Placeholder:new {} child = Placeholder:new {},
}, },
}, },
}, },
} }
} }
end end
return Builder { return Builder {
debugDraw = true, -- debugDraw = true,
builder = function() builder = function()
return ScreenArea:new { return Scale:new {
child = MyWidget:new {} sx = 2,
sy = 2,
child = ScreenArea:new {
key = "screen",
dimensions = Rect {
width = love.graphics.getWidth() / 2,
height = love.graphics.getHeight() / 2
},
filter = "nearest",
child = MyWidget:new {}
}
} }
end end
} }

View File

@ -12,6 +12,8 @@ end
function love.load() function love.load()
love.window.setMode(1280, 720, { resizable = true, msaa = 4, vsync = true }) love.window.setMode(1280, 720, { resizable = true, msaa = 4, vsync = true })
love.graphics.setDefaultFilter("nearest")
require "lib/tree" -- важно это сделать после настройки окна require "lib/tree" -- важно это сделать после настройки окна
testLayout = require "lib.simple_ui.level.test" testLayout = require "lib.simple_ui.level.test"