#include "ui_defs.lua" #include "ui_animators.lua" #include "ui_object.lua" Ui.GetBBox = function(uiObjects) local top = uiObjects[1].y local bottom = uiObjects[1].y + uiObjects[1].h local left = uiObjects[1].x local right = uiObjects[1].x + uiObjects[1].w for _, obj in ipairs(uiObjects) do if top > obj.y then top = obj.y end if bottom < obj.y + obj.h then bottom = obj.y + obj.h end if left > obj.x then left = obj.x end if right < obj.x + obj.w then right = obj.x + obj.w end end return { x = left, y = top, w = right - left, h = bottom - top } end function Ui.Window(obj) local window = Ui.Object:new { blur = true, modal = true, interactable = true, allowHide = true, clip = false, visible = false, fitToContent = false, animator = Ui.CreateAnimator(), isClosed = true, tasks = { queue = {}, push = function(self, task) table.insert(self.queue, task) end, execute = function(self) for _, task in ipairs(self.queue) do task() end self.queue = {} end }, onInit = function(self) end, onBeginClosing = function(self) end, onClose = function(self) end, onShow = function(self) end, onDraw = function(self) end, onLogicUpdate = function(self) end, show = function(self, needShow) self.visible = needShow == nil or needShow self.forceClose = false if self.visible then UiAddDrawObject(self) if not self._inited then self:_init() end if self.isClosed and self.animator.isFinished then self.animator:playForward() self.requestShow = true self:onShow() end else self:hide() end end, restore = function(self) if self.canRestore and not self:canRestore() then return end if not self._inited then self:_init() end self.animator:reset(1.0) self.visible = true self.isClosed = false UiAddDrawObject(self) if self.onRestore then self:onRestore() end end, hide = function(self) if self.canHide and not self:canHide() then return end if not self.isClosed and self.animator.isFinished then self.animator:playBackwards() self.requestHide = true self:onBeginClosing() end end, draw = function(self) UiPush() UiTranslateToPositionOnScreen(self.x, self.y) self.animator:draw(function() if self.animator.factor ~= 0 then if self.interactable and self.modal then UiModalBegin(true) end end self:_logicUpdate() if self.interactable then UiMakeInteractive() end self:_draw() end) UiPop() end, _draw = function(self) if self.animator.factor == 0 then return end self:onDraw() if self.background then self.background.w = self.w self.background.h = self.h end for _,child in ipairs(self.children) do UiTranslateToWindowTopLeft(child.x, child.y) UiPush() child:getSize() child:draw() UiPop() end end, _init = function(self) self:onInit() self._inited = true if self.background then tableMove(self.children, self.background, 1) end end, _logicUpdate = function(self) if self.requestShow and self.animator.isFinished then self.requestShow = false self.isClosed = false end if self.requestHide and self.animator.isFinished or self.forceClose then self.requestHide = false self.isClosed = true self.visible = false self:onClose() UiRemoveDrawObject(self) end if self.fitToContent then local bbox = Ui.GetBBox(tableFilter(self.children, function(it) return not it.resizeToParent end)) self.w = bbox.x + bbox.w self.h = bbox.y + bbox.h end if self.interactable and self.allowHide then if not UiIsMouseInRect(self.w, self.h) and InputPressed("lmb") then self:hide() end if InputPressed("esc") then self:hide() end if InputPressed("menu_cancel") then self:hide() end end if not self.isClosed then self:onLogicUpdate() end end, _inited = false, _requestShow = false, _requestHide = false, } window.animator.onAnimationUpdate = function(self, factor) UiTranslate(self.parent.w / 2, self.parent.h / 2) UiAlign("middle center") if self.parent.blur then UiBlur(factor) end UiColorFilter(1, 1, 1, factor) UiScale(factor) UiWindow(self.parent.w, self.parent.h, self.parent.clip) UiAlign("top left") UiTranslateToWindowTopLeft() end local wo = window:new(obj) wo.animator.parent = wo return wo end