local Rect = require "lib.simple_ui.rect" local function makeGradientMesh(w, h, topColor, bottomColor) local vertices = { { 0, 0, 0, 0, topColor[1], topColor[2], topColor[3], topColor[4] }, -- левый верх { w, 0, 1, 0, topColor[1], topColor[2], topColor[3], topColor[4] }, -- правый верх { w, h, 1, 1, bottomColor[1], bottomColor[2], bottomColor[3], bottomColor[4] }, -- правый низ { 0, h, 0, 1, bottomColor[1], bottomColor[2], bottomColor[3], bottomColor[4] }, -- левый низ } local mesh = love.graphics.newMesh(vertices, "fan", "static") return mesh end --- @class UIElement --- @field bounds Rect Прямоугольник, в границах которого размещается элемент. Размеры и положение в экранных координатах --- @field overlayGradientMesh love.Mesh Общий градиент поверх элемента (интерполированный меш) local uiElement = {} uiElement.bounds = Rect {} uiElement.overlayGradientMesh = makeGradientMesh(1, 1, { 0, 0, 0, 0 }, { 0, 0, 0, 0.4 }); uiElement.__index = uiElement function uiElement:update(dt) end function uiElement:draw() end function uiElement:hitTest(screenX, screenY) return self.bounds:hasPoint(screenX, screenY) end --- @generic T : UIElement --- @param values table --- @param self T --- @return T function uiElement.new(self, values) values.bounds = values.bounds or Rect {} values.overlayGradientMesh = values.overlayGradientMesh or uiElement.overlayGradientMesh; return setmetatable(values, self) end --- Рисует границу вокруг элемента (с псевдо-затенением) --- @param type "outer" | "inner" --- @param width? number function uiElement:drawBorder(type, width) local w = width or 4 love.graphics.setLineWidth(w) 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.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, -- }) love.graphics.line({ self.bounds.x, self.bounds.y + self.bounds.height - w, self.bounds.x, self.bounds.y + w, }) love.graphics.line({ self.bounds.x + w, self.bounds.y, self.bounds.x + self.bounds.width - w, self.bounds.y, }) 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.line({ self.bounds.x + self.bounds.width, self.bounds.y + w, self.bounds.x + self.bounds.width, self.bounds.y + self.bounds.height - w, }) love.graphics.line({ self.bounds.x + self.bounds.width - w, self.bounds.y + self.bounds.height, self.bounds.x + w, self.bounds.y + self.bounds.height, }) end love.graphics.setColor(1, 1, 1) end --- рисует градиент поверх элемента function uiElement:drawGradientOverlay() love.graphics.push() love.graphics.translate(self.bounds.x, self.bounds.y) love.graphics.scale(self.bounds.width, self.bounds.height) love.graphics.setColor(1, 1, 1, 1) love.graphics.draw(self.overlayGradientMesh) love.graphics.pop() end return uiElement