diff --git a/lib/simple_ui/core/builder.lua b/lib/simple_ui/core/builder.lua index c256918..8d9ada5 100644 --- a/lib/simple_ui/core/builder.lua +++ b/lib/simple_ui/core/builder.lua @@ -62,6 +62,7 @@ function builder:build_step(cur) local storedState = self:getStateOf(cur) if not storedState then self.states[key] = self:initStateOf(cur) + cur.state = self.states[key] else cur.state = storedState end diff --git a/lib/simple_ui/elements/placeholder.lua b/lib/simple_ui/elements/placeholder.lua index c4b175d..e66194e 100644 --- a/lib/simple_ui/elements/placeholder.lua +++ b/lib/simple_ui/elements/placeholder.lua @@ -15,11 +15,12 @@ function element:layout() end function element:draw() - love.graphics.rectangle("line", self._offset_.x, self._offset_.y, self._size_.x, self._size_.y) - love.graphics.line(self._offset_.x, self._offset_.y, self._offset_.x + self._size_.x, self._offset_.y + self._size_ - .y) - love.graphics.line(self._offset_.x, self._offset_.y + self._size_.y, self._offset_.x + self._size_.x, self._offset_ - .y) + love.graphics.setLineStyle("rough") + love.graphics.rectangle("line", 0, 0, self._size_.x, self._size_.y) + + love.graphics.line(0, 0, self._size_.x, self._size_.y) + love.graphics.line(0, self._size_.y, self._size_.x, 0) + love.graphics.setLineStyle("smooth") end --- @return Placeholder diff --git a/lib/simple_ui/elements/scale.lua b/lib/simple_ui/elements/scale.lua new file mode 100644 index 0000000..9849839 --- /dev/null +++ b/lib/simple_ui/elements/scale.lua @@ -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 diff --git a/lib/simple_ui/elements/screen_area.lua b/lib/simple_ui/elements/screen_area.lua index 60a1dfb..9d3b8ad 100644 --- a/lib/simple_ui/elements/screen_area.lua +++ b/lib/simple_ui/elements/screen_area.lua @@ -1,13 +1,26 @@ 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.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() - local screenW, screenH = love.graphics.getWidth(), love.graphics.getHeight() + local screenW, screenH = self.state.canvas:getDimensions() + self._constraints_ = Constraints { maxWidth = screenW, maxHeight = screenH @@ -20,10 +33,37 @@ function element:layout() self._child_._offset_ = Vec3 {} 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 ---- @param values {child: UIElement?} +--- @param values {key: any, dimensions: Rect?, filter: "nearest" | "linear" | nil, child: UIElement?} 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 return element diff --git a/lib/simple_ui/level/test.lua b/lib/simple_ui/level/test.lua index 7d0682c..f13abfe 100644 --- a/lib/simple_ui/level/test.lua +++ b/lib/simple_ui/level/test.lua @@ -1,9 +1,10 @@ +local Rect = require "lib.simple_ui.core.rect" local ScreenArea = require "lib.simple_ui.elements.screen_area" local Placeholder = require "lib.simple_ui.elements.placeholder" local Padding = require "lib.simple_ui.elements.padding" local Builder = require "lib.simple_ui.core.builder" 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 StatefulElement = require "lib.simple_ui.core.stateful_element" @@ -77,7 +78,6 @@ function MyWidget:build() height = 100, child = Placeholder:new {} }, - SizedBox:new { width = 100, height = 100, @@ -86,20 +86,29 @@ function MyWidget:build() SizedBox:new { width = 100, height = 100, - child = Placeholder:new {} + child = Placeholder:new {}, }, }, - }, } } end return Builder { - debugDraw = true, + -- debugDraw = true, builder = function() - return ScreenArea:new { - child = MyWidget:new {} + return Scale: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 } diff --git a/main.lua b/main.lua index 38f1e43..6ca204b 100644 --- a/main.lua +++ b/main.lua @@ -12,6 +12,8 @@ end function love.load() love.window.setMode(1280, 720, { resizable = true, msaa = 4, vsync = true }) + love.graphics.setDefaultFilter("nearest") + require "lib/tree" -- важно это сделать после настройки окна testLayout = require "lib.simple_ui.level.test"