From 0c3f4a10f03acf28f02ba80a1d9630ebc15f0496 Mon Sep 17 00:00:00 2001 From: Kazhnuz Date: Thu, 14 Feb 2019 18:32:52 +0100 Subject: [PATCH] core/menusystem: make the grid system use free widget placement It'll make it way more easy to use and maintain compared to the old "parent/children" system, and will be more flexible. --- .../core/modules/menusystem/grid.lua | 267 +++++------------- sonic-boost.love/scenes/test_scene/init.lua | 14 +- 2 files changed, 77 insertions(+), 204 deletions(-) diff --git a/sonic-boost.love/core/modules/menusystem/grid.lua b/sonic-boost.love/core/modules/menusystem/grid.lua index 97f59bf..a85b4e8 100644 --- a/sonic-boost.love/core/modules/menusystem/grid.lua +++ b/sonic-boost.love/core/modules/menusystem/grid.lua @@ -22,13 +22,17 @@ function GridBox:new(menusystem, name, x, y, w, h, colNumber, lineNumber) -- La gridbox possède la particularité de pouvoir fusioner des slots, on fait -- donc une liste de slots disponibles, qui serviront par la suite. self.slots = {} - for i= 1, self.view.slotNumber do - self.slots[i] = {} - self.slots[i].height = 1 - self.slots[i].width = 1 - self.slots[i].parent = 0 - self.slots[i].widgetID = i - end +end + +function GridBox:addSlot(widgetID, x, y, w, h) + local slot = {} + slot.x = x + slot.y = y + slot.w = w + slot.h = h + slot.widgetID = widgetID + + table.insert(self.slots, slot) end function GridBox:updateWidgetSize() @@ -38,15 +42,31 @@ end function GridBox:getWidgetSize(id) local slot = self:getWidgetSlot(id) - return self.widget.w * self.slots[slot].width, self.widget.h * self.slots[slot].height + if slot == 0 then + return 1, 1 + else + return self.widget.w * self.slots[slot].w, self.widget.h * self.slots[slot].h + end +end + +function GridBox:getSlotHitbox(slot) + local x, y, w, h + x = self.slots[slot].x * self.widget.w + y = self.slots[slot].y * self.widget.h + w = self.slots[slot].w * self.widget.w + h = self.slots[slot].h * self.widget.h + + return x, y, w, h end function GridBox:getWidgetID(slot) - if (self.slots[slot].parent == 0) then - return self.slots[slot].widgetID + local widgetID + if self.slots[slot] ~= nil then + widgetID = self.slots[slot].widgetID else - return self.slots[self.slots[slot].parent].widgetID + widgetID = 0 end + return widgetID end function GridBox:haveWidget(slot) @@ -65,145 +85,45 @@ function GridBox:getWidgetSlot(widgetID) return slot end +function GridBox:getWidgetAtPoint(x, y) + local x = x or 0 + local y = y or 0 + local widgetID = nil + + for i,v in ipairs(self.slots) do + local xx, yy, ww, hh = self:getSlotHitbox(i) + print(i, xx, yy, ww, hh, x, y) + if (x >= xx) and (y >= yy) and (x < xx + ww) and (y < yy + hh) then + widgetID = v.widgetID + end + end + + return widgetID +end + function GridBox:update(dt) self.view.firstSlot = 1 - local slotID = self:getSlotbyCoord(self.cursor.x, self.cursor.y) - if self.slots[slotID].parent > 0 then - slotID = self.slots[slotID].parent - end - self.widget.selected = self.slots[slotID].widgetID - self.cursor.x, self.cursor.y = self:getCoord(slotID) -end - -function GridBox:regenSlots() - local widgetID = 1 - for i,v in ipairs(self.slots) do - if v.parent == 0 and (widgetID <= #self.widget.list) then - self.slots[i].widgetID = widgetID - widgetID = widgetID + 1 - end - end -end - -function GridBox:addCol(slotID) - local col, line = self:getCoord(slotID) - if (col + self.slots[slotID].width + 1) <= self.view.colNumber then - slotChild = slotID + self.slots[slotID].width - for i = 1, self.slots[slotID].height do - self.slots[slotChild + ((i-1)* self.view.colNumber)].parent = slotID - end - self.slots[slotID].width = self.slots[slotID].width + 1 - end -end - -function GridBox:addLine(slotID) - local col, line = self:getCoord(slotID) - if (line + self.slots[slotID].height + 1) <= self.view.colNumber then - slotChild = slotID + (self.slots[slotID].height * self.view.colNumber) - for i = 1, self.slots[slotID].width do - self.slots[slotChild + (i-1)].parent = slotID - end - self.slots[slotID].height = self.slots[slotID].height + 1 - end -end - -function GridBox: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 -end - -function GridBox:getSlotbyCoord(col, line) - return (line * self.view.colNumber) + col + 1 -end - -function GridBox:getSlot(widgetID) - local slotID - for i,v in ipairs(self.slots) do - if v.widgetID == widgetID then - return i - end - end - return 0 -end - -function GridBox:moveCursor(newcol, newline) - local col, line = self.cursor.x, self.cursor.y - self:moveCursorRelative(newcol - self.cursor.x, newline - self.cursor.y) -end - -function GridBox:moveCursorRelative(dx, dy) - - local i = 0 - self.cursor.x = self.cursor.x + dx - self.cursor.y = self.cursor.y + dy - self:fixCursorOverflow() - print(self.cursor.x, self.cursor.y, self:haveValidCursorPosition()) - while not(self:haveValidCursorPosition()) do - self.cursor.x = self.cursor.x + utils.math.sign(dx) - self.cursor.y = self.cursor.y + utils.math.sign(dy) - self:fixCursorOverflow() - print(self.cursor.x, self.cursor.y, self:haveValidCursorPosition()) - i = i + 1 - if i == 200 then - break - end - end - -end - -function GridBox:haveValidCursorPosition() - local newSlot = self:getSlotbyCoord(self.cursor.x, self.cursor.y) - local isValid = true - - if (self.slots[newSlot].parent > 0) or (self.slots[newSlot].widgetID > #self.widget.list) then - if (self.slots[newSlot].parent == previousSlot) or (self.slots[newSlot].widgetID > #self.widget.list) then - isValid = false - end - end - - return isValid -end - -function GridBox:fixCursorOverflow() - if self.cursor.x < 0 then - self.cursor.x = self.view.colNumber - 1 - end - - if self.cursor.x > self.view.colNumber - 1 then - self.cursor.x = 0 - end - - if self.cursor.y < 0 then - self.cursor.y = self.view.lineNumber - 1 - end - - if self.cursor.y > self.view.lineNumber - 1 then - self.cursor.y = 0 - end end function GridBox:keyreleased(key, code) - slotID = self:getSlot(self.widget.selected) + slotID = self:getWidgetSlot(self.widget.selected) local col, line = self.cursor.x, self.cursor.y if key == 'left' then --self:moveCol(-1) - self:moveCursor(col - 1, line) + --self:moveCursor(col - 1, line) end if key == 'right' then --self:moveCol(1) - self:moveCursor(col + 1, line) + --self:moveCursor(col + 1, line) end if key == 'up' then - self:moveCursor(col, line - 1) + --self:moveCursor(col, line - 1) end if key == 'down' then - self:moveCursor(col, line + 1) + --self:moveCursor(col, line + 1) end if key == "A" and self.widget.selected <= #self.widget.list then @@ -212,22 +132,12 @@ function GridBox:keyreleased(key, code) end function GridBox:mousemoved(x, y) - local col, line = self:getCoord(self.widget.selected) - local begincol, beginline = self:getCoord(self.view.firstSlot) - local newcol, newline - local newselect, slotID + local widgetID = self:getWidgetAtPoint(x, y) - newline = beginline + math.floor(y / self.widget.h) - newcol = math.floor(x / self.widget.w) - newselect = (newline * self.view.colNumber) + newcol + 1 - - if self:haveWidget(newselect) then - self.cursor.x = newcol - self.cursor.y = newline + if widgetID ~= nil then + self.widget.selected = widgetID + self:getFocus() end - print(self:haveWidget(newselect), newselect) - - self:getFocus() if self.widget.selected < 1 then self.widget.selected = 1 @@ -239,73 +149,40 @@ function GridBox:mousemoved(x, y) end function GridBox:mousepressed(x, y, button, isTouch) - local col, line = self:getCoord(self.widget.selected) - local begincol, beginline = self:getCoord(self.view.firstSlot) - local newcol, newline - local newselect, slotID + local widgetID = self:getWidgetAtPoint(x, y) - newline = beginline + math.floor(y / self.widget.h) - newcol = math.floor(x / self.widget.w) - newselect = (newline * self.view.colNumber) + newcol + 1 + if widgetID ~= nil then + self.widget.selected = widgetID + self:getFocus() - self:getFocus() - - if self.slots[newselect].parent > 0 then - slotID = self.slots[newselect].parent - else - slotID = newselect - end - - self.widget.selected = self.slots[slotID].widgetID - - if #self.widget.list > 0 and self.widget.selected > 1 and self.widget.selected <= #self.widget.list then - self.widget.list[self.widget.selected]:action() + if #self.widget.list > 0 and self.widget.selected > 1 and self.widget.selected <= #self.widget.list then + self.widget.list[self.widget.selected]:action() + end end end function GridBox:draw() - local widgety = self.y - local widgetx = self.x - self:regenSlots() -- On reget les slots au cas où :p for i,v in ipairs(self.slots) do - if (v.parent == 0) and (v.widgetID <= #self.widget.list) then - --self.widget.list[v.widgetID]:draw(widgetx, widgety, self.widget.w * v.width, self.widget.h * v.height) + if self:haveWidget(i) then + local widgetx = self.x + (v.x * self.widget.w) + local widgety = self.y + (v.y * self.widget.h) if self.widget.selected == v.widgetID and self:haveFocus() == true then - self.widget.list[v.widgetID]:drawSelected(widgetx, widgety, self.widget.w * v.width, self.widget.h * v.height) + self.widget.list[v.widgetID]:drawSelected(widgetx, widgety) else - self.widget.list[v.widgetID]:draw(widgetx, widgety, self.widget.w * v.width, self.widget.h * v.height) + self.widget.list[v.widgetID]:draw(widgetx, widgety) end end - if (v.parent > 0) and false then - love.graphics.setColor(255,255,255,128) - love.graphics.rectangle("fill", widgetx, widgety, self.widget.w, self.widget.h) - end - local col, line = self:getCoord(i) - - if (col == self.cursor.x) and (line == self.cursor.y) and false then - love.graphics.setColor(255,255,0,128) - love.graphics.rectangle("fill", widgetx, widgety, self.widget.w, self.widget.h) - end - - --love.graphics.setColor(0,0,0,10) - --love.graphics.rectangle("line", widgetx, widgety, self.widget.w, self.widget.h) - widgetx = widgetx + self.widget.w - if widgetx == (self.x + self.w) then - widgetx = self.x - widgety = widgety + self.widget.h - end end end function GridBox: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(self.widget.selected) - local col, line = self:getCoord(self.widget.selected) - local x = (col) * h - local y = (line - beginline) * h + local slot = self:getWidgetSlot(self.widget.selected) + local w, h = self:getWidgetSize(slot) + local x = self.slots[slot].x * self.widget.w + local y = self.slots[slot].y * self.widget.h menuutils.drawCursor(self.x + x, self.y + y, w, h) end end diff --git a/sonic-boost.love/scenes/test_scene/init.lua b/sonic-boost.love/scenes/test_scene/init.lua index 06c60de..bb71db2 100644 --- a/sonic-boost.love/scenes/test_scene/init.lua +++ b/sonic-boost.love/scenes/test_scene/init.lua @@ -67,19 +67,15 @@ function TestScene:new() Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base(self.menusystem.menus["testMenu2"]) - MenuType3(self.menusystem, "testMenu3", 164, 32 + 72, 24*8, 24*4, 8, 4) - self.menusystem.menus["testMenu3"]:addCol(1) - self.menusystem.menus["testMenu3"]:addCol(1) - self.menusystem.menus["testMenu3"]:addCol(1) - self.menusystem.menus["testMenu3"]:addCol(1) - self.menusystem.menus["testMenu3"]:addLine(1) - self.menusystem.menus["testMenu3"]:addLine(1) - self.menusystem.menus["testMenu3"]:addLine(2) - Widget.Base(self.menusystem.menus["testMenu3"]) + MenuType3(self.menusystem, "testMenu3", 164, 32 + 72, 24*8, 24*5, 8, 5) Widget.Base(self.menusystem.menus["testMenu3"]) Widget.Base(self.menusystem.menus["testMenu3"]) Widget.Base(self.menusystem.menus["testMenu3"]) Widget.Base(self.menusystem.menus["testMenu3"]) + self.menusystem.menus["testMenu3"]:addSlot(1, 0, 0, 4, 3) + self.menusystem.menus["testMenu3"]:addSlot(2, 0, 3, 5, 2) + self.menusystem.menus["testMenu3"]:addSlot(3, 5, 0, 3, 1) + self.menusystem.menus["testMenu3"]:addSlot(4, 5, 1, 3, 4) end