From a72dfc07114d6d2f21e551deaa46561bccc7ed9d Mon Sep 17 00:00:00 2001 From: Kazhnuz Date: Fri, 4 Dec 2020 12:57:24 +0100 Subject: [PATCH] feat: refactor most menus --- birb/modules/menusystem/menus/flowbox.lua | 190 ++++++--------------- birb/modules/menusystem/menus/hlistbox.lua | 104 +++-------- birb/modules/menusystem/menus/listbox.lua | 103 +++-------- birb/modules/menusystem/menus/parent.lua | 62 ++++++- 4 files changed, 159 insertions(+), 300 deletions(-) diff --git a/birb/modules/menusystem/menus/flowbox.lua b/birb/modules/menusystem/menus/flowbox.lua index c3d9426..87a1f8a 100644 --- a/birb/modules/menusystem/menus/flowbox.lua +++ b/birb/modules/menusystem/menus/flowbox.lua @@ -26,205 +26,115 @@ local cwd = (...):gsub('%.flowbox$', '') .. "." local Menu = require(cwd .. "parent") local FlowBox = Menu:extend() -local menuutils = require(cwd .. "widgets.utils") +local View2D = require(cwd .. "utils.view2D") -- INIT FUNCTIONS -- Initialize and configure the flowbox function FlowBox:new(menusystem, name, x, y, w, h, slots_hor, slots_vert) - self.view = {} - self.view.slotNumber = slots_hor * slots_vert - self.view.lineNumber = slots_vert - self.view.colNumber = slots_hor - self.view.firstSlot = 1 + self.view = View2D(slots_hor, slots_vert) FlowBox.super.new(self, menusystem, name, x, y, w, h) - self.widget.h = math.floor( self.h / slots_vert ) - self.widget.w = math.floor( self.w / slots_hor ) - self.h = slots_vert * self.widget.h -- On fait en sorte que la hauteur - self.w = slots_hor * self.widget.w -- et la largeur + self:setRealSize() +end + +function FlowBox:setRealSize() + -- On fait en sorte que la hauteur et la largeur -- soit un multiple du nombre de slot et de leur dimensions + self:updateWidgetSize() + self.w = self.view.colNumber * self.widgetSize.w + self.h = self.view.lineNumber * self.widgetSize.h end -- UPDATE FUNCTIONS -- Update the menu and its view function FlowBox:updateWidgetSize() - self.widget.h = math.floor( self.h / self.view.lineNumber ) - self.widget.w = math.floor( self.w / self.view.colNumber ) + self.widgetSize.h = math.floor( self.h / self.view.lineNumber ) + self.widgetSize.w = math.floor( self.w / self.view.colNumber ) end function FlowBox:update(dt) - self:updateView() -end - -function FlowBox:updateView() - local col, line = self:getCoord(self.widget.selected) - local begincol, beginline = self:getCoord(self.view.firstSlot) - - if line < beginline then - beginline = line - end - - if line > beginline + self.view.lineNumber - 1 then - beginline = line - self.view.lineNumber + 1 - end - - if beginline < 0 then - beginline = 0 - end - - self.view.firstSlot = beginline * self.view.colNumber + 1 -end - --- INFO FUNCTIONS --- Get informations - -function FlowBox:getCoord(id_selected) - id_selected = id_selected - 1 -- On simplifie les calcul en prenant 0 comme départ - local line, col - line = math.floor(id_selected / self.view.colNumber) - col = id_selected - (line * self.view.colNumber) - return col, line + self.view:updateFirstSlot(self.widget:getSelected()) end -- CURSOR FUNCTIONS -- Handle the cursor in a 2D menu -function FlowBox:moveCursor(new_col, new_line) - local col, line = self:getCoord(self.widget.selected) - local lastcol, lastline = self:getCoord(#self.widget.list) +function FlowBox:moveCursor2D(new_col, new_line) + local lastcol, lastline = self.view:getCoord(self.widget:lenght()) - - if new_line < 0 then - new_line = lastline - end - - if new_line > lastline then - new_line = 0 - end + new_line = utils.math.wrapAndLimit(new_line, 0, lastline) if (new_line == lastline) then - if new_col < 0 then - new_col = lastcol - end - - if new_col > lastcol then - if (line == lastline) then - new_col = 0 - else - new_col = lastcol - end - end + new_col = utils.math.wrapAndLimit(new_col, 0, lastcol) else - if new_col < 0 then - new_col = self.view.colNumber - 1 - end - - if new_col == self.view.colNumber then - new_col = 0 - end + new_col = utils.math.wrapAndLimit(new_col, 0, (self.view.colNumber - 1)) end - self.widget.selected = (new_line * self.view.colNumber) + new_col + 1 + self.widget:moveCursor((new_line * self.view.colNumber) + new_col + 1) end -- KEYS FUNCTIONS -- Handle the keyboard/controller inputs -function FlowBox:keyreleased(key, code) - local col, line = self:getCoord(self.widget.selected) +function FlowBox:moveByKeys(key) + local col, line = self.view:getCoord(self.widget:getSelected()) if key == 'left' then - self:moveCursor(col - 1, line) + self:moveCursor2D(col - 1, line) end if key == 'right' then - self:moveCursor(col + 1, line) + self:moveCursor2D(col + 1, line) end if key == 'up' then - self:moveCursor(col, line - 1) + self:moveCursor2D(col, line - 1) end if key == 'down' then - self:moveCursor(col, line + 1) - end - - if key == "A" then - if (self.widget.selected >= 1 and self.widget.selected <= #self.widget.list) then - self.widget.list[self.widget.selected]:action("key") - end + self:moveCursor2D(col, line + 1) end end --- MOUSE FUNCTIONS --- Handle the mouse/touch pointer - -function FlowBox:mousemoved(x, y) - local col, line = self:getCoord(self.widget.selected) - local begincol, beginline = self:getCoord(self.view.firstSlot) - local newcol, newline, widget_selected - - newline = beginline + math.floor(y / self.widget.h) - newcol = math.floor(x / self.widget.w) - widget_selected = (newline * self.view.colNumber) + newcol + 1 - - if widget_selected >= 1 and widget_selected <= #self.widget.list then - self.widget.selected = widget_selected - self:getFocus() - end -end - -function FlowBox:mousepressed(x, y, button, isTouch) - local col, line = self:getCoord(self.widget.selected) - local begincol, beginline = self:getCoord(self.view.firstSlot) - local newline, newcol, widget_selected - - newline = beginline + math.floor(y / self.widget.h) - newcol = math.floor(x / self.widget.w) - widget_selected = (newline * self.view.colNumber) + newcol + 1 - - if widget_selected >= 1 and widget_selected <= #self.widget.list then - self.widget.selected = widget_selected - self:getFocus() - self.widget.list[self.widget.selected]:action("pointer") - end +-- POSITION FUNCTIONS +-- Get a widget by a position. +function FlowBox:getWidgetAtPoint(x, y) + local col = math.floor(x / self.widgetSize.w) + local line = math.floor(y / self.widgetSize.h) + return self.view:getFromCoord(col, line) end -- DRAW FUNCTIONS -- Draw the menu and its content function FlowBox:draw() - self:updateView() + self.view:updateFirstSlot(self.widget:getSelected()) local widgety = self.y local widgetx = self.x - for i,v in ipairs(self.widget.list) do - if (i >= self.view.firstSlot) and (i < self.view.firstSlot + self.view.slotNumber) then - v:draw(widgetx, widgety, self.widget.w, self.widget.h) - if self.widget.selected == i and self:haveFocus() == true then - v:drawSelected(widgetx, widgety, self.widget.w, self.widget.h) - else - v:draw(widgetx, widgety, self.widget.w, self.widget.h) - end - widgetx = widgetx + self.widget.w - if widgetx == (self.x + self.w) then + + local listWidget = self.widget:getList(self.view.firstSlot, self.view.slotNumber) + + for _, widget in ipairs(listWidget) do + widget:drawWidget(widgetx, widgety, self.w, self.widgetSize.h) + + -- On calcule la position du prochain widget + widgetx = widgetx + self.widgetSize.w + if widgetx >= (self.x + self.w) then widgetx = self.x - widgety = widgety + self.widget.h + widgety = widgety + self.widgetSize.h end - end end end -function FlowBox:drawCursor() - self:updateView() - local begincol, beginline = self:getCoord(self.view.firstSlot) - if (self.widget.selected >= 1 and self.widget.selected <= #self.widget.list) then - local w, h = self:getWidgetSize() - local col, line = self:getCoord(self.widget.selected) - local x = (col) * h - local y = (line - beginline) * h - menuutils.drawCursor(self.x + x, self.y + y, w, h) - end +function FlowBox:getGraphicalCursorPosition() + self.view:updateFirstSlot(self.widget:getSelected()) + local _, beginline = self.view:getCoord(self.view.firstSlot) + local w, h = self:getWidgetSize() + local col, line = self.view:getCoord(self.widget:getSelected()) + local x = (col) * h + local y = (line - beginline) * h + return self.x + x, self.y + y, w, h end return FlowBox diff --git a/birb/modules/menusystem/menus/hlistbox.lua b/birb/modules/menusystem/menus/hlistbox.lua index 067de32..6f9bbf6 100644 --- a/birb/modules/menusystem/menus/hlistbox.lua +++ b/birb/modules/menusystem/menus/hlistbox.lua @@ -27,16 +27,15 @@ local Menu = require(cwd .. "parent") local HListBox = Menu:extend() local menuutils = require(cwd .. "widgets.utils") +local View1D = require(cwd .. "utils.view1D") -- INIT FUNCTIONS -- Initialize and configure functions. function HListBox:new(menusystem, name, x, y, w, h, slotNumber) - self.view = {} - self.view.slotNumber = slotNumber - self.view.firstSlot = 1 + self.view = View1D(slotNumber) HListBox.super.new(self, menusystem, name, x, y, w, h) - self.w = slotNumber * self.widget.w -- On fait en sorte que la hauteur + self.w = slotNumber * self.widgetSize.w -- On fait en sorte que la hauteur -- soit un multiple du nombre de slot et de leur hauteur end @@ -44,105 +43,56 @@ end -- Update the menu every step. function HListBox:updateWidgetSize() - self.widget.h = self.h - self.widget.w = math.floor( self.w / self.view.slotNumber ) + self.widgetSize.h = self.h + self.widgetSize.w = math.floor( self.w / self.view.slotNumber ) end function HListBox:update(dt) - self:updateView() -end - -function HListBox:updateView() - if self.widget.selected < self.view.firstSlot then - self.view.firstSlot = self.widget.selected - end - if self.widget.selected > self.view.firstSlot + self.view.slotNumber - 1 then - self.view.firstSlot = self.widget.selected - self.view.slotNumber + 1 - end - - if self.view.firstSlot < 1 then - self.view.firstSlot = 1 - end + self.view:updateFirstSlot(self.widget:getSelected()) end -- KEYBOARD FUNCTIONS -- Handle key check. -function HListBox:keyreleased(key, code) - +function HListBox:moveByKeys(key, code) if key == 'left' then - self:moveCursor(self.widget.selected - 1) + self.widget:moveCursor(-1) end if key == 'right' then - self:moveCursor(self.widget.selected + 1) - end - - if key == "A" then - if (self.widget.selected >= 1 and self.widget.selected <= #self.widget.list) then - self.widget.list[self.widget.selected]:action("key") - end - end - - if key == "B" then - if (self.widget.cancel >= 1 and self.widget.cancel <= #self.widget.list) then - self.widget.list[self.widget.cancel]:action("key") - end - end - -end - --- MOUSE FUNCTIONS --- Click and stuff like that. - -function HListBox:mousemoved(x, y) - local widget_selected = self.view.firstSlot + math.floor(x / self.widget.w) - - if widget_selected >= 1 and widget_selected <= #self.widget.list then - self.widget.selected = widget_selected - self:getFocus() + self.widget:moveCursor(1) end end -function HListBox:mousepressed(x, y, button, isTouch) - local widget_selected = self.view.firstSlot + math.floor(x / self.widget.w) - - if widget_selected >= 1 and widget_selected <= #self.widget.list then - self.widget.selected = widget_selected - self:getFocus() - if #self.widget.list > 0 then - self.widget.list[self.widget.selected]:action("pointer") - end - end +-- POSITION FUNCTIONS +-- Get a widget by a position. +function HListBox:getWidgetAtPoint(x, y) + return (self.view.firstSlot + math.floor(x / self.widgetSize.w)) end -- DRAW FUNCTIONS -- Draw the menu and its content function HListBox:draw() - self:updateView() + self.view:updateFirstSlot(self.widget:getSelected()) + local widgetx = self.x - for i,v in ipairs(self.widget.list) do - if (i >= self.view.firstSlot) and (i < self.view.firstSlot + self.view.slotNumber) then - v:draw(widgetx, self.y, self.widget.w, self.h) - if self.widget.selected == i and self:haveFocus() == true then - v:drawSelected(widgetx, self.y, self.widget.w, self.h) - else - v:draw(widgetx, self.y, self.widget.w, self.h) - end - widgetx = widgetx + self.widget.w - end + + local listWidget = self.widget:getList(self.view.firstSlot, self.view.slotNumber) + + for _, widget in ipairs(listWidget) do + widget:drawWidget(widgetx, self.y, self.widgetSize.w, self.h) + widgetx = widgetx + self.widgetSize.w end end -function HListBox:drawCursor() - self:updateView() - if (self.widget.selected >= 1 and self.widget.selected <= #self.widget.list) then - local w, h = self:getWidgetSize() - local x = (self.widget.selected - self.view.firstSlot) * w - menuutils.drawCursor(self.x + x,self.y, w, h) - end +function HListBox:getGraphicalCursorPosition() + self.view:updateFirstSlot(self.widget:getSelected()) + local w, h = self:getWidgetSize() + local x = (self.widget:getSelected() - self.view.firstSlot) * w + + return self.x + x,self.y, w, h end return HListBox diff --git a/birb/modules/menusystem/menus/listbox.lua b/birb/modules/menusystem/menus/listbox.lua index 19c2ea2..ce19de7 100644 --- a/birb/modules/menusystem/menus/listbox.lua +++ b/birb/modules/menusystem/menus/listbox.lua @@ -27,16 +27,15 @@ local Menu = require(cwd .. "parent") local ListBox = Menu:extend() local menuutils = require(cwd .. "widgets.utils") +local View1D = require(cwd .. "utils.view1D") -- INIT FUNCTIONS -- Initialize and configure functions. function ListBox:new(menusystem, name, x, y, w, h, slotNumber) - self.view = {} - self.view.slotNumber = slotNumber - self.view.firstSlot = 1 + self.view = View1D(slotNumber) ListBox.super.new(self, menusystem, name, x, y, w, h) - self.h = slotNumber * self.widget.h -- On fait en sorte que la hauteur + self.h = slotNumber * self.widgetSize.h -- On fait en sorte que la hauteur -- soit un multiple du nombre de slot et de leur hauteur end @@ -44,105 +43,55 @@ end -- Update the menu every step. function ListBox:updateWidgetSize() - self.widget.h = math.floor( self.h / self.view.slotNumber ) - self.widget.w = self.w + self.widgetSize.h = math.floor( self.h / self.view.slotNumber ) + self.widgetSize.w = self.w end function ListBox:update(dt) - self:updateView() -end - -function ListBox:updateView() - if self.widget.selected < self.view.firstSlot then - self.view.firstSlot = self.widget.selected - end - if self.widget.selected > self.view.firstSlot + self.view.slotNumber - 1 then - self.view.firstSlot = self.widget.selected - self.view.slotNumber + 1 - end - - if self.view.firstSlot < 1 then - self.view.firstSlot = 1 - end + self.view:updateFirstSlot(self.widget:getSelected()) end -- KEYBOARD FUNCTIONS -- Handle input from keyboard/controllers. -function ListBox:keyreleased(key, code) - +function ListBox:moveByKeys(key) if key == 'up' then - self:moveCursor(self.widget.selected - 1) + self.widget:moveCursor(-1) end if key == 'down' then - self:moveCursor(self.widget.selected + 1) - end - - if key == "A" then - if (self.widget.selected >= 1 and self.widget.selected <= #self.widget.list) then - self.widget.list[self.widget.selected]:action("key") - end - end - - if key == "B" then - if (self.widget.cancel >= 1 and self.widget.cancel <= #self.widget.list) then - self.widget.list[self.widget.cancel]:action("key") - end - end - -end - --- MOUSE FUNCTIONS --- Handle input from pointers. - -function ListBox:mousemoved(x, y) - local widget_selected = self.view.firstSlot + math.floor(y / self.widget.h) - - if widget_selected >= 1 and widget_selected <= #self.widget.list then - self.widget.selected = widget_selected - self:getFocus() + self.widget:moveCursor(1) end end -function ListBox:mousepressed(x, y, button, isTouch) - local widget_selected = self.view.firstSlot + math.floor(y / self.widget.h) - - if widget_selected >= 1 and widget_selected <= #self.widget.list then - self.widget.selected = widget_selected - self:getFocus() - if #self.widget.list > 0 then - self.widget.list[self.widget.selected]:action("pointer") - end - end +-- POSITION FUNCTIONS +-- Get a widget by a position. +function ListBox:getWidgetAtPoint(x, y) + return (self.view.firstSlot + math.floor(y / self.widgetSize.h)) end -- DRAW FUNCTIONS -- draw the menu and the rest of content. function ListBox:draw() - self:updateView() + self.view:updateFirstSlot(self.widget:getSelected()) local widgety = self.y - for i,v in ipairs(self.widget.list) do - if (i >= self.view.firstSlot) and (i < self.view.firstSlot + self.view.slotNumber) then - v:draw(self.x, widgety, self.w, self.widget.h) - if self.widget.selected == i and self:haveFocus() == true then - v:drawSelected(self.x, widgety, self.w, self.widget.h) - else - v:draw(self.x, widgety, self.w, self.widget.h) - end - widgety = widgety + self.widget.h - end + + local listWidget = self.widget:getList(self.view.firstSlot, self.view.slotNumber) + + for _, widget in ipairs(listWidget) do + widget:drawWidget(self.x, widgety, self.w, self.widgetSize.h) + widgety = widgety + self.widgetSize.h end end -function ListBox:drawCursor() - self:updateView() - if (self.widget.selected >= 1 and self.widget.selected <= #self.widget.list) then - local w, h = self:getWidgetSize() - local y = (self.widget.selected - self.view.firstSlot) * h - menuutils.drawCursor(self.x,self.y + y, w, h) - end +function ListBox:getGraphicalCursorPosition() + self.view:updateFirstSlot(self.widget:getSelected()) + local w, h = self:getWidgetSize() + local y = (self.widget:getSelected() - self.view.firstSlot) * h + + return self.x,self.y + y, w, h end return ListBox diff --git a/birb/modules/menusystem/menus/parent.lua b/birb/modules/menusystem/menus/parent.lua index 0f1a093..8707896 100644 --- a/birb/modules/menusystem/menus/parent.lua +++ b/birb/modules/menusystem/menus/parent.lua @@ -26,6 +26,7 @@ local GuiElement = require "birb.modules.menusystem.parent" local Menu = GuiElement:extend() local MenuModel = require "birb.modules.menusystem.menus.utils.menumodel" +local menuUtils = require "birb.modules.menusystem.menus.widgets.utils" -- INIT FUNCTIONS -- Initialize and configure functions. @@ -34,11 +35,55 @@ function Menu:new(menusystem, name, x, y, w, h) self.menusystem = self:getGui() self.widget = MenuModel() + self.widgetSize = {} self:updateWidgetSize() self:resetSound() end +-- INTERACTION FUNCTIONS +-- Keyboard and mouse + +function Menu:keyreleased(key) + self:moveByKeys(key) + self:actionAndCancel(key) +end + +function Menu:mousemoved(x, y) + local widgetID = self:getWidgetAtPoint(x, y) + + if (widgetID ~= nil) then + if self.widget:trySelectWidget(widgetID) then + self:getFocus() + end + end +end + +function Menu:mousepressed(x, y, button, istouch) + local widgetID = self:getWidgetAtPoint(x, y) + + if (widgetID ~= nil) then + if self.widget:trySelectWidget(widgetID) then + self:getFocus() + self.widget:action(widgetID, "pointer") + end + end +end + +function Menu:moveByKeys(key) + -- Cette fonction ne contient rien par défaut +end + +function Menu:actionAndCancel(key) + if key == "A" then + self.widget:selectedAction() + end + + if key == "B" then + self.widget:cancelAction() + end +end + -- ACTION FUNCTIONS -- Send actions to the widgets @@ -69,12 +114,13 @@ end function Menu:drawElement() self:draw() if (self:haveFocus()) then - self:drawCursor() + local x, y, w, h = self:getGraphicalCursorPosition() + self:drawGraphicalCursor(x, y, w, h) end end -function Menu:drawCursor() - -- nothing here +function Menu:drawGraphicalCursor(x, y, w, h) + menuUtils.drawCursor(x, y, w, h) end function Menu:drawCanvas() @@ -93,18 +139,22 @@ function Menu:setCancelWidget(id) end function Menu:updateWidgetSize() - self.widget.h = 0 - self.widget.w = 0 + self.widgetSize.h = 0 + self.widgetSize.w = 0 end function Menu:getWidgetSize(id) - return self.widget.w, self.widget.h + return self.widgetSize.w, self.widgetSize.h end function Menu:getWidgetNumber() return self.widget:lenght() end +function Menu:getWidgetAtPoint(x, y) + +end + -- CURSOR FUNCTIONS -- Set or move the cursor of the menu