Compare commits

..

40 commits

Author SHA1 Message Date
Kazhnuz
f347f47aab fix: port the option menu to the new menusystem 2021-01-30 09:19:37 +01:00
Kazhnuz
e8b796f978 fix: port to the new menusystem the pause menu 2021-01-30 09:19:22 +01:00
Kazhnuz
150aad86f1 fix: port mainMenu to the new Scene:start() API 2021-01-30 09:18:59 +01:00
Kazhnuz
baa5a24ce6 fix: initial ports of the basic scenes 2021-01-30 09:18:07 +01:00
Kazhnuz
8f1c326e6a fix: reset view on page change 2021-01-29 21:54:34 +01:00
Kazhnuz
f8910aefa4 feat(textwidget): label replacement 2021-01-24 15:44:24 +01:00
Kazhnuz
af6ceef38d improvement: add a way to start a scene after init 2021-01-24 15:44:07 +01:00
Kazhnuz
d3350e3938 feat: add a way to apply volume 2021-01-24 15:43:46 +01:00
Kazhnuz
99952487a9 fix: port main menu to textmenu 2021-01-23 18:31:40 +01:00
Kazhnuz
870a4f7118 feat: add a basic text menu 2021-01-23 18:30:45 +01:00
Kazhnuz
772becc1a8 feat(textwidget): extend API 2021-01-23 18:30:30 +01:00
Kazhnuz
92c10440a1 fix: search global asset only if there is no local 2021-01-23 11:28:40 +01:00
Kazhnuz
e5d8e699bc feat(asset): fail when an asset doesn't exist 2021-01-17 12:44:40 +01:00
Kazhnuz
b22cc2159f feat: add a fail log function 2021-01-17 12:44:25 +01:00
Kazhnuz
0f4b6daf73 feat: add padding to text widgets 2020-12-05 21:20:20 +01:00
Kazhnuz
72829eb02a feat: add multi-label support in text widget 2020-12-05 09:27:40 +01:00
Kazhnuz
49509001ab feat: add asset access to widgets 2020-12-05 09:23:46 +01:00
Kazhnuz
93bbf56047 chore: port the main menu to the new system 2020-12-05 09:02:42 +01:00
Kazhnuz
abfda56b14 feat: give the menu name to widgets 2020-12-05 09:02:22 +01:00
Kazhnuz
3ae96e4cfc feat: add a page system to menus 2020-12-05 09:01:41 +01:00
Kazhnuz
e2d029ab0f feat: add a function to get a menu 2020-12-04 20:55:01 +01:00
Kazhnuz
bb6cf14437 chore:move around menus sub-objects 2020-12-04 13:16:32 +01:00
Kazhnuz
a72dfc0711 feat: refactor most menus 2020-12-04 12:57:24 +01:00
Kazhnuz
7e697c3628 feat: add drawWidget
Let the widget handle if its selected or not
2020-12-04 12:55:48 +01:00
Kazhnuz
37fc1fc9be feat: add a selected color for text widgets 2020-12-04 12:54:57 +01:00
Kazhnuz
4ff85e2cc1 feat: add views for 1D and 2D menus 2020-12-04 12:00:43 +01:00
Kazhnuz
89bbf5fff2 feat: add a getter for selected widget 2020-12-04 12:00:28 +01:00
Kazhnuz
876d30671d feat(math): add a basic wrap and limit function 2020-12-04 11:59:32 +01:00
Kazhnuz
12b4b3fbc1 feat(menumodel): add a widget limit 2020-11-29 12:50:07 +01:00
Kazhnuz
a3e2da3972 fix(menumodel): fix for loop 2020-11-29 12:43:52 +01:00
Kazhnuz
b1cd9a6683 chore: refactor widget list in a menumodel class 2020-11-28 18:32:49 +01:00
Kazhnuz
d9b8b71672 chore: separate widgets into three files 2020-11-28 15:27:25 +01:00
Kazhnuz
7e7cfe3763 chore: create a generic guiElement 2020-11-28 14:17:48 +01:00
Kazhnuz
dca462803f chore: make the code more readable in menumanager 2020-11-27 19:35:00 +01:00
Kazhnuz
74d8e904b2 chore: put all menus in their own subfolder 2020-11-27 17:00:39 +01:00
Kazhnuz
4b66d15014 chore: port actors to rect and box 2020-11-27 16:03:07 +01:00
Kazhnuz
82cf59588a chore: port menu to rect 2020-11-27 16:02:54 +01:00
Kazhnuz
e58f197049 feat: initial version of physical entities for 3D 2020-11-27 16:02:39 +01:00
Kazhnuz
cf1928444f fix: remove some problems in point and rects 2020-11-27 16:02:21 +01:00
Kazhnuz
fb55c9e706 chore: extract shapes from actor3D 2020-11-27 11:15:57 +01:00
47 changed files with 2349 additions and 1346 deletions

View file

@ -67,10 +67,18 @@ function AssetManager:clearLocal()
end end
function AssetManager:get(name) function AssetManager:get(name)
local asset
if self.locals[name] ~= nil then if self.locals[name] ~= nil then
return self.locals[name] asset = self.locals[name]
else
asset = self.globals[name]
end
if (asset ~= nil) then
return asset
else
core.debug:fail("core.assets", "L'asset " .. name .. " n'existe pas.")
end end
return self.globals[name]
end end
-- Specific functions -- Specific functions

View file

@ -125,6 +125,17 @@ function DebugSystem:logError(context, string)
end end
end end
--- Log an error and fail
--
-- @param context the context of the log
-- @param string the logged string
function DebugSystem:fail(context, string)
if (self:isError()) then
print(self:createLogLine("ERROR", context, string))
error(string)
end
end
--- Create a formatted debug line --- Create a formatted debug line
-- --
-- @param level the level of the log -- @param level the level of the log

View file

@ -54,6 +54,10 @@ function MusicManager:haveMusic()
return (self.musics[1] ~= nil) return (self.musics[1] ~= nil)
end end
function MusicManager:applyVolume()
self.musics[1]:setVolume(self.core.options.data.audio.music / 100)
end
function MusicManager:playMusic() function MusicManager:playMusic()
if (self:haveMusic()) then if (self:haveMusic()) then
self.musics[1]:setVolume(self.core.options.data.audio.music / 100) self.musics[1]:setVolume(self.core.options.data.audio.music / 100)

View file

@ -43,6 +43,7 @@ function SceneManager:setScene(scene)
self:startTransition(scene) self:startTransition(scene)
else else
self.currentScene = scene self.currentScene = scene
self.currentScene:start()
self.currentScene.isActive = true self.currentScene.isActive = true
end end
end end
@ -73,12 +74,7 @@ end
function SceneManager:update(dt) function SceneManager:update(dt)
self.timers:update(dt) self.timers:update(dt)
if (self.currentScene ~= nil) then if (self.currentScene ~= nil) then
self.currentScene:updateStart(dt) self.currentScene:updateScene(dt)
self.currentScene:setKeys()
self.currentScene.menusystem:update(dt)
self.currentScene:updateWorld(dt)
self.currentScene:update(dt)
self.currentScene:updateEnd(dt)
end end
end end
@ -146,6 +142,7 @@ end
function SceneManager:timerResponse(timer) function SceneManager:timerResponse(timer)
if timer == "fadeOut" then if timer == "fadeOut" then
self.currentScene = self.transition.nextScene self.currentScene = self.transition.nextScene
self.currentScene:start()
self.currentScene:flushKeys(self.transition.duration / 2.5) self.currentScene:flushKeys(self.transition.duration / 2.5)
self.currentScene.isActive = false self.currentScene.isActive = false
core.screen:fadeOut(self.transition.duration / 2.5, self.transition.easeOut) core.screen:fadeOut(self.transition.duration / 2.5, self.transition.easeOut)
@ -162,11 +159,7 @@ end
function SceneManager:draw() function SceneManager:draw()
self.controller.screen:apply() self.controller.screen:apply()
if (self.currentScene ~= nil) then if (self.currentScene ~= nil) then
self.currentScene:drawStart() self.currentScene:drawScene()
self.currentScene:drawWorld()
self.currentScene:draw()
self.currentScene.menusystem:draw()
self.currentScene:drawEnd()
end end
self.controller.screen:cease() self.controller.screen:cease()
end end

View file

@ -1,230 +0,0 @@
-- flowbox :: flexible box menu, that handle in grid the widgets
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local cwd = (...):gsub('%.flowbox$', '') .. "."
local Menu = require(cwd .. "parent")
local FlowBox = Menu:extend()
local menuutils = require(cwd .. "widgets.utils")
-- 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
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
-- soit un multiple du nombre de slot et de leur dimensions
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 )
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
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)
if new_line < 0 then
new_line = lastline
end
if new_line > lastline then
new_line = 0
end
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
else
if new_col < 0 then
new_col = self.view.colNumber - 1
end
if new_col == self.view.colNumber then
new_col = 0
end
end
self.widget.selected = (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)
if key == 'left' then
self:moveCursor(col - 1, line)
end
if key == 'right' then
self:moveCursor(col + 1, line)
end
if key == 'up' then
self:moveCursor(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
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
end
-- DRAW FUNCTIONS
-- Draw the menu and its content
function FlowBox:draw()
self:updateView()
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
widgetx = self.x
widgety = widgety + self.widget.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
end
return FlowBox

View file

@ -1,148 +0,0 @@
-- hlistbox : add an horizontal list of widgets.
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local cwd = (...):gsub('%.hlistbox$', '') .. "."
local Menu = require(cwd .. "parent")
local HListBox = Menu:extend()
local menuutils = require(cwd .. "widgets.utils")
-- 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
HListBox.super.new(self, menusystem, name, x, y, w, h)
self.w = slotNumber * self.widget.w -- On fait en sorte que la hauteur
-- soit un multiple du nombre de slot et de leur hauteur
end
-- UPDATE FUNCTIONS
-- Update the menu every step.
function HListBox:updateWidgetSize()
self.widget.h = self.h
self.widget.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
end
-- KEYBOARD FUNCTIONS
-- Handle key check.
function HListBox:keyreleased(key, code)
if key == 'left' then
self:moveCursor(self.widget.selected - 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()
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
end
-- DRAW FUNCTIONS
-- Draw the menu and its content
function HListBox:draw()
self:updateView()
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
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
end
return HListBox

View file

@ -27,13 +27,13 @@ local cwd = (...):gsub('%.init$', '') .. "."
local MenuSystem = Object:extend() local MenuSystem = Object:extend()
-- Load the differents menu object to get an easy access -- Load the differents menu object to get an easy access
MenuSystem.Parent = require(cwd .. "parent") MenuSystem.Parent = require(cwd .. "menus.parent")
MenuSystem.ListBox = require(cwd .. "listbox") MenuSystem.ListBox = require(cwd .. "menus.listbox")
MenuSystem.FlowBox = require(cwd .. "flowbox") MenuSystem.FlowBox = require(cwd .. "menus.flowbox")
MenuSystem.Grid = require(cwd .. "grid") MenuSystem.Grid = require(cwd .. "menus.grid")
-- load widgets object -- load widgets object
MenuSystem.Widget = require(cwd .. "widgets") MenuSystem.Widget = require(cwd .. "menus.widgets")
-- INIT FUNCTIONS -- INIT FUNCTIONS
-- Initialize and configure the menu controller -- Initialize and configure the menu controller
@ -106,19 +106,23 @@ function MenuSystem:addMenu(name, menu)
self.menus[name] = menu self.menus[name] = menu
end end
function MenuSystem:getMenu(name)
return self.menus[name]
end
function MenuSystem:menuExist(name) function MenuSystem:menuExist(name)
return (self.menus[name] ~= nil) return (self.menus[name] ~= nil)
end end
function MenuSystem:switchMenu(menu) function MenuSystem:switchMenu(menuName)
for k,v in pairs(self.menus) do for name, guiElement in pairs(self.menus) do
if k == menu then if (name == menuName) then
v:getFocus() guiElement:getFocus()
v:setVisibility(true) guiElement:setVisibility(true)
v:setActivity(true) guiElement:setActivity(true)
else else
v:setVisibility(false) guiElement:setVisibility(false)
v:setActivity(false) guiElement:setActivity(false)
end end
end end
end end
@ -156,38 +160,39 @@ function MenuSystem:setMenuVisibility(menu, visibility)
end end
function MenuSystem:setAllMenuVisibility(visibility) function MenuSystem:setAllMenuVisibility(visibility)
for k,v in pairs(self.menus) do for _, guiElement in pairs(self.menus) do
v:setVisibility(visibility) guiElement:setVisibility(visibility)
end end
end end
function MenuSystem:setAllMenuActivity(activity) function MenuSystem:setAllMenuActivity(activity)
for k,v in pairs(self.menus) do for _, guiElement in pairs(self.menus) do
v.isActive = activity guiElement.isActive = activity
end end
end end
function MenuSystem:removeDestroyedMenus() function MenuSystem:removeDestroyedMenus()
-- On retire les entitées marquées comme supprimées -- On retire les entitées marquées comme supprimées
for k,v in pairs(self.menus) do for name, guiElement in pairs(self.menus) do
if (v.isDestroyed == true) then if (guiElement.isDestroyed == true) then
self.menus[k] = nil self.menus[name] = nil
end end
end end
end end
-- SOUND FUNCTIONS -- SOUND FUNCTIONS
-- Add sounds to every menus -- Add sounds to every menus
-- TODO: rework to be used directly by widgets later
function MenuSystem:setSoundFromSceneAssets(soundname) function MenuSystem:setSoundFromSceneAssets(soundname)
for k,v in pairs(self.menus) do for _, guiElement in pairs(self.menus) do
v:setSoundFromSceneAssets(soundname) guiElement:setSoundFromSceneAssets(soundname)
end end
end end
function MenuSystem:setSound(soundasset) function MenuSystem:setSound(soundasset)
for k,v in pairs(self.menus) do for _, guiElement in pairs(self.menus) do
v:setSound(soundasset) guiElement:setSound(soundasset)
end end
end end
@ -197,17 +202,16 @@ end
function MenuSystem:update(dt) function MenuSystem:update(dt)
if (self.isActive) then if (self.isActive) then
self:removeDestroyedMenus() self:removeDestroyedMenus()
for k,v in pairs(self.menus) do for _, guiElement in pairs(self.menus) do
v:update(dt) guiElement:updateElement(dt)
v:updateWidgets(dt)
end end
if self.menus[self.focusedMenu] ~= nil then if self.menus[self.focusedMenu] ~= nil then
-- Only check buttons if the current focused menu is actually active -- Only check buttons if the current focused menu is actually active
if self.menus[self.focusedMenu].isActive then if self.menus[self.focusedMenu].isActive then
for k,v in pairs(self.keys) do for keyname, keydata in pairs(self.keys) do
if self.keys[k].isPressed then if self.keys[keyname].isPressed then
self.menus[self.focusedMenu]:keyreleased(k) self.menus[self.focusedMenu]:keyreleased(keyname)
end end
end end
end end
@ -221,10 +225,11 @@ end
function MenuSystem:mousemoved(x, y, dx, dy) function MenuSystem:mousemoved(x, y, dx, dy)
if (self.isActive) then if (self.isActive) then
for k,v in pairs(self.menus) do for _, guiElement in pairs(self.menus) do
if v.isActive then if guiElement.isActive then
if (x > v.x) and (x < v.x + v.w) and (y > v.y) and (y < v.y + v.h) then if guiElement:areCoordInside(x, y) then
v:mousemoved(x - v.x, y - v.y) local xx, yy = guiElement:getRelativeCoordinate(x, y)
guiElement:mousemoved(xx, yy)
break; break;
end end
end end
@ -235,10 +240,11 @@ end
function MenuSystem:mousepressed( x, y, button, istouch ) function MenuSystem:mousepressed( x, y, button, istouch )
if (self.isActive) then if (self.isActive) then
for k,v in pairs(self.menus) do for _, guiElement in pairs(self.menus) do
if v.isActive then if guiElement.isActive then
if (x > v.x) and (x < v.x + v.w) and (y > v.y) and (y < v.y + v.h) then if guiElement:areCoordInside(x, y) then
v:mousepressed(x - v.x, y - v.y, button, istouch ) local xx, yy = guiElement:getRelativeCoordinate(x, y)
guiElement:mousepressed(xx, yy, button, istouch )
break; break;
end end
end end
@ -251,10 +257,10 @@ end
function MenuSystem:getDrawList() function MenuSystem:getDrawList()
local drawList = {} local drawList = {}
for k,v in pairs(self.menus) do for name, guiElement in pairs(self.menus) do
local drawObject = {} local drawObject = {}
drawObject.name = k drawObject.name = name
drawObject.depth = v.depth drawObject.depth = guiElement.depth
table.insert(drawList, drawObject) table.insert(drawList, drawObject)
end end
table.sort(drawList, function(a,b) return a.depth > b.depth end) table.sort(drawList, function(a,b) return a.depth > b.depth end)
@ -267,16 +273,10 @@ function MenuSystem:draw(dt)
-- Draw all the menus -- Draw all the menus
self.drawList = self:getDrawList() self.drawList = self:getDrawList()
for i,v in ipairs(self.drawList) do for _, drawObject in ipairs(self.drawList) do
local v2 = self.menus[v.name] local guiElement = self.menus[drawObject.name]
if (v2.isVisible) then if (guiElement.isVisible) then
v2:draw(dt) guiElement:drawElement(dt)
end
end
if self.menus[self.focusedMenu] ~= nil then
if (self.menus[self.focusedMenu].isVisible) then
self.menus[self.focusedMenu]:drawCursor()
end end
end end
end end

View file

@ -1,148 +0,0 @@
-- listbox : add a vertical list of widgets.
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local cwd = (...):gsub('%.listbox$', '') .. "."
local Menu = require(cwd .. "parent")
local ListBox = Menu:extend()
local menuutils = require(cwd .. "widgets.utils")
-- 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
ListBox.super.new(self, menusystem, name, x, y, w, h)
self.h = slotNumber * self.widget.h -- On fait en sorte que la hauteur
-- soit un multiple du nombre de slot et de leur hauteur
end
-- UPDATE FUNCTIONS
-- Update the menu every step.
function ListBox:updateWidgetSize()
self.widget.h = math.floor( self.h / self.view.slotNumber )
self.widget.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
end
-- KEYBOARD FUNCTIONS
-- Handle input from keyboard/controllers.
function ListBox:keyreleased(key, code)
if key == 'up' then
self:moveCursor(self.widget.selected - 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()
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
end
-- DRAW FUNCTIONS
-- draw the menu and the rest of content.
function ListBox:draw()
self:updateView()
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
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
end
return ListBox

View file

@ -0,0 +1,144 @@
-- flowbox :: flexible box menu, that handle in grid the widgets
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local cwd = (...):gsub('%.flowbox$', '') .. "."
local Menu = require(cwd .. "parent")
local FlowBox = Menu:extend()
local View2D = require(cwd .. "views.view2D")
-- INIT FUNCTIONS
-- Initialize and configure the flowbox
function FlowBox:new(menusystem, name, x, y, w, h, slots_hor, slots_vert)
self.view = View2D(slots_hor, slots_vert)
FlowBox.super.new(self, menusystem, name, x, y, w, h)
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
function FlowBox:resetView()
self.view:reset()
end
-- UPDATE FUNCTIONS
-- Update the menu and its view
function FlowBox:updateWidgetSize()
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.view:updateFirstSlot(self.widget:getSelected())
end
-- CURSOR FUNCTIONS
-- Handle the cursor in a 2D menu
function FlowBox:moveCursor2D(new_col, new_line)
local lastcol, lastline = self.view:getCoord(self.widget:lenght())
new_line = utils.math.wrapAndLimit(new_line, 0, lastline)
if (new_line == lastline) then
new_col = utils.math.wrapAndLimit(new_col, 0, lastcol)
else
new_col = utils.math.wrapAndLimit(new_col, 0, (self.view.colNumber - 1))
end
self.widget:moveCursor((new_line * self.view.colNumber) + new_col + 1)
end
-- KEYS FUNCTIONS
-- Handle the keyboard/controller inputs
function FlowBox:moveByKeys(key)
local col, line = self.view:getCoord(self.widget:getSelected())
if key == 'left' then
self:moveCursor2D(col - 1, line)
end
if key == 'right' then
self:moveCursor2D(col + 1, line)
end
if key == 'up' then
self:moveCursor2D(col, line - 1)
end
if key == 'down' then
self:moveCursor2D(col, line + 1)
end
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.view:updateFirstSlot(self.widget:getSelected())
local widgety = self.y
local widgetx = self.x
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.widgetSize.h
end
end
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

View file

@ -26,20 +26,16 @@ local cwd = (...):gsub('%.grid$', '') .. "."
local Menu = require(cwd .. "parent") local Menu = require(cwd .. "parent")
local GridBox = Menu:extend() local GridBox = Menu:extend()
local menuutils = require(cwd .. "widgets.utils") local View2D = require "birb.modules.menusystem.menus.views.view2D"
-- INIT FUNCTIONS -- INIT FUNCTIONS
-- Initialize and configure the menu -- Initialize and configure the menu
function GridBox:new(menusystem, name, x, y, w, h, colNumber, lineNumber) function GridBox:new(menusystem, name, x, y, w, h, colNumber, lineNumber)
self.view = {} self.view = View2D(colNumber, lineNumber)
self.view.slotNumber = colNumber * lineNumber
self.view.colNumber = colNumber
self.view.lineNumber = lineNumber
self.view.firstSlot = 1
GridBox.super.new(self, menusystem, name, x, y, w, h) GridBox.super.new(self, menusystem, name, x, y, w, h)
self.h = lineNumber * self.widget.h -- On fait en sorte que la hauteur self.h = lineNumber * self.widgetSize.h -- On fait en sorte que la hauteur
self.w = colNumber * self.widget.w -- et la largeur self.w = colNumber * self.widgetSize.w -- et la largeur
-- soit un multiple du nombre de slot et de leur dimensions -- soit un multiple du nombre de slot et de leur dimensions
self.cursor = {} self.cursor = {}
self.cursor.x = 0 self.cursor.x = 0
@ -56,14 +52,13 @@ function GridBox:addSlot(widgetID, x, y, w, h)
slot.y = y slot.y = y
slot.w = w slot.w = w
slot.h = h slot.h = h
slot.widgetID = widgetID
table.insert(self.slots, slot) table.insert(self.slots, slot)
end end
function GridBox:updateWidgetSize() function GridBox:updateWidgetSize()
self.widget.h = math.floor( self.h / self.view.lineNumber ) self.widgetSize.h = math.floor( self.h / self.view.lineNumber )
self.widget.w = math.floor( self.w / self.view.colNumber ) self.widgetSize.w = math.floor( self.w / self.view.colNumber )
end end
-- INFO FUNCTIONS -- INFO FUNCTIONS
@ -71,19 +66,19 @@ end
function GridBox:getWidgetSize(id) function GridBox:getWidgetSize(id)
local slot = self:getWidgetSlot(id) local slot = self:getWidgetSlot(id)
if slot == 0 then if (slot == 0) then
return 1, 1 return 1, 1
else else
return self.widget.w * self.slots[slot].w, self.widget.h * self.slots[slot].h return self.widgetSize.w * self.slots[slot].w, self.widgetSize.h * self.slots[slot].h
end end
end end
function GridBox:getSlotHitbox(slot) function GridBox:getSlotHitbox(slot)
local x, y, w, h local x, y, w, h
x = self.slots[slot].x * self.widget.w x = self.slots[slot].x * self.widgetSize.w
y = self.slots[slot].y * self.widget.h y = self.slots[slot].y * self.widgetSize.h
w = self.slots[slot].w * self.widget.w w = self.slots[slot].w * self.widgetSize.w
h = self.slots[slot].h * self.widget.h h = self.slots[slot].h * self.widgetSize.h
return x, y, w, h return x, y, w, h
end end
@ -142,11 +137,16 @@ function GridBox:update(dt)
self.view.firstSlot = 1 self.view.firstSlot = 1
end end
function GridBox:resetView()
self.view:reset()
end
-- KEYS FUNCTIONS -- KEYS FUNCTIONS
-- Handle the keyboard/manette functions -- Handle the keyboard/manette functions
function GridBox:keyreleased(key, code) function GridBox:keyreleased(key, code)
local slotID = self:getWidgetSlot(self.widget.selected) local slotID = self:getWidgetSlot(self.widget:getSelected())
local col, line = self.cursor.x, self.cursor.y local col, line = self.cursor.x, self.cursor.y
if key == 'left' then if key == 'left' then
self:moveCol(-1) self:moveCol(-1)
@ -164,13 +164,13 @@ function GridBox:keyreleased(key, code)
self:moveLine(1) self:moveLine(1)
end end
if key == "A" and self.widget.selected <= #self.widget.list then if key == "A" and self.widget:getSelected() <= self.widget:lenght() then
self.widget.list[self.widget.selected]:action("key") self.widget.list[self.widget:getSelected()]:action("key")
end end
end end
function GridBox:moveCol(direction) function GridBox:moveCol(direction)
local orig_x, orig_y = self:getSlotCenter(self.widget.selected) local orig_x, orig_y = self:getSlotCenter(self.widget:getSelected())
local distance = self.w -- on met directement à la distance max possible le système local distance = self.w -- on met directement à la distance max possible le système
local nearestWidget = 0 local nearestWidget = 0
for i,v in ipairs(self.slots) do for i,v in ipairs(self.slots) do
@ -185,13 +185,13 @@ function GridBox:moveCol(direction)
end end
end end
if nearestWidget ~= 0 then if (nearestWidget ~= 0) then
self.widget.selected = nearestWidget self.widget:setCursor(nearestWidget)
end end
end end
function GridBox:moveLine(direction) function GridBox:moveLine(direction)
local orig_x, orig_y = self:getSlotCenter(self.widget.selected) local orig_x, orig_y = self:getSlotCenter(self.widget:getSelected())
local distance = self.h -- on met directement à la distance max possible le système local distance = self.h -- on met directement à la distance max possible le système
local nearestWidget = 0 local nearestWidget = 0
for i,v in ipairs(self.slots) do for i,v in ipairs(self.slots) do
@ -206,8 +206,8 @@ function GridBox:moveLine(direction)
end end
end end
if nearestWidget ~= 0 then if (nearestWidget ~= 0) then
self.widget.selected = nearestWidget self.widget:setCursor(nearestWidget)
end end
end end
@ -217,31 +217,31 @@ end
function GridBox:mousemoved(x, y) function GridBox:mousemoved(x, y)
local widgetID = self:getWidgetAtPoint(x, y) local widgetID = self:getWidgetAtPoint(x, y)
if widgetID ~= nil then -- if (widgetID ~= nil) then
self.widget.selected = widgetID -- self.widget:getSelected() = widgetID
self:getFocus() -- self:getFocus()
end -- end
if self.widget.selected < 1 then -- if self.widget:getSelected() < 1 then
self.widget.selected = 1 -- self.widget:getSelected() = 1
end -- end
if self.widget.selected > #self.widget.list then -- if self.widget:getSelected() > self.widget:lenght() then
self.widget.selected = #self.widget.list -- self.widget:getSelected() = self.widget:lenght()
end -- end
end end
function GridBox:mousepressed(x, y, button, isTouch) function GridBox:mousepressed(x, y, button, isTouch)
local widgetID = self:getWidgetAtPoint(x, y) local widgetID = self:getWidgetAtPoint(x, y)
if widgetID ~= nil then -- if (widgetID ~= nil) then
self.widget.selected = widgetID -- self.widget:getSelected() = widgetID
self:getFocus() -- self:getFocus()
if #self.widget.list > 0 and self.widget.selected > 1 and self.widget.selected <= #self.widget.list then -- if self.widget:lenght() > 0 and self.widget:getSelected() > 1 and self.widget:getSelected() <= self.widget:lenght() then
self.widget.list[self.widget.selected]:action("pointer") -- self.widget.list[self.widget:getSelected()]:action("pointer")
end -- end
end -- end
end end
-- DRAW FUNCTIONS -- DRAW FUNCTIONS
@ -251,9 +251,9 @@ function GridBox:draw()
for i,v in ipairs(self.slots) do for i,v in ipairs(self.slots) do
if self:haveWidget(i) then if self:haveWidget(i) then
local widgetx = self.x + (v.x * self.widget.w) local widgetx = self.x + (v.x * self.widgetSize.w)
local widgety = self.y + (v.y * self.widget.h) local widgety = self.y + (v.y * self.widgetSize.h)
if self.widget.selected == v.widgetID and self:haveFocus() == true then if self.widget:getSelected() == v.widgetID and self:haveFocus() == true then
self.widget.list[v.widgetID]:drawSelected(widgetx, widgety) self.widget.list[v.widgetID]:drawSelected(widgetx, widgety)
else else
self.widget.list[v.widgetID]:draw(widgetx, widgety) self.widget.list[v.widgetID]:draw(widgetx, widgety)
@ -264,12 +264,12 @@ end
function GridBox:drawCursor() function GridBox:drawCursor()
self:updateView() self:updateView()
if (self.widget.selected >= 1 and self.widget.selected <= #self.widget.list) then if (self.widget:getSelected() >= 1 and self.widget:getSelected() <= self.widget:lenght()) then
local slot = self:getWidgetSlot(self.widget.selected) local slot = self:getWidgetSlot(self.widget:getSelected())
local w, h = self:getWidgetSize(slot) local w, h = self:getWidgetSize(slot)
local x = self.slots[slot].x * self.widget.w local x = self.slots[slot].x * self.widgetSize.w
local y = self.slots[slot].y * self.widget.h local y = self.slots[slot].y * self.widgetSize.h
menuutils.drawCursor(self.x + x, self.y + y, w, h) self:drawGraphicalCursor(self.x + x, self.y + y, w, h)
end end
end end

View file

@ -0,0 +1,101 @@
-- hlistbox : add an horizontal list of widgets.
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local cwd = (...):gsub('%.hlistbox$', '') .. "."
local Menu = require(cwd .. "parent")
local HListBox = Menu:extend()
local View1D = require(cwd .. "views.view1D")
-- INIT FUNCTIONS
-- Initialize and configure functions.
function HListBox:new(menusystem, name, x, y, w, h, slotNumber)
self.view = View1D(slotNumber)
HListBox.super.new(self, menusystem, name, x, y, w, h)
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
-- UPDATE FUNCTIONS
-- Update the menu every step.
function HListBox:updateWidgetSize()
self.widgetSize.h = self.h
self.widgetSize.w = math.floor( self.w / self.view.slotNumber )
end
function HListBox:update(dt)
self.view:updateFirstSlot(self.widget:getSelected())
end
function HListBox:resetView()
self.view:reset()
end
-- KEYBOARD FUNCTIONS
-- Handle key check.
function HListBox:moveByKeys(key, code)
if key == 'left' then
self.widget:moveCursor(-1)
end
if key == 'right' then
self.widget:moveCursor(1)
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.view:updateFirstSlot(self.widget:getSelected())
local widgetx = self.x
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: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

View file

@ -0,0 +1,100 @@
-- listbox : add a vertical list of widgets.
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local cwd = (...):gsub('%.listbox$', '') .. "."
local Menu = require(cwd .. "parent")
local ListBox = Menu:extend()
local View1D = require(cwd .. "views.view1D")
-- INIT FUNCTIONS
-- Initialize and configure functions.
function ListBox:new(menusystem, name, x, y, w, h, slotNumber)
self.view = View1D(slotNumber)
ListBox.super.new(self, menusystem, name, x, y, w, h)
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
-- UPDATE FUNCTIONS
-- Update the menu every step.
function ListBox:updateWidgetSize()
self.widgetSize.h = math.floor( self.h / self.view.slotNumber )
self.widgetSize.w = self.w
end
function ListBox:update(dt)
self.view:updateFirstSlot(self.widget:getSelected())
end
function ListBox:resetView()
self.view:reset()
end
-- KEYBOARD FUNCTIONS
-- Handle input from keyboard/controllers.
function ListBox:moveByKeys(key)
if key == 'up' then
self.widget:moveCursor(-1)
end
if key == 'down' then
self.widget:moveCursor(1)
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.view:updateFirstSlot(self.widget:getSelected())
local widgety = self.y
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: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

View file

@ -0,0 +1,189 @@
local MenuModel = Object:extend()
local Page = require "birb.modules.menusystem.menus.model.page"
local function updateWidgetByOrder(a, b)
if a.order ~= b.order then
return a.order < b.order
else
return a.creationID < b.creationID
end
end
-- INIT FUNCTIONS
-- Initialize and basic functions.
function MenuModel:new()
self:clear()
self.list = {}
self.selected = 0
self.selectedPrevious = 0
self.cancel = 0
self.limit = -1
-- self:updateWidgetSize()
end
function MenuModel:clear()
self.pages = {}
self:addPage("main")
end
-- PAGE FUNCTIONS
-- Handle pages
function MenuModel:addPage(pageName)
local page = Page()
self.pages[pageName] = page
self.currentPage = pageName
return page
end
function MenuModel:addSubmenu(pageName, parent)
local page = self:addPage(pageName)
page:setParent(parent)
end
function MenuModel:removePage(pageName)
self.pages[pageName] = nil
end
function MenuModel:pageExists(pageName)
return (self.pages[pageName] ~= nil)
end
function MenuModel:getPage(pageName)
return self.pages[pageName]
end
function MenuModel:switch(pageName)
if (self:pageExists(pageName)) then
self.currentPage = pageName
end
end
function MenuModel:back()
local page = self:getCurrentPage()
self:switch(page:getParent())
end
function MenuModel:getCurrentPage()
return self:getPage(self.currentPage)
end
-- UPDATE/DRAW FUNCTIONS
-- All the update functions
function MenuModel:update(dt)
local page = self:getCurrentPage()
page:update(dt)
end
function MenuModel:updateWidgetsOrder()
local page = self:getCurrentPage()
page:updateWidgetByOrder()
end
function MenuModel:updateWidgetsID()
local page = self:getCurrentPage()
page:updateWidgetsID()
end
-- ACTION FUNCTIONS
-- All the actions callback used by the widgets
function MenuModel:cancelAction()
local page = self:getCurrentPage()
page:cancelAction()
end
function MenuModel:action(id, type)
local page = self:getCurrentPage()
page:action(id, type)
end
function MenuModel:selectedAction()
local page = self:getCurrentPage()
page:selectedAction()
end
-- WIDGET FUNCTIONS
-- All the functions to handle widgets
function MenuModel:addWidget(newWidget)
local page = self:getCurrentPage()
page:addWidget(newWidget)
end
function MenuModel:getList(first, lenght)
local page = self:getCurrentPage()
return page:getList(first, lenght)
end
function MenuModel:removeDestroyedWidgets()
local page = self:getCurrentPage()
page:removeDestroyedWidgets()
end
function MenuModel:lenght()
local page = self:getCurrentPage()
return page:lenght()
end
function MenuModel:widgetExist(id)
local page = self:getCurrentPage()
return page:widgetExist(id)
end
function MenuModel:setLimit(limit)
local page = self:getCurrentPage()
page:setLimit(limit)
end
-- CANCEL FUNCTIONS
-- Add a widget as a "cancel" function
function MenuModel:setCancelWidget()
local page = self:getCurrentPage()
page:setCancelWidget()
end
function MenuModel:getCancelWidget()
local page = self:getCurrentPage()
return page:getCancelWidget()
end
-- CURSOR FUNCTIONS
-- Set or move the cursor of the menu
function MenuModel:getSelected()
local page = self:getCurrentPage()
return page:getSelected()
end
function MenuModel:haveCursor()
local page = self:getCurrentPage()
return page:haveCursor()
end
function MenuModel:trySelectWidget(cursorid)
local page = self:getCurrentPage()
return page:trySelectWidget(cursorid)
end
function MenuModel:setCursor(cursorid)
local page = self:getCurrentPage()
page:setCursor(cursorid)
end
function MenuModel:moveCursorAbsolute(newSelected)
local page = self:getCurrentPage()
page:moveCursorAbsolute(newSelected)
end
function MenuModel:moveCursor(relative)
local page = self:getCurrentPage()
page:moveCursor(relative)
end
return MenuModel

View file

@ -0,0 +1,185 @@
local Page = Object:extend()
local function updateWidgetByOrder(a, b)
if a.order ~= b.order then
return a.order < b.order
else
return a.creationID < b.creationID
end
end
-- INIT FUNCTIONS
-- Initialize and basic functions.
function Page:new()
self.widgets = {}
self.selected = 0
self.selectedPrevious = 0
self.cancel = 0
self.limit = -1
self.parent = nil
-- self:updateWidgetSize()
end
function Page:clear()
self.widgets = {}
self.cancel = 0
end
function Page:setLimit(limit)
self.limit = limit
end
-- PAGE FUNCTIONS
-- functions to handle other pages
function Page:setParent(parent)
self.parent = parent
end
function Page:getParent()
return self.parent
end
-- UPDATE/DRAW FUNCTIONS
-- All the update functions
function Page:update(dt)
self:removeDestroyedWidgets()
for id, widget in ipairs(self.widgets) do
widget.id = id
widget:update(dt)
end
end
function Page:updateWidgetsOrder()
table.sort(self.widgets, updateWidgetByOrder)
end
function Page:updateWidgetsID()
for id, widget in ipairs(self.widgets) do
widget.id = id
end
end
-- ACTION FUNCTIONS
-- All the actions callback used by the widgets
function Page:cancelAction()
if (self.cancel ~= 0) then
self:action(self.cancel, "key")
end
end
function Page:action(id, type)
if (self:widgetExist(id)) then
self.widgets[id]:action(type)
end
end
function Page:selectedAction()
if (self.selected ~= 0) then
self:action(self.selected, "key")
end
end
-- WIDGET FUNCTIONS
-- All the functions to handle widgets
function Page:addWidget(newWidget)
if (self.limit ~= -1 and #self.widgets >= self.limit) then
return
end
if #self.widgets == 0 then
self.selected = 1
end
table.insert(self.widgets, newWidget)
self:updateWidgetsID()
self:updateWidgetsOrder()
end
function Page:getList(first, lenght)
local listWidget = {}
local first = first or 1
local lenght = lenght or #self.widgets
lenght = math.min(lenght, (#self.widgets + 1 - first))
local last = (first + lenght - 1)
for i = first, (last) do
table.insert(listWidget, self.widgets[i])
end
return listWidget
end
function Page:removeDestroyedWidgets() -- On retire les widgets marquées comme supprimées
for i, v in ipairs(self.widgets) do
if (v.destroyed == true) then
table.remove(self.widgets, i)
end
end
end
function Page:lenght()
return #self.widgets
end
function Page:widgetExist(id)
local id = id or 0
return (id >= 1 and id <= #self.widgets)
end
-- CANCEL FUNCTIONS
-- Add a widget as a "cancel" function
function Page:setCancelWidget(id)
self.cancel = #self.widgets
end
function Page:getCancelWidget(id)
return self.cancel
end
-- CURSOR FUNCTIONS
-- Set or move the cursor of the menu
function Page:getSelected()
return self.selected
end
function Page:haveCursor()
return self:widgetExist(self.selected)
end
function Page:trySelectWidget(cursorid)
if (self:widgetExist(cursorid)) then
self:setCursor(cursorid)
return true
else
return false
end
end
function Page:setCursor(cursorid)
self.selected = cursorid --math.max(1, math.min(cursorid, #self.widgets))
end
function Page:moveCursorAbsolute(newSelected)
-- self:playNavigationSound()
if newSelected < 1 then
self.selected = #self.widgets + newSelected
else
if newSelected > #self.widgets then
self.selected = newSelected - #self.widgets
else
self.selected = newSelected
end
end
end
function Page:moveCursor(relative)
self:moveCursorAbsolute(self.selected + relative)
end
return Page

View file

@ -0,0 +1,242 @@
-- parent.lua : The parent of the functions.
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local GuiElement = require "birb.modules.menusystem.parent"
local Menu = GuiElement:extend()
local MenuModel = require "birb.modules.menusystem.menus.model"
local menuUtils = require "birb.modules.menusystem.utils"
-- INIT FUNCTIONS
-- Initialize and configure functions.
function Menu:new(menusystem, name, x, y, w, h)
Menu.super.new(self, 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
-- PAGE FUNCTIONS
-- Wrapper around pages functions from the model
function Menu:addPage(pageName)
self.widget:addPage(pageName)
end
function Menu:addSubmenu(pageName, parent)
self.widget:addSubmenu(pageName, parent)
end
function Menu:removePage(pageName)
self.widget:removePage(pageName)
end
function Menu:pageExists(pageName)
return self.widget:pageExists(pageName)
end
function Menu:getPage(pageName)
self.widget:getPage(pageName)
end
function Menu:switch(pageName)
self.widget:switch(pageName)
self:resetView()
end
function Menu:back()
self.widget:back()
self:resetView()
end
-- ACTION FUNCTIONS
-- Send actions to the widgets
function Menu:cancelAction()
self.widget:cancelAction()
end
function Menu:clear()
self.widget:clear()
end
function Menu:resize(x,y,w,h)
self:set(x,y,w,h)
self:updateWidgetSize()
end
-- UPDATE FUNCTIONS
function Menu:updateElement(dt)
self:update(dt)
self.widget:update(dt)
end
-- DRAW FUNCTIONS
-- Draw the menu and its content
function Menu:drawElement()
self:draw()
if (self:haveFocus()) then
local x, y, w, h = self:getGraphicalCursorPosition()
self:drawGraphicalCursor(x, y, w, h)
end
end
function Menu:drawGraphicalCursor(x, y, w, h)
menuUtils.drawCursor(x, y, w, h)
end
function Menu:drawCanvas()
end
-- WIDGET FUNCTIONS
-- Handle widgets of the functions
function Menu:addWidget(newwidget)
self.widget:addWidget(newwidget)
end
function Menu:setCancelWidget(id)
self.widget:setCancelWidget(id)
end
function Menu:updateWidgetSize()
self.widgetSize.h = 0
self.widgetSize.w = 0
end
function Menu:getWidgetSize(id)
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
function Menu:setCursor(cursorid)
self.widget:setCursor(cursorid)
end
function Menu:moveCursor(new_selected)
self:playNavigationSound()
self.widget:moveCursorAbsolute(new_selected)
end
-- SOUND FUNCTION
-- Handle SFX
function Menu:resetSound()
self.sound = {}
self.sound.active = false
self.sound.asset = nil
end
function Menu:setSoundFromSceneAssets(name)
self:setSound(self.menusystem.scene.assets:getWithType(name, "sfx"))
end
function Menu:setSound(soundasset)
self.sound.active = true
self.sound.asset = soundasset
end
function Menu:playNavigationSound()
if self.sound.active == true then
self.sound.asset:play()
end
end
-- VIEW FUNCTIONS
-- Handle the view of the menu
function Menu:resetView()
-- ne sert à rien ici, c'est juste pour éviter des crash
end
function Menu:updateView()
-- ne sert à rien ici, c'est juste pour éviter des crash
end
function Menu:moveView()
-- ne sert à rien ici, c'est juste pour éviter des crash
end
return Menu

View file

@ -0,0 +1,49 @@
-- view1D.lua : A basic 1D view for menus.
-- Must be used as a subobject of a Menu
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local View1D = Object:extend()
function View1D:new(slotNumber)
self.slotNumber = slotNumber
self.firstSlot = 1
end
function View1D:reset()
self.firstSlot = 1
print("reset")
end
function View1D:updateFirstSlot(widgetID)
self.firstSlot = math.max(1, widgetID - (self.slotNumber - 1), math.min(widgetID, self.firstSlot))
end
function View1D:isBeforeView(x)
return (x < self.firstSlot)
end
function View1D:isAfterView(x)
return (x >= (self.firstSlot + self.slotNumber))
end
return View1D

View file

@ -0,0 +1,61 @@
-- view2D.lua : A basic 2D view for menus.
-- Must be used as a subobject of a Menu
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local View1D = require "birb.modules.menusystem.menus.views.view1D"
local View2D = View1D:extend()
function View2D:new(colNumber, lineNumber)
self.colNumber = colNumber
self.lineNumber = lineNumber
View2D.super.new(self, (colNumber * lineNumber))
end
function View2D:updateFirstSlot(widgetID)
local _, line = self:getCoord(widgetID)
local _, beginline = self:getCoord(self.firstSlot)
beginline = math.min(line, math.max(0, beginline, line - (self.lineNumber - 1)))
self.view.firstSlot = (beginline * self.view.colNumber) + 1
end
-- INFO FUNCTIONS
-- Get informations
function View2D:getCoord(x)
-- On simplifie les calcul en prenant 0 comme départ
local x = x - 1
local line, col
line = math.floor(x / self.view.colNumber)
col = x - (line * self.view.colNumber)
return col, line
end
function View2D:getFromCoord(col, line)
local _, beginline = self.view:getCoord(self.view.firstSlot)
local line = beginline + line
return (line * self.view.colNumber) + col + 1
end
return View2D

View file

@ -0,0 +1,150 @@
-- widgets/base.lua :: basic widget object
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local BaseWidget = Object:extend()
-- INIT FUNCTIONS
-- Initialize and configure the widget
function BaseWidget:new(menuName)
self.menu = self:getMenuByName(menuName)
self.assets = self:getAssets()
self.destroyed = false
self.selectable = false
self.selection_margin = 0
self.margin = 2
self.canvas = {}
self.canvas.texture = nil
self.canvas.needRedraw = true
self.order = 0
self:register()
end
function BaseWidget:getMenuByName(name)
local gui = self:getGui()
return gui:getMenu(name)
end
function BaseWidget:getGui()
local scene = core.scenemanager.currentScene
return scene.menusystem
end
function BaseWidget:getAssets()
local scene = core.scenemanager.currentScene
return scene.assets
end
function BaseWidget:register()
self.creationID = self.menu:getWidgetNumber()
self.menu:addWidget(self)
end
function BaseWidget:redrawCanvas()
self.width, self.height = self.menu:getWidgetSize(self.id)
local canvas = love.graphics.newCanvas(self.width, self.height)
love.graphics.setCanvas(canvas)
self:drawCanvas()
self.canvas.needRedraw = false
love.graphics.setCanvas()
local imageData = canvas:newImageData()
self.canvas.texture = love.graphics.newImage(imageData)
canvas:release()
imageData:release()
end
function BaseWidget:invalidateCanvas()
self.canvas.needRedraw = true
end
function BaseWidget:drawCanvas()
self.r = love.math.random(128) / 256
self.g = love.math.random(128) / 256
self.b = love.math.random(128) / 256
love.graphics.setColor(self.r, self.g, self.b, 70)
love.graphics.rectangle("fill", 0, 0, self.width, self.height)
love.graphics.setColor(self.r, self.g, self.b)
love.graphics.rectangle("line", 0, 0, self.width, self.height)
utils.graphics.resetColor()
end
function BaseWidget:selectAction()
-- Do nothing
end
-- DRAW WIDGETS
-- Draw the widget
function BaseWidget:drawWidget(x, y, w, h)
if (self:haveFocus()) then
self:drawSelected(x, y, w, h)
else
self:draw(x, y, w, h)
end
end
function BaseWidget:draw(x, y, w, h)
if self.canvas.texture ~= nil then
love.graphics.draw(self.canvas.texture, x, y)
end
end
function BaseWidget:drawSelected(x, y, w, h)
self:draw(x, y, w, h)
end
-- UPDATE FUNCTIONS
-- Update the widget
function BaseWidget:update(dt)
if (self.canvas.needRedraw) then
self:redrawCanvas()
end
-- N/A
end
-- FOCUS FUNCTIONS
-- Detect if the widget have focus
function BaseWidget:haveFocus()
return (self.menu:haveFocus() and self.menu.widget:getSelected() == self.id)
end
-- ACTION FUNCTION
-- Functions to handle actions and selection.
function BaseWidget:action(source)
--self:destroy()
end
function BaseWidget:destroy()
self.destroyed = true
end
return BaseWidget

View file

@ -0,0 +1,30 @@
-- widgets :: basic widget object
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local Widget = {}
-- Add the widget as subvariable to the returned table
Widget.Base = require "birb.modules.menusystem.menus.widgets.base"
Widget.Text = require "birb.modules.menusystem.menus.widgets.text"
return Widget

View file

@ -0,0 +1,95 @@
-- widgets/text.lua :: basic text widget object
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local BaseWidget = require "birb.modules.menusystem.menus.widgets.base"
local TextWidget = BaseWidget:extend()
-- TEXT WIDGET
-- Simple text widget
function TextWidget:new(menuName, font, label, position, padding)
TextWidget.super.new(self, menuName)
self.font = font
self.labels = {}
self.padding = padding or 0
-- We add the first label
local position = position or "center"
self:addLabel(label, position)
self:setSelectedColor(1, 1, 1)
end
function TextWidget:addLabel(label, position)
local complexLabel = {}
complexLabel.label = label
complexLabel.position = position
table.insert(self.labels, complexLabel)
end
function TextWidget:replaceLabel(id, newLabel)
self.labels[id].label = newLabel
end
function TextWidget:setSelectedColor(r, g, b)
self.selectedColor = {}
self.selectedColor.r = r
self.selectedColor.g = g
self.selectedColor.b = b
end
function TextWidget:getFont()
return self.assets:getFont(self.font)
end
function TextWidget:getSelectedColor()
return self.selectedColor.r, self.selectedColor.g, self.selectedColor.b
end
function TextWidget:getPadding()
return self.padding
end
function TextWidget:drawCanvas()
local w, h
local font = self:getFont()
h = math.floor(self.height / 2) - (font:getHeight() / 2)
for _, complexLabel in pairs(self.labels) do
if (complexLabel.position == "center") then
w = math.floor(self.width / 2)
elseif (complexLabel.position == "left") then
w = self:getPadding()
elseif (complexLabel.position == "right") then
w = math.floor(self.width - self:getPadding())
end
font:draw(complexLabel.label, w, h, -1, complexLabel.position)
end
end
function TextWidget:drawSelected(x, y, w, h)
local r, g, b = self:getSelectedColor()
love.graphics.setColor(r, g, b, 1)
self:draw(x, y)
utils.graphics.resetColor()
end
return TextWidget

View file

@ -1,289 +1,119 @@
-- parent.lua : The parent of the functions. local Rect = require "birb.objects.2D.rect"
--[[ local GuiElement = Rect:extend()
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of function GuiElement:new(name, x, y, w, h)
this software and associated documentation files (the "Software"), to deal in GuiElement.super.new(self, x, y, w, h)
the Software without restriction, including without limitation the rights to self.name = name
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all self.isDestroyed = false
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local Menu = Object:extend()
local function updateWidgetByOrder(a, b)
if a.order ~= b.order then
return a.order < b.order
else
return a.creationID < b.creationID
end
end
-- INIT FUNCTIONS
-- Initialize and configure functions.
function Menu:new(menusystem, name, x, y, w, h)
self.menusystem = menusystem
self.name = name
self.x = x
self.y = y
self.w = w
self.h = h
self.widget = {}
self.widget.list = {}
self.widget.selected = 0
self.widget.selectedPrevious = 0
self.widget.cancel = 0
self:updateWidgetSize()
self.isDestroyed = false
self.isVisible = true
self.isActive = true
self.isLocked = false
self.isAlwaysVisible = false
self.depth = 0
self:resetSound()
self:register()
end
function Menu:setDepth(depth)
self.depth = depth or 0
end
function Menu:setVisibility(visibility)
if self.isLocked == false and self.isAlwaysVisible == false then
-- if the menu is locked (thus is always active), it should also
-- be always visible.
self.isVisible = visibility
else
self.isVisible = true self.isVisible = true
end
end
function Menu:setActivity(activity)
if self.isLocked == false then
self.isActive = activity
else
self.isActive = true self.isActive = true
end self.isLocked = false
self.isAlwaysVisible = false
self.depth = 0
self:register()
end end
function Menu:lock(lock) function GuiElement:getGui()
self.isLocked = lock local scene = core.scenemanager.currentScene
return scene.menusystem
end end
function Menu:lockVisibility(lock) function GuiElement:register()
self.isAlwaysVisible = lock local gui = self:getGui()
gui:addMenu(self.name, self)
end end
function Menu:getFocus() function GuiElement:destroy()
self.menusystem.focusedMenu = self.name self.destroyed = true
end end
function Menu:haveFocus() -- VISIBILITY/ACTIVITY
return (self.menusystem.focusedMenu == self.name) -- Handle drawing and how we interact with
function GuiElement:setDepth(depth)
self.depth = depth or 0
end end
function Menu:register() function GuiElement:setVisibility(visibility)
self.menusystem:addMenu(self.name, self) if self.isLocked == false and self.isAlwaysVisible == false then
self.isVisible = visibility
else
-- if the element is locked (thus is always active), it should also
-- be always visible.
self.isVisible = true
end
end end
function Menu:setCancelWidget(id) function GuiElement:setActivity(activity)
self.widget.cancel = #self.widget.list if self.isLocked == false then
self.isActive = activity
else
self.isActive = true
end
end end
function Menu:updateWidgetSize() function GuiElement:lock(lock)
self.widget.h = 0 self.isLocked = lock
self.widget.w = 0
end end
function Menu:getWidgetSize(id) function GuiElement:lockVisibility(lock)
return self.widget.w, self.widget.h self.isAlwaysVisible = lock
end end
function Menu:getWidgetNumber() function GuiElement:getFocus()
return #self.widget.list local gui = self:getGui()
gui.focusedMenu = self.name
end end
-- ACTION FUNCTIONS function GuiElement:haveFocus()
-- Send actions to the widgets local gui = self:getGui()
return (gui.focusedMenu == self.name)
function Menu:cancelAction()
if (self.widget.cancel ~= 0) then
self.widget.list[self.widget.cancel]:action("key")
end
end
function Menu:clear()
self.widget.list = {}
self.widget.cancel = 0
end
function Menu:resize(x,y,w,h)
self.x = x
self.y = y
self.w = w
self.h = h
self:updateWidgetSize()
end
function Menu:destroy()
self.destroyed = true
end
function Menu:updateWidgetsOrder()
table.sort(self.widget.list, updateWidgetByOrder)
end end
-- UPDATE FUNCTIONS -- UPDATE FUNCTIONS
-- Update the menu every game update -- Update the menu every game update
function Menu:update(dt) -- External update function
-- Cette fonction ne contient rien par défaut function GuiElement:updateElement(dt)
self:update(dt)
end
-- Internal update function
function GuiElement:update(dt)
-- Cette fonction ne contient rien par défaut
end end
-- DRAW FUNCTIONS -- DRAW FUNCTIONS
-- Draw the menu and its content -- Draw the menu and its content
function Menu:draw() function GuiElement:drawElement()
-- nothing here self:draw()
end end
function Menu:drawCursor() function GuiElement:draw()
-- nothing here -- nothing here
end
function Menu:drawCanvas()
end end
-- KEYBOARD FUNCTIONS -- KEYBOARD FUNCTIONS
-- Handle key press -- Handle key press
function Menu:keyreleased(key) function GuiElement:keyreleased(key)
-- Cette fonction ne contient rien par défaut -- Cette fonction ne contient rien par défaut
end end
-- MOUSE FUNCTIONS -- MOUSE FUNCTIONS
-- Handle pointers (clic/touch) -- Handle pointers (clic/touch)
function Menu:mousemoved(x, y) function GuiElement:mousemoved(x, y)
-- Cette fonction ne contient rien par défaut -- Cette fonction ne contient rien par défaut
end end
function Menu:mousepressed( x, y, button, istouch ) function GuiElement:mousepressed(x, y, button, istouch)
-- Cette fonction ne contient rien par défaut -- Cette fonction ne contient rien par défaut
end end
-- WIDGET FUNCTIONS return GuiElement
-- Handle widgets of the functions
function Menu:addWidget(newwidget)
if #self.widget.list == 0 then
self.widget.selected = 1
end
table.insert(self.widget.list, newwidget)
self:updateWidgetsID()
self:updateWidgetsOrder()
end
function Menu:updateWidgets(dt)
self:removeDestroyedWidgets()
for i,v in ipairs(self.widget.list) do
v.id = i
v:update(dt)
end
end
function Menu:updateWidgetsID()
for i,v in ipairs(self.widget.list) do
v.id = i
end
end
function Menu:removeDestroyedWidgets() -- On retire les widgets marquées comme supprimées
for i,v in ipairs(self.widget.list) do
if (v.destroyed == true) then
table.remove(self.widget.list, i)
end
end
end
-- CURSOR FUNCTIONS
-- Set or move the cursor of the menu
function Menu:setCursor(cursorid)
self.widget.selected = cursorid --math.max(1, math.min(cursorid, #self.widget.list))
end
function Menu:moveCursor(new_selected)
self:playNavigationSound()
if new_selected < 1 then
self.widget.selected = #self.widget.list + new_selected
else
if new_selected > #self.widget.list then
self.widget.selected = new_selected - #self.widget.list
else
self.widget.selected = new_selected
end
end
end
-- SOUND FUNCTION
-- Handle SFX
function Menu:resetSound()
self.sound = {}
self.sound.active = false
self.sound.asset = nil
end
function Menu:setSoundFromSceneAssets(name)
self:setSound(self.menusystem.scene.assets:getWithType(name, "sfx"))
end
function Menu:setSound(soundasset)
self.sound.active = true
self.sound.asset = soundasset
end
function Menu:playNavigationSound()
if self.sound.active == true then
self.sound.asset:play()
end
end
-- VIEW FUNCTIONS
-- Handle the view of the menu
function Menu:resetView()
-- ne sert à rien ici, c'est juste pour éviter des crash
end
function Menu:updateView()
-- ne sert à rien ici, c'est juste pour éviter des crash
end
function Menu:moveView()
-- ne sert à rien ici, c'est juste pour éviter des crash
end
return Menu

View file

@ -0,0 +1,78 @@
-- listbox : a text-based menu.
-- It allow to easily handle a listbox with text-widget and automatically add a widget
-- for submenu.
-- It also make the menu manage the font and the selection color, for a simpler handling
--[[
Copyright © 2020 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local ListBox = require "birb.modules.menusystem.menus.listbox"
local TextMenu = ListBox:extend()
TextMenu.baseWidgets = require "birb.modules.menusystem.textmenu.widgets"
local BASE_PADDING = 8
function TextMenu:new(name, font, x, y, w, slotNumber, padding)
self:setFont(font)
self.name = name
local h = self.font:getHeight() * slotNumber
self.padding = padding or BASE_PADDING
self:setSelectedColor(1,1,1)
TextMenu.super.new(self, nil, name, x, y, w, h, slotNumber)
end
function TextMenu:setFont(fontName)
local scene = core.scenemanager.currentScene
self.font = scene.assets:getFont(fontName)
end
function TextMenu:getFont()
return self.font
end
function TextMenu:setSelectedColor(r, g, b)
self.selectedColor = {}
self.selectedColor.r = r
self.selectedColor.g = g
self.selectedColor.b = b
end
function TextMenu:getSelectedColor()
return self.selectedColor.r, self.selectedColor.g, self.selectedColor.b
end
function TextMenu:getPadding()
return self.padding
end
function TextMenu:addSubmenu(pageName, label, parent, backWidget)
local label = label or pageName
local parent = parent or "main"
self:switch(parent)
TextMenu.baseWidgets.SubMenu(self.name, pageName, label)
TextMenu.super.addSubmenu(self, pageName, parent)
if (backWidget ~= false) then
TextMenu.baseWidgets.Back(self.name)
end
end
return TextMenu

View file

@ -0,0 +1,37 @@
-- backwidget : the base widget to go to parent submenu
--[[
Copyright © 2020 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local TextMenuWidget = require "birb.modules.menusystem.textmenu.widgets.basic"
local BackWidget = TextMenuWidget:extend()
function BackWidget:new(menuName)
BackWidget.super.new(self, menuName, "Back", "left")
self.order = 1000
end
function BackWidget:action()
self.menu:back()
end
return BackWidget

View file

@ -0,0 +1,47 @@
-- widget : the base widget for a textmenu
-- It replace the functions to get the font and the selectionColor by wrapper to
-- TextMenu.
--[[
Copyright © 2020 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local TextWidget = require "birb.modules.menusystem.menus.widgets.text"
local TextMenuWidget = TextWidget:extend()
function TextMenuWidget:new(menuName, label, position)
local position = position or "left"
TextMenuWidget.super.new(self, menuName, "", label, position, 0)
end
function TextMenuWidget:getFont()
return self.menu:getFont()
end
function TextMenuWidget:getSelectedColor()
return self.menu:getSelectedColor()
end
function TextMenuWidget:getPadding()
return self.menu:getPadding()
end
return TextMenuWidget

View file

@ -0,0 +1,31 @@
-- widgets :: basic widget object
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local Widget = {}
-- Add the widget as subvariable to the returned table
Widget.Base = require "birb.modules.menusystem.textmenu.widgets.basic"
Widget.SubMenu= require "birb.modules.menusystem.textmenu.widgets.submenu"
Widget.Back = require "birb.modules.menusystem.textmenu.widgets.back"
return Widget

View file

@ -0,0 +1,39 @@
-- widget : the base widget to go to a submenu
-- Make go to a submenu
--[[
Copyright © 2020 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local TextMenuWidget = require "birb.modules.menusystem.textmenu.widgets.basic"
local SubmenuWidget = TextMenuWidget:extend()
function SubmenuWidget:new(menuName, submenu, label, position)
self.submenu = submenu
SubmenuWidget.super.new(self, menuName, label, position)
self:addLabel(">", "right")
end
function SubmenuWidget:action()
self.menu:switch(self.submenu)
end
return SubmenuWidget

View file

@ -1,4 +1,4 @@
-- widgets/utils :: basic utility functions for the widgets -- menusystem/utils :: basic utility functions for the gui
--[[ --[[
Copyright © 2019 Kazhnuz Copyright © 2019 Kazhnuz
@ -21,9 +21,9 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]] ]]
local menuUtils = {} local guiUtils = {}
function menuUtils.drawCursor(x, y, w, h) function guiUtils.drawCursor(x, y, w, h)
love.graphics.setColor(0,0,0) love.graphics.setColor(0,0,0)
love.graphics.rectangle("fill", x, y, 4, 8) love.graphics.rectangle("fill", x, y, 4, 8)
@ -54,4 +54,4 @@ function menuUtils.drawCursor(x, y, w, h)
end end
return menuUtils return guiUtils

View file

@ -1,144 +0,0 @@
-- widgets :: basic widget object
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local Widget = {}
BaseWidget = Object:extend()
TextWidget = BaseWidget:extend()
-- INIT FUNCTIONS
-- Initialize and configure the widget
function BaseWidget:new(menu)
self.menu = menu
self.destroyed = false
self.selectable = false
self.selection_margin = 0
self.margin = 2
self.canvas = {}
self.canvas.texture = nil
self.canvas.needRedraw = true
self.order = 0
self:register()
end
function BaseWidget:register()
self.creationID = self.menu:getWidgetNumber()
self.menu:addWidget(self)
end
function BaseWidget:redrawCanvas()
self.width, self.height = self.menu:getWidgetSize(self.id)
local canvas = love.graphics.newCanvas(self.width, self.height)
love.graphics.setCanvas( canvas )
self:drawCanvas()
self.canvas.needRedraw = false
love.graphics.setCanvas( )
local imageData = canvas:newImageData( )
self.canvas.texture = love.graphics.newImage( imageData )
canvas:release( )
imageData:release( )
end
function BaseWidget:invalidateCanvas()
self.canvas.needRedraw = true
end
function BaseWidget:drawCanvas()
self.r = love.math.random(128)/256
self.g = love.math.random(128)/256
self.b = love.math.random(128)/256
love.graphics.setColor(self.r, self.g, self.b, 70)
love.graphics.rectangle("fill", 0, 0, self.width, self.height)
love.graphics.setColor(self.r, self.g, self.b)
love.graphics.rectangle("line", 0, 0, self.width, self.height)
utils.graphics.resetColor()
end
function BaseWidget:selectAction()
-- Do nothing
end
-- DRAW WIDGETS
-- Draw the widget
function BaseWidget:draw(x, y)
if self.canvas.texture ~= nil then
utils.graphics.resetColor()
love.graphics.draw(self.canvas.texture, x, y)
end
end
function BaseWidget:drawSelected(x,y,w,h)
self:draw(x, y, w, h)
end
-- UPDATE FUNCTIONS
-- Update the widget
function BaseWidget:update(dt)
if (self.canvas.needRedraw) then
self:redrawCanvas()
end
-- N/A
end
-- ACTION FUNCTION
-- Functions to handle actions and selection.
function BaseWidget:action(source)
--self:destroy()
end
function BaseWidget:destroy()
self.destroyed = true
end
-- TEXT WIDGET
-- Simple text widget
function TextWidget:new(menu, font, label)
TextWidget.super.new(self, menu)
self.font = font
self.label = label
end
function TextWidget:drawCanvas()
local w, h
w = math.floor(self.width / 2)
h = math.floor(self.height / 2) - (self.font:getHeight() / 2)
self.font:draw(self.label, w, h, -1, "center")
end
-- Add the widget as subvariable to the returned table
Widget.Base = BaseWidget
Widget.Text = TextWidget
return Widget

View file

@ -32,7 +32,7 @@ local MenuSystem = require(cwd .. "menusystem")
-- INIT FUNCTIONS -- INIT FUNCTIONS
-- Initialize and configure the scene -- Initialize and configure the scene
function Scene:new() function Scene:new(args)
self.mouse = {} self.mouse = {}
self.mouse.x, self.mouse.y = core.screen:getMousePosition() self.mouse.x, self.mouse.y = core.screen:getMousePosition()
@ -45,11 +45,17 @@ function Scene:new()
self:flushKeys() self:flushKeys()
self.isActive = false self.isActive = false
self.args = args
self:initWorld() self:initWorld()
self:register() self:register()
end end
function Scene:start()
-- Empty function
end
function Scene:register() function Scene:register()
core.scenemanager:setScene(self) core.scenemanager:setScene(self)
end end
@ -61,6 +67,15 @@ end
-- UPDATE FUNCTIONS -- UPDATE FUNCTIONS
-- Handle stuff that happens every steps -- Handle stuff that happens every steps
function Scene:updateScene(dt)
self:updateStart(dt)
self:setKeys()
self.menusystem:update(dt)
self:updateWorld(dt)
self:update(dt)
self:updateEnd(dt)
end
function Scene:updateStart(dt) function Scene:updateStart(dt)
end end
@ -115,6 +130,14 @@ end
-- DRAW FUNCTIONS -- DRAW FUNCTIONS
-- Draw the scene and its content -- Draw the scene and its content
function Scene:drawScene()
self:drawStart()
self:drawWorld()
self:draw()
self.menusystem:draw()
self:drawEnd()
end
function Scene:drawStart() function Scene:drawStart()
end end

View file

@ -22,13 +22,15 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]] ]]
local Rect = require "birb.objects.2D.rect"
local BaseActor = require("birb.modules.world.actors.mixins.base") local BaseActor = require("birb.modules.world.actors.mixins.base")
local SpritedActor = require("birb.modules.world.actors.mixins.sprites") local SpritedActor = require("birb.modules.world.actors.mixins.sprites")
local TimedActor = require("birb.modules.world.actors.mixins.timers") local TimedActor = require("birb.modules.world.actors.mixins.timers")
local InputActor = require("birb.modules.world.actors.mixins.inputs") local InputActor = require("birb.modules.world.actors.mixins.inputs")
local PhysicalActor = require("birb.modules.world.actors.mixins.physics") local PhysicalActor = require("birb.modules.world.actors.mixins.physics")
local Actor2D = Object:extend() local Actor2D = Rect:extend()
Actor2D:implement(BaseActor) Actor2D:implement(BaseActor)
Actor2D:implement(SpritedActor) Actor2D:implement(SpritedActor)
Actor2D:implement(TimedActor) Actor2D:implement(TimedActor)
@ -41,8 +43,9 @@ local Hitbox = require("birb.modules.world.actors.utils.hitbox2D")
-- Initialise the actor and its base functions -- Initialise the actor and its base functions
function Actor2D:new(world, type, x, y, w, h, isSolid) function Actor2D:new(world, type, x, y, w, h, isSolid)
Actor2D.super.new(self, x, y, w, h)
self:init(world, type) self:init(world, type)
self:initPhysics(Hitbox, x, y, 0, w, h, 0, isSolid) self:initPhysics(Hitbox, isSolid)
self:initTimers() self:initTimers()
self:initSprite() self:initSprite()
self:initKeys() self:initKeys()
@ -134,10 +137,6 @@ end
-- DRAW FUNCTIONS -- DRAW FUNCTIONS
-- Draw the actors. -- Draw the actors.
function Actor2D:getShape()
return (self.x), (self.y), self.w, (self.h)
end
function Actor2D:draw() function Actor2D:draw()
self:drawStart() self:drawStart()
local x, y = math.floor(self.x), math.floor(self.y) local x, y = math.floor(self.x), math.floor(self.y)

View file

@ -22,44 +22,42 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]] ]]
local cwd = (...):gsub('%.actor3D$', '') .. "." local BasicBox = require "birb.objects.3D.box"
local BaseActor = require("birb.modules.world.actors.mixins.base") local BaseActor = require("birb.modules.world.actors.mixins.base")
local SpritedActor = require("birb.modules.world.actors.mixins.sprites") local SpritedActor = require("birb.modules.world.actors.mixins.sprites")
local TimedActor = require("birb.modules.world.actors.mixins.timers") local TimedActor = require("birb.modules.world.actors.mixins.timers")
local InputActor = require("birb.modules.world.actors.mixins.inputs") local InputActor = require("birb.modules.world.actors.mixins.inputs")
local PhysicalActor = require("birb.modules.world.actors.mixins.physics") local PhysicalActor = require("birb.modules.world.actors.mixins.physics")
local Shape3DActor = require("birb.modules.world.actors.mixins.shapes")
local Actor3D = Object:extend() local Actor3D = BasicBox:extend()
Actor3D:implement(BaseActor) Actor3D:implement(BaseActor)
Actor3D:implement(SpritedActor) Actor3D:implement(SpritedActor)
Actor3D:implement(TimedActor) Actor3D:implement(TimedActor)
Actor3D:implement(InputActor) Actor3D:implement(InputActor)
Actor3D:implement(PhysicalActor) Actor3D:implement(PhysicalActor)
Actor3D:implement(Shape3DActor)
local Hitbox = require(cwd .. "utils.hitbox3D") local Hitbox = require("birb.modules.world.actors.utils.hitbox3D")
local Boxes = require(cwd .. "utils.boxes") local Boxes = require("birb.modules.world.actors.utils.boxes")
-- INIT FUNCTIONS -- INIT FUNCTIONS
-- Initialise the actor and its base functions -- Initialise the actor and its base functions
function Actor3D:new(world, type, x, y, z, w, h, d, isSolid) function Actor3D:new(world, type, x, y, z, w, h, d, isSolid)
Actor3D.super.new(self, x, y, z, w, h, d)
self:init(world, type) self:init(world, type)
self:initPhysics(Hitbox, x, y, z, w, h, d, isSolid) self:initPhysics(Hitbox, isSolid)
self:initTimers() self:initTimers()
self:initSprite() self:initSprite()
self.world:registerShape(self) self:initShape(Boxes, true)
self.boxes = Boxes
self.doCastShadows = true
end end
function Actor3D:destroy() function Actor3D:destroy()
self:removeOldShadowTargets() self:destroyShape()
if self.box ~= nil then
self.world:removeTerrain(self)
end
self.world:removeActor(self)
self.mainHitbox:destroy() self.mainHitbox:destroy()
self.world:removeShape(self) self.world:removeActor(self)
self.isDestroyed = true self.isDestroyed = true
end end
@ -154,62 +152,6 @@ function Actor3D:getViewCenter()
return x, y - (self.d/2) return x, y - (self.d/2)
end end
-- SHADOW FUNCTIONS
-- Handle everything related to shadow
function Actor3D:castShadow()
local shadowTargets = self.world:getTerrainInRect(self.x, self.y, self.w, self.d)
-- initialize the shadowTargetsPrevious variable if it doesn't exist
if (self.shadowTargetsPrevious == nil) then
self.shadowTargetsPrevious = {}
end
for i, target in ipairs(shadowTargets) do
-- We test if the actor is below the current actor
if (target ~= self) and (target.box ~= nil) then
if (target.z + target.d <= self.z + self.d) then
-- Remove the target of the list of item targeted last update,
-- in order to only have object no longer shadowed after the
-- end of the loop
for j, oldtarget in ipairs(self.shadowTargetsPrevious) do
if (target == oldtarget) then
table.remove(self.shadowTargetsPrevious, j)
end
end
-- We update the shadow source
local x, y = math.floor(self.x - target.x), math.floor(self.y - target.y)
target.box:setShadowSource(self, x, y)
end
end
end
-- At this point, if a target is still in the shadowTargetsPrevious list,
-- it mean that it's not shadowed. So we can simply remove the shadow.
self:removeOldShadowTargets()
self.shadowTargetsPrevious = shadowTargets
end
function Actor3D:removeOldShadowTargets()
if (self.shadowTargetsPrevious ~= nil) then
for i, target in ipairs(self.shadowTargetsPrevious) do
if (target.box ~= nil) then
target.box:removeShadowSource(self)
end
end
end
end
function Actor3D:redrawShadowCanvas()
if (self.box ~= nil) then
self.box:redrawShadowCanvas()
end
end
-- DRAW FUNCTIONS -- DRAW FUNCTIONS
-- Draw the actors. -- Draw the actors.

View file

@ -3,15 +3,9 @@ PhysicalActor = Object:extend()
-- PHYSICS FUNCTIONS -- PHYSICS FUNCTIONS
-- Raw implementation of everything common in physics -- Raw implementation of everything common in physics
function PhysicalActor:initPhysics(hitboxObj, x, y, z, w, h, d, isSolid) function PhysicalActor:initPhysics(hitboxObj, isSolid)
self:setCoordinate(x, y, z)
self.isSolid = isSolid or false self.isSolid = isSolid or false
self.w = w or 0
self.h = h or 0
self.d = d or 0
self.xsp = 0 self.xsp = 0
self.ysp = 0 self.ysp = 0
self.zsp = 0 self.zsp = 0
@ -29,12 +23,6 @@ function PhysicalActor:initPhysics(hitboxObj, x, y, z, w, h, d, isSolid)
self:addUpdateFunction(self.autoMove) self:addUpdateFunction(self.autoMove)
end end
function PhysicalActor:setCoordinate(x, y, z, w, h, d)
self.x = x or self.x
self.y = y or self.y
self.z = z or self.z
end
function PhysicalActor:setBounceFactor(newBounceFactor) function PhysicalActor:setBounceFactor(newBounceFactor)
self.bounceFactor = newBounceFactor or 0 self.bounceFactor = newBounceFactor or 0
end end
@ -57,7 +45,9 @@ function PhysicalActor:getFuturePosition(dt)
local dx, dy, dz local dx, dy, dz
dx = self.x + self.xsp * dt dx = self.x + self.xsp * dt
dy = self.y + self.ysp * dt dy = self.y + self.ysp * dt
dz = self.z + self.zsp * dt if (self.z ~= nil) then
dz = self.z + self.zsp * dt
end
return dx, dy, dz return dx, dy, dz
end end
@ -65,7 +55,9 @@ end
function PhysicalActor:applyFriction(dt) function PhysicalActor:applyFriction(dt)
self.xsp = utils.math.toZero(self.xsp, self.xfrc * dt) self.xsp = utils.math.toZero(self.xsp, self.xfrc * dt)
self.ysp = utils.math.toZero(self.ysp, self.yfrc * dt) self.ysp = utils.math.toZero(self.ysp, self.yfrc * dt)
self.zsp = utils.math.toZero(self.zsp, self.zfrc * dt) if (self.z ~= nil) then
self.zsp = utils.math.toZero(self.zsp, self.zfrc * dt)
end
end end
function PhysicalActor:solveAllCollisions(cols) function PhysicalActor:solveAllCollisions(cols)
@ -89,10 +81,6 @@ end
-- Handle coordinate -- Handle coordinate
-- Will be replaced by functions inside Actors or Rects/Point -- Will be replaced by functions inside Actors or Rects/Point
function PhysicalActor:getCenter()
return (self.x + (self.w / 2)), (self.y + (self.h / 2)), (self.z + (self.d / 2))
end
function PhysicalActor:getViewCenter() function PhysicalActor:getViewCenter()
return self:getCenter() return self:getCenter()
end end

View file

@ -0,0 +1,97 @@
-- ShapedActor.lua :: Handle the shape of a 2.5D actor.
-- It handle terrain box, and shadows
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local ShapedActor = Object:extend()
function ShapedActor:initShape(boxObj, doCastShadows)
self.world:registerShape(self)
self.boxes = boxObj
self.doCastShadows = doCastShadows
end
function ShapedActor:destroyShape()
self:removeOldShadowTargets()
if self.box ~= nil then
self.world:removeTerrain(self)
end
self.world:removeShape(self)
end
-- SHADOW FUNCTIONS
-- Handle everything related to shadow
function ShapedActor:castShadow()
local shadowTargets = self.world:getTerrainInRect(self.x, self.y, self.w, self.d)
-- initialize the shadowTargetsPrevious variable if it doesn't exist
if (self.shadowTargetsPrevious == nil) then
self.shadowTargetsPrevious = {}
end
for i, target in ipairs(shadowTargets) do
-- We test if the actor is below the current actor
if (target ~= self) and (target.box ~= nil) then
if (target.z + target.d <= self.z + self.d) then
-- Remove the target of the list of item targeted last update,
-- in order to only have object no longer shadowed after the
-- end of the loop
for j, oldtarget in ipairs(self.shadowTargetsPrevious) do
if (target == oldtarget) then
table.remove(self.shadowTargetsPrevious, j)
end
end
-- We update the shadow source
local x, y = math.floor(self.x - target.x), math.floor(self.y - target.y)
target.box:setShadowSource(self, x, y)
end
end
end
-- At this point, if a target is still in the shadowTargetsPrevious list,
-- it mean that it's not shadowed. So we can simply remove the shadow.
self:removeOldShadowTargets()
self.shadowTargetsPrevious = shadowTargets
end
function ShapedActor:removeOldShadowTargets()
if (self.shadowTargetsPrevious ~= nil) then
for i, target in ipairs(self.shadowTargetsPrevious) do
if (target.box ~= nil) then
target.box:removeShadowSource(self)
end
end
end
end
function ShapedActor:redrawShadowCanvas()
if (self.box ~= nil) then
self.box:redrawShadowCanvas()
end
end
return ShapedActor

View file

@ -31,7 +31,7 @@ function Point:setPosition(x, y)
self.x, self.y = x, y self.x, self.y = x, y
end end
function Point:move(x, y) function Point:goToward(x, y)
local x = x or 0 local x = x or 0
local y = y or 0 local y = y or 0
self:setPosition(self.x + x, self.y + y) self:setPosition(self.x + x, self.y + y)
@ -63,7 +63,7 @@ function Point:getMiddlePoint(x, y)
return utils.math.getMiddlePoint(self.x, self.y, x, y) return utils.math.getMiddlePoint(self.x, self.y, x, y)
end end
function Point:getDirectionFromPoint(other) function Point:getMiddlePointFromPoint(other)
local x, y = other:getPosition() local x, y = other:getPosition()
self:getMiddlePoint(x, y) self:getMiddlePoint(x, y)
end end

View file

@ -29,6 +29,11 @@ function Rect:new(x, y, w, h)
self:setSize(w, h) self:setSize(w, h)
end end
function Rect:set(x, y, w, h)
self:setPosition(x, y)
self:setSize(w, h)
end
function Rect:setSize(w, h) function Rect:setSize(w, h)
self.w = w or self.w self.w = w or self.w
self.h = h or self.h self.h = h or self.h
@ -39,6 +44,10 @@ function Rect:getArea()
return x, y, self.w, self.h return x, y, self.w, self.h
end end
function Rect:getShape()
return self:getArea()
end
function Rect:getCorners() function Rect:getCorners()
local x, y, w, h = self:getArea() local x, y, w, h = self:getArea()
return x, y, x + w, y + h return x, y, x + w, y + h

70
birb/objects/3D/box.lua Normal file
View file

@ -0,0 +1,70 @@
-- box.lua :: a 3D box.
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local Point = require "birb.objects.3D.point3D"
local Box = Point:extend()
function Box:new(x, y, z, w, h, d)
Box.super.new(self, x, y, z)
self:setSize(w, h, d)
end
function Box:setSize(w, h, d)
self.w = w or self.w
self.h = h or self.h
self.d = d or self.d
end
function Box:getArea()
local x, y, z = self:getPosition()
return x, y, z, self.w, self.h, self.d
end
function Box:getShape()
local x, y, z, w, h, d = self:getArea()
end
function Box:getCorners()
local x, y, z, w, h, d = self:getArea()
return x, y, z, x + w, y + h, z + d
end
function Box:getCenter()
local x, y, z, w, h, d = self:getArea()
return math.floor(x + (w/2)), math.floor(y + (h/2)), math.floor(z + (d/2))
end
function Box:areCoordInside(dx, dy, dz)
local x, y, z, w, h, d = self:getArea()
return ((dx > x) and (dx < x + w) and (dy > y) and (dy < y + h)) and (dz > z) and (dz < z + d)
end
function Box:getRelativeCoordinate(dx, dy, dz)
return dx - self.x, dy - self.y, dz - self.z
end
function Box:drawBox()
utils.graphics.box(self.x, self.y, self.w, self.h)
end
return Box

View file

@ -0,0 +1,71 @@
-- indexedbox.lua :: An indexed box is a box indexed to a point,
-- Basically a box that have its coordinate recalculated from an existing
-- point
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local Rect = require "birb.objects.2D.rect"
local IndexedRect = Rect:extend()
function IndexedRect:new(origin, ox, oy, oz, w, h, d)
self.setOrigin(origin)
self.ox = ox
self.oy = oy
self.oz = oz
local x, y, z = self:getPosition()
IndexedRect.super.new(self, x, y, w, h)
end
function IndexedRect:setRelativePosition(ox, oy, oz)
self.ox = ox or self.ox
self.oy = oy or self.oy
self.oz = oz or self.oz
end
function IndexedRect:setOrigin(origin)
self.origin = origin
-- We should check if the origin is really a point
end
function IndexedRect:getOrigin(origin)
return self.origin
end
function IndexedRect:getPosition()
return self.origin.x + self.ox, self.origin.y + self.oy, self.origin.z + self.oz
end
function IndexedRect:updateBox()
local x, y, z = self:getPosition()
self:setPosition(x, y, z)
return x, y, self.w, self.h, self.d
end
function IndexedRect:modify(ox, oy, oz, w, h, d)
self.ox = ox
self.oy = oy
self.oz = oz
self:setSize(w, h, d)
self:updateBox()
end
return IndexedRect

View file

@ -0,0 +1,72 @@
-- point3D.lua :: a 3D point.
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local Point = Object:extend()
function Point:new(x, y, z)
self.x, self.y, self.z = x, y, z
end
function Point:setPosition(x, y, z)
self.x, self.y, self.z = x, y, z
end
function Point:goToward(x, y, z)
local x = x or 0
local y = y or 0
local z = z or 0
self:setPosition(self.x + x, self.y + y, self.z + z)
end
function Point:getPosition()
return self.x, self.y, self.z
end
function Point:getDistance(x, y, z)
return utils.math.pointDistance3D(self.x, self.y, self.z, x, y, z)
end
function Point:getDistanceFromPoint(other)
local x, y, z = other:getPosition()
self:getDistance(x, y, z)
end
function Point:getDirection(x, y)
return utils.math.pointDirection(self.x, self.y, x, y)
end
function Point:getDirectionFromPoint(other)
local x, y = other:getPosition()
self:getDirection(x, y)
end
function Point:getMiddlePoint(x, y, z)
return utils.math.getMiddlePoint3D(self.x, self.y, self.z, x, y, z)
end
function Point:getMiddlePointFromPoint(other)
local x, y, z = other:getPosition()
self:getMiddlePoint(x, y, z)
end
return Point

View file

@ -56,6 +56,15 @@ function Math.between(num, value1, value2)
return math.min(math.max(num, min), max) return math.min(math.max(num, min), max)
end end
function Math.wrapAndLimit(num, min, max)
if (num < min) then
num = max
elseif (num > max) then
num = min
end
return num
end
-- VECTOR/DIRECTION functions -- VECTOR/DIRECTION functions
-- Easy-to-use function to handle point and motion -- Easy-to-use function to handle point and motion

View file

@ -24,10 +24,10 @@
local Scene = require "birb.modules.scenes" local Scene = require "birb.modules.scenes"
local TestScene = Scene:extend() local TestScene = Scene:extend()
local MenuType = require "birb.modules.menusystem.listbox" local MenuType = require "birb.modules.menusystem.menus.listbox"
local MenuType2 = require "birb.modules.menusystem.flowbox" local MenuType2 = require "birb.modules.menusystem.menus.flowbox"
local MenuType3 = require "birb.modules.menusystem.grid" local MenuType3 = require "birb.modules.menusystem.menus.grid"
local Widget = require "birb.modules.menusystem.widgets" local Widget = require "birb.modules.menusystem.menus.widgets"
local MenuWidget = Widget.Text:extend() local MenuWidget = Widget.Text:extend()
@ -37,39 +37,39 @@ function TestScene:new()
MenuType(self.menusystem, "testMenu1", 32, 32, 100, 24*8, 4) MenuType(self.menusystem, "testMenu1", 32, 32, 100, 24*8, 4)
MenuWidget(self, "testMenu1", "text_menu1") MenuWidget(self, "testMenu1", "text_menu1")
Widget.Base(self.menusystem.menus["testMenu1"]) Widget.Base("testMenu1")
Widget.Base(self.menusystem.menus["testMenu1"]) Widget.Base("testMenu1")
Widget.Base(self.menusystem.menus["testMenu1"]) Widget.Base("testMenu1")
Widget.Base(self.menusystem.menus["testMenu1"]) Widget.Base("testMenu1")
Widget.Base(self.menusystem.menus["testMenu1"]) Widget.Base("testMenu1")
MenuType2(self.menusystem, "testMenu2", 164, 32, 24*8, 24*2, 8, 2) MenuType2(self.menusystem, "testMenu2", 164, 32, 24*8, 24*2, 8, 2)
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
Widget.Base(self.menusystem.menus["testMenu2"]) Widget.Base("testMenu2")
MenuType3(self.menusystem, "testMenu3", 164, 32 + 72, 24*8, 24*5, 8, 5) MenuType3(self.menusystem, "testMenu3", 164, 32 + 72, 24*8, 24*5, 8, 5)
Widget.Base(self.menusystem.menus["testMenu3"]) Widget.Base("testMenu3")
Widget.Base(self.menusystem.menus["testMenu3"]) Widget.Base("testMenu3")
Widget.Base(self.menusystem.menus["testMenu3"]) Widget.Base("testMenu3")
Widget.Base(self.menusystem.menus["testMenu3"]) Widget.Base("testMenu3")
self.menusystem.menus["testMenu3"]:addSlot(1, 0, 0, 4, 3) 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(2, 0, 3, 5, 2)
self.menusystem.menus["testMenu3"]:addSlot(3, 5, 0, 3, 1) self.menusystem.menus["testMenu3"]:addSlot(3, 5, 0, 3, 1)
@ -120,7 +120,7 @@ end
function TestScene:addTextWidget(menu, number) function TestScene:addTextWidget(menu, number)
for i=1, number do for i=1, number do
Widget.Text(self.menusystem.menus[menu], self.assets.fonts["medium"], "lorem ipsum " .. i) Widget.Text(menu, "medium", "lorem ipsum " .. i)
end end
end end
@ -131,10 +131,8 @@ end
function MenuWidget:new(scene, menu, newmenu) function MenuWidget:new(scene, menu, newmenu)
self.scene = scene self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
self.newmenu = newmenu self.newmenu = newmenu
MenuWidget.super.new(self, widgetmenu, font, newmenu) MenuWidget.super.new(self, menu, "menu", newmenu)
end end
function MenuWidget:action() function MenuWidget:action()

View file

@ -1,5 +1,5 @@
local ListMenu = require "birb.modules.menusystem.listbox" local ListMenu = require "birb.modules.menusystem.menus.listbox"
local Widget = require "birb.modules.menusystem.widgets" local Widget = require "birb.modules.menusystem.menus.widgets"
local PauseMenu = ListMenu:extend() local PauseMenu = ListMenu:extend()
@ -7,26 +7,27 @@ local ResumeWidget = Widget.Text:extend()
local RestartWidget = Widget.Text:extend() local RestartWidget = Widget.Text:extend()
local ExitWidget = Widget.Text:extend() local ExitWidget = Widget.Text:extend()
local MENU_NAME = "PauseMenu"
function PauseMenu:new(scene) function PauseMenu:new(scene)
self.scene = scene self.scene = scene
local screenHeight, screenWidth = core.screen:getDimensions() local screenHeight, screenWidth = core.screen:getDimensions()
local w, h = 424/4, 240 - 48*4 local w, h = 424/4, 240 - 48*4
local x, y = 3*w/2, 24*4 local x, y = 3*w/2, 24*4
PauseMenu.super.new(self, scene.menusystem, "PauseMenu", x, y, w, h, 3) PauseMenu.super.new(self, scene.menusystem, MENU_NAME, x, y, w, h, 3)
ResumeWidget(self) ResumeWidget()
RestartWidget(self) RestartWidget()
ExitWidget(self) ExitWidget()
end end
-- WIDGETS -- WIDGETS
-- All widgets used by the pause menu -- All widgets used by the pause menu
function ResumeWidget:new(menu) function ResumeWidget:new()
self.scene = menu.scene self.scene = core.scenemanager.currentScene
local font = self.scene.assets:getFont("medium")
local label = "resume" local label = "resume"
ResumeWidget.super.new(self, menu, font, label) ResumeWidget.super.new(self, MENU_NAME, "medium", label)
end end
function ResumeWidget:action() function ResumeWidget:action()
@ -34,11 +35,10 @@ function ResumeWidget:action()
self.scene.menusystem:deactivate() self.scene.menusystem:deactivate()
end end
function RestartWidget:new(menu) function RestartWidget:new()
self.scene = menu.scene self.scene = core.scenemanager.currentScene
local font = self.scene.assets:getFont("medium")
local label = "restart" local label = "restart"
RestartWidget.super.new(self, menu, font, label) RestartWidget.super.new(self, MENU_NAME, "medium", label)
end end
function RestartWidget:action() function RestartWidget:action()
@ -46,11 +46,10 @@ function RestartWidget:action()
self.scene:restart() self.scene:restart()
end end
function ExitWidget:new(menu) function ExitWidget:new()
self.scene = menu.scene self.scene = core.scenemanager.currentScene
local font = self.scene.assets:getFont("medium")
local label = "exit" local label = "exit"
ExitWidget.super.new(self, menu, font, label) ExitWidget.super.new(self, MENU_NAME, "medium", label)
end end
function ExitWidget:action() function ExitWidget:action()

View file

@ -24,62 +24,65 @@
local Scene = require "birb.modules.scenes" local Scene = require "birb.modules.scenes"
local MainMenu = Scene:extend() local MainMenu = Scene:extend()
local ListBox = require "birb.modules.menusystem.listbox" local ListBox = require "birb.modules.menusystem.menus.listbox"
local Widget = require "birb.modules.menusystem.widgets" local Widget = require "birb.modules.menusystem.menus.widgets"
local SubMenuWidget = Widget.Text:extend() local TextMenu = require "birb.modules.menusystem.textmenu"
local SceneWidget = Widget.Text:extend()
local ExitWidget = Widget.Text:extend()
function MainMenu:new() local SceneWidget = TextMenu.baseWidgets.Base:extend()
MainMenu.super.new(self) local ExitWidget = TextMenu.baseWidgets.Base:extend()
local MENU_NAME = "mainMenu"
function MainMenu:start()
self.assets:batchImport("scenes.mainmenu.assets") self.assets:batchImport("scenes.mainmenu.assets")
print(self.assets:getFont("medium"))
self:addMenu("main", true) local menu = self:addMenu()
for i=1, 4 do for i=1, 4 do
local name = i .. "player" local name = i .. "player"
self:addSubMenu(name, name) menu:addSubmenu(name, core.lang:translate("commons", name))
if i == 1 then if i == 1 then
self:addScene(name, scenes.Plateformer, "plateform", i) self:addScene(scenes.Plateformer, "plateform", i)
end end
self:addScene(name, scenes.MovePlayer, "topdown", i) self:addScene(scenes.MovePlayer, "topdown", i)
self:addScene(name, scenes.MovePlayer3D, "topdown3D", i) self:addScene(scenes.MovePlayer3D, "topdown3D", i)
self:addScene(name, scenes.Action3D, "bigmap3D", i) self:addScene(scenes.Action3D, "bigmap3D", i)
if i > 1 then if i > 1 then
self:addScene(name, scenes.MovePlayer, "topdown (zoom)", i, "zoom") self:addScene(scenes.MovePlayer, "topdown (zoom)", i, "zoom")
self:addScene(name, scenes.MovePlayer3D, "topdown3D (zoom)", i, "zoom") self:addScene(scenes.MovePlayer3D, "topdown3D (zoom)", i, "zoom")
end end
end end
self:addSubMenu("menus", "menu") self:addSubMenu("menus", "menu")
self:addScene("menus", scenes.Inventory, "inventory") self:addScene(scenes.Inventory, "inventory")
self:addScene("menus", scenes.Options, "options") self:addScene(scenes.Options, "options")
self:addScene(scenes.TestMenu, "tests")
self.menusystem:setSoundFromSceneAssets("navigate") self.menusystem:setSoundFromSceneAssets("navigate")
local menu = self.menusystem.menus[MENU_NAME]
menu:switch("main")
ExitWidget(self, "main") ExitWidget(self, "main")
self.menusystem:switchMenu("main") self.menusystem:switchMenu(MENU_NAME)
end end
-- MENU FUNCTION -- MENU FUNCTION
-- Functions that serve the handling of menus -- Functions that serve the handling of menus
function MainMenu:addMenu(name, nobackbutton) function MainMenu:addMenu()
local screenHeight, screenWidth = core.screen:getDimensions() local w = 424/2
local w, h = 424/2, 240 - 48
local x, y = w / 2, 24 local x, y = w / 2, 24
ListBox(self.menusystem, name, x, y, w, h, 8) return TextMenu(MENU_NAME, "medium", x, y, w, 8, 0)
end end
function MainMenu:addSubMenu(name, fullname) function MainMenu:addSubMenu(name, fullname)
self:addMenu(name) local menu = self.menusystem.menus[MENU_NAME]
SubMenuWidget(self, "main", name, fullname) menu:addSubmenu(name, core.lang:translate("mainmenu", fullname))
SubMenuWidget(self, name, "main", "back", 1)
end end
function MainMenu:addScene(submenu, scene, fullname, arg1, arg2, arg3, arg4, arg5) function MainMenu:addScene(scene, fullname, arg1, arg2, arg3, arg4, arg5)
local args = {arg1, arg2, arg3, arg4, arg5} local args = {arg1, arg2, arg3, arg4, arg5}
SceneWidget(self, submenu, scene, fullname, args) SceneWidget(self, MENU_NAME, scene, fullname, args)
end end
function MainMenu:draw() function MainMenu:draw()
@ -92,40 +95,14 @@ end
-- WIDGETS -- WIDGETS
-- Widgets used by menus -- Widgets used by menus
-- Submenu widget :: go to a submenu
function SubMenuWidget:new(scene, menu, newmenu, fullname, order)
self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets:getFont("medium")
self.newmenu = newmenu
local label = ""
if fullname == "back" then
label = core.lang:translate("commons", fullname)
self.sfx = "cancel"
else
label = core.lang:translate("mainmenu", fullname)
self.sfx = "confirm"
end
SubMenuWidget.super.new(self, widgetmenu, font, label)
self.order = order or 0
end
function SubMenuWidget:action()
self.scene.assets:playSFX(self.sfx)
self.scene.menusystem:switchMenu(self.newmenu)
end
-- Scene widget :: switch scene -- Scene widget :: switch scene
function SceneWidget:new(scene, menu, newscene, fullname, args) function SceneWidget:new(scene, menu, newscene, fullname, args)
self.scene = scene self.scene = scene
self.args = args self.args = args
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets:getFont("medium")
self.newscene = newscene self.newscene = newscene
local label = core.lang:translate("mainmenu", fullname) local label = core.lang:translate("mainmenu", fullname)
SceneWidget.super.new(self, widgetmenu, font, label) SceneWidget.super.new(self, MENU_NAME, label)
end end
function SceneWidget:action() function SceneWidget:action()
@ -138,10 +115,8 @@ end
function ExitWidget:new(scene, menu) function ExitWidget:new(scene, menu)
self.scene = scene self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets:getFont("medium")
local label = core.lang:translate("commons", "exit") local label = core.lang:translate("commons", "exit")
SceneWidget.super.new(self, widgetmenu, font, label) SceneWidget.super.new(self, MENU_NAME, label)
end end
function ExitWidget:action() function ExitWidget:action()

View file

@ -24,9 +24,9 @@
local Scene = require "birb.modules.scenes" local Scene = require "birb.modules.scenes"
local Inventory = Scene:extend() local Inventory = Scene:extend()
local HListBox = require "birb.modules.menusystem.hlistbox" local HListBox = require "birb.modules.menusystem.menus.hlistbox"
local FloxBox = require "birb.modules.menusystem.flowbox" local FloxBox = require "birb.modules.menusystem.menus.flowbox"
local Widget = require "birb.modules.menusystem.widgets" local Widget = require "birb.modules.menusystem.menus.widgets"
local InventoryWidget = Widget.Text:extend() local InventoryWidget = Widget.Text:extend()
local ItemWidget = Widget.Text:extend() local ItemWidget = Widget.Text:extend()

View file

@ -0,0 +1,8 @@
local consts = {}
consts.OPTION_MENU = "optionMenu"
consts.BORDERS_W = 96
consts.BORDERS_H = 24
consts.NBR_ELEMS = 8
return consts

View file

@ -24,10 +24,12 @@
local Scene = require "birb.modules.scenes" local Scene = require "birb.modules.scenes"
local OptionsMenu = Scene:extend() local OptionsMenu = Scene:extend()
local ListBox = require "birb.modules.menusystem.listbox"
local Widgets = require "scenes.menus.options.widgets" local Widgets = require "scenes.menus.options.widgets"
local Menu = require "scenes.menus.options.menu"
function OptionsMenu:new() local consts = require "scenes.menus.options.consts"
function OptionsMenu:start()
OptionsMenu.super.new(self) OptionsMenu.super.new(self)
self.assets:addImageFont("medium", "assets/fonts/medium") self.assets:addImageFont("medium", "assets/fonts/medium")
self.assets:setMusic("assets/music/options.ogg") self.assets:setMusic("assets/music/options.ogg")
@ -38,26 +40,31 @@ function OptionsMenu:new()
self.assets:playMusic() self.assets:playMusic()
self:addMenu("main", true) self.menu = Menu("medium");
self:addSubMenu("video", "video") self:addSubMenu("video", "video")
self:addSubMenu("audio", "audio")
self:addSubMenu("langs", "langs")
self:addSubMenu("inputs", "inputs")
Widgets.Resolution(self, "video") Widgets.Resolution(self, "video")
Widgets.Switch(self, "video", "fullscreen") Widgets.Switch("fullscreen")
Widgets.Switch(self, "video", "borders") Widgets.Switch("borders")
Widgets.Switch(self, "video", "vsync") Widgets.Switch("vsync")
self:addPlayerMenus() self:addSubMenu("audio", "audio")
Widgets.Audio("sfx")
Widgets.Audio("music")
self:addSubMenu("langs", "langs")
self:setLanguageMenu() self:setLanguageMenu()
Widgets.Audio(self, "audio", "sfx") self:addSubMenu("inputs", "inputs")
Widgets.Audio(self, "audio", "music")
self:addPlayerMenus()
local menu = self.menusystem.menus[consts.OPTION_MENU]
menu:switch("main")
Widgets.Exit(self, "main") Widgets.Exit(self, "main")
self.menusystem:switchMenu("main") self.menusystem:switchMenu(consts.OPTION_MENU)
self.menusystem:setSoundFromSceneAssets("navigate") self.menusystem:setSoundFromSceneAssets("navigate")
@ -69,29 +76,19 @@ end
-- Functions that serve the handling of menus -- Functions that serve the handling of menus
function OptionsMenu:addMenu(name, nobackbutton) function OptionsMenu:addMenu(name, nobackbutton)
local screenHeight, screenWidth = core.screen:getDimensions() Menu("medium")
local w, h = 424/2, 240 - 48
local x, y = w / 2, 24
ListBox(self.menusystem, name, x, y, w, h, 8)
end end
function OptionsMenu:addSubMenu(name, fullname) function OptionsMenu:addSubMenu(name, fullname)
self:addMenu(name) local menu = self.menusystem.menus[consts.OPTION_MENU]
Widgets.SubMenu(self, "main", name, fullname) menu:addSubmenu(name, core.lang:translate("options", fullname), "main")
Widgets.SubMenu(self, name, "main", "back", 1, "<")
end end
function OptionsMenu:addPlayerMenus() function OptionsMenu:addPlayerMenus()
for i,v in ipairs(core.input.data) do for key, _ in pairs(core.input.data[1].keys) do
local menu = "player" .. i -- FIXME: make sure that you can use the order you want for the keys list
self:addMenu(menu) -- instead of a random one
Widgets.PlayerSubMenu(self, "inputs", i) Widgets.Key(key)
for k,w in pairs(v.keys) do
-- FIXME: make sure that you can use the order you want for the keys list
-- instead of a random one
Widgets.Key(self, i, k)
end
Widgets.SubMenu(self, menu, "inputs", "back", 1, "<")
end end
end end
@ -100,8 +97,8 @@ function OptionsMenu:addScene(submenu, scene, fullname)
end end
function OptionsMenu:setLanguageMenu() function OptionsMenu:setLanguageMenu()
for i,v in ipairs(core.lang.data.available) do for i,lang in ipairs(core.lang.data.available) do
Widgets.Lang(self, "langs", v) Widgets.Lang(lang)
end end
end end
@ -121,6 +118,7 @@ end
function OptionsMenu:draw() function OptionsMenu:draw()
love.graphics.setColor(.3, .1, .4, 1) love.graphics.setColor(.3, .1, .4, 1)
love.graphics.rectangle("fill", 0, 0, 424, 240) love.graphics.rectangle("fill", 0, 0, 424, 240)
utils.graphics.resetColor()
end end
return OptionsMenu return OptionsMenu

View file

@ -0,0 +1,14 @@
local TextMenu = require "birb.modules.menusystem.textmenu"
local OptionMenu = TextMenu:extend()
local consts = require "examples.scenes.menus.options.consts"
function OptionMenu:new(font)
local screenWidth, _ = core.screen:getDimensions()
local w = screenWidth - (consts.BORDERS_W*2)
local x = consts.BORDERS_W
local y = consts.BORDERS_H
OptionMenu.super.new(self, consts.OPTION_MENU, font, x, y, w, consts.NBR_ELEMS, 8)
end
return OptionMenu

View file

@ -23,15 +23,15 @@
local widgets = {} local widgets = {}
local Widget = require "birb.modules.menusystem.widgets" local Widget = require "birb.modules.menusystem.textmenu.widgets.basic"
local DoubleTextWidget = Widget.Text:extend() local DoubleTextWidget = Widget:extend()
widgets.SubMenu = DoubleTextWidget:extend() widgets.SubMenu = DoubleTextWidget:extend()
widgets.Dummy = Widget.Text:extend() widgets.Dummy = Widget:extend()
widgets.Exit = Widget.Text:extend() widgets.Exit = Widget:extend()
widgets.Switch = DoubleTextWidget:extend() widgets.Switch = DoubleTextWidget:extend()
widgets.Resolution = DoubleTextWidget:extend() widgets.Resolution = DoubleTextWidget:extend()
widgets.Lang = Widget.Text:extend() widgets.Lang = Widget:extend()
widgets.PlayerSubMenu = DoubleTextWidget:extend() widgets.PlayerSubMenu = DoubleTextWidget:extend()
widgets.Key = DoubleTextWidget:extend() widgets.Key = DoubleTextWidget:extend()
widgets.Audio = DoubleTextWidget:extend() widgets.Audio = DoubleTextWidget:extend()
@ -41,44 +41,33 @@ widgets.Audio = DoubleTextWidget:extend()
-- DoubleText widget : a two-side text widget -- DoubleText widget : a two-side text widget
function DoubleTextWidget:new(menu, font, label1, label2) function DoubleTextWidget:new(label1, label2)
DoubleTextWidget.super.new(self, menu, font, label1) DoubleTextWidget.super.new(self, "optionMenu", label1, "left")
self.label2 = label2 or "" local label2 = label2 or ""
end self:addLabel(label2, "right")
function DoubleTextWidget:drawCanvas()
local w, h
w = math.floor(self.width)
h = math.floor(self.height / 2) - (self.font:getHeight() / 2)
self.font:draw(self.label, 4, h, -1, "left")
self.font:draw(self.label2, w-4, h, -1, "right")
end end
-- Submenu widget :: go to a submenu -- Submenu widget :: go to a submenu
function widgets.SubMenu:new(scene, menu, newmenu, fullname, order, label2) function widgets.SubMenu:new(scene, newmenu, fullname, order, label2)
self.scene = scene self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
local label = core.lang:translate("options", fullname) local label = core.lang:translate("options", fullname)
local label2 = label2 or ">" local label2 = label2 or ">"
self.newmenu = newmenu self.newmenu = newmenu
widgets.SubMenu.super.new(self, widgetmenu, font, label, label2) widgets.SubMenu.super.new(self, label, label2)
self.order = order or 0 self.order = order or 0
end end
function widgets.SubMenu:action() function widgets.SubMenu:action()
self.scene.assets:playSFX("confirm") self.scene.assets:playSFX("confirm")
self.scene.menusystem:switchMenu(self.newmenu) self.menu:switch(self.newmenu)
end end
-- Dummy widget :: An empty widget to serve as a base for others -- Dummy widget :: An empty widget to serve as a base for others
function widgets.Dummy:new(scene, menu, fullname) function widgets.Dummy:new(scene, menu, fullname)
self.scene = scene self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu] widgets.Dummy.super.new(self, menu, fullname)
local font = self.scene.assets.fonts["medium"]
widgets.Dummy.super.new(self, widgetmenu, font, fullname)
end end
function widgets.Dummy:action() function widgets.Dummy:action()
@ -89,14 +78,12 @@ end
function widgets.Exit:new(scene, menu) function widgets.Exit:new(scene, menu)
self.scene = scene self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
local label = core.lang:translate("commons", "exit") local label = core.lang:translate("commons", "exit")
widgets.Exit.super.new(self, widgetmenu, font, "Exit") widgets.Exit.super.new(self, "optionMenu", label, "left")
end end
function widgets.Exit:action() function widgets.Exit:action()
self.scene.assets:playSFX("confirm") self.assets:playSFX("confirm")
core.scenemanager:setStoredScene("mainmenu") core.scenemanager:setStoredScene("mainmenu")
end end
@ -105,14 +92,11 @@ end
-- Switch widget (One widget to handle graphical switch) -- Switch widget (One widget to handle graphical switch)
function widgets.Switch:new(scene, menu, keyname) function widgets.Switch:new(keyname)
self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
self.keyname = keyname self.keyname = keyname
local label = core.lang:translate("options", keyname) local label = core.lang:translate("options", keyname)
local label2 = self:getLabel() local label2 = self:getLabel()
widgets.Switch.super.new(self, widgetmenu, font, label, label2) widgets.Switch.super.new(self, label, label2)
self.order = 0 self.order = 0
end end
@ -152,21 +136,19 @@ end
function widgets.Switch:action() function widgets.Switch:action()
self:modifyKey() self:modifyKey()
self.scene.assets:playSFX("confirm") local scene = core.scenemanager.currentScene
self.label2 = self:getLabel() scene.assets:playSFX("confirm")
self:replaceLabel(2, self:getLabel())
core.options:write() core.options:write()
self:invalidateCanvas() self:invalidateCanvas()
end end
-- Resolution Widget -- Resolution Widget
function widgets.Resolution:new(scene, menu) function widgets.Resolution:new()
self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
local label = core.lang:translate("options", "resolution") local label = core.lang:translate("options", "resolution")
local label2 = self:getLabel() local label2 = self:getLabel()
widgets.Resolution.super.new(self, widgetmenu, font, label, label2) widgets.Resolution.super.new(self, label, label2)
end end
function widgets.Resolution:getLabel() function widgets.Resolution:getLabel()
@ -179,9 +161,10 @@ function widgets.Resolution:action()
else else
core.options.data.video.resolution = core.options.data.video.resolution + 1 core.options.data.video.resolution = core.options.data.video.resolution + 1
end end
self.label2 = self:getLabel() self:replaceLabel(2, self:getLabel())
core.screen:applySettings() core.screen:applySettings()
self.scene.assets:playSFX("confirm") local scene = core.scenemanager.currentScene
scene.assets:playSFX("confirm")
self:invalidateCanvas() self:invalidateCanvas()
core.options:write() core.options:write()
end end
@ -189,17 +172,15 @@ end
-- LANGS WIDGET -- LANGS WIDGET
-- Allow you to change the lang of the game -- Allow you to change the lang of the game
function widgets.Lang:new(scene, menu, lang) function widgets.Lang:new(lang)
self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
local label = core.lang:getLangName(lang) local label = core.lang:getLangName(lang)
self.lang = lang self.lang = lang
widgets.Lang.super.new(self, widgetmenu, font, label) widgets.Lang.super.new(self, "optionMenu", label, "left")
end end
function widgets.Lang:action() function widgets.Lang:action()
self.scene.assets:playSFX("confirm") local scene = core.scenemanager.currentScene
scene.assets:playSFX("confirm")
core.options:setLanguage(self.lang) core.options:setLanguage(self.lang)
--self.scene.menusystem:invalidateAllWidgets() --self.scene.menusystem:invalidateAllWidgets()
end end
@ -209,35 +190,31 @@ end
function widgets.PlayerSubMenu:new(scene, menu, sourceid) function widgets.PlayerSubMenu:new(scene, menu, sourceid)
self.scene = scene self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
local label = core.lang:translate("options", "player") .. " " .. sourceid local label = core.lang:translate("options", "player") .. " " .. sourceid
local label2 = ">" local label2 = ">"
self.newmenu = "player" .. sourceid self.newmenu = "player" .. sourceid
widgets.PlayerSubMenu.super.new(self, widgetmenu, font, label, label2) widgets.PlayerSubMenu.super.new(self, label, label2)
self.order = 0 self.order = 0
end end
function widgets.PlayerSubMenu:action() function widgets.PlayerSubMenu:action()
self.scene.assets:playSFX("confirm") local scene = core.scenemanager.currentScene
self.scene.menusystem:switchMenu(self.newmenu) scene.assets:playSFX("confirm")
scene.menusystem:switchMenu(self.newmenu)
end end
-- Key widgets -- Key widgets
function widgets.Key:new(scene, sourceid, key) function widgets.Key:new(key)
self.scene = scene self.source = 1
self.source = sourceid
self.key = key self.key = key
local menu = "player" .. self.source local menu = "player" .. self.source
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
local label = self.key local label = self.key
local label2 = self:getLabel() local label2 = self:getLabel()
widgets.Key.super.new(self, widgetmenu, font, label, label2) widgets.Key.super.new(self, label, label2)
self.order = 0 self.order = 0
end end
@ -246,28 +223,27 @@ function widgets.Key:getLabel()
end end
function widgets.Key:action() function widgets.Key:action()
self.scene.assets:playSFX("navigate") local scene = core.scenemanager.currentScene
self.scene:changeKey(self) scene.assets:playSFX("navigate")
self.scene.menusystem:deactivate() scene:changeKey(self)
scene.menusystem:deactivate()
end end
function widgets.Key:receiveKey( key ) function widgets.Key:receiveKey( key )
self.scene.assets:playSFX("confirm") local scene = core.scenemanager.currentScene
scene.assets:playSFX("confirm")
core.options:setInputKey(self.source, self.key, key) core.options:setInputKey(self.source, self.key, key)
self.label2 = self:getLabel() self:replaceLabel(2, self:getLabel())
self:invalidateCanvas() self:invalidateCanvas()
end end
-- AUDIO FUNCTIONS -- AUDIO FUNCTIONS
-- Sounds/Music functions -- Sounds/Music functions
function widgets.Audio:new(scene, menu, audiotype) function widgets.Audio:new(audiotype)
self.scene = scene
self.audiotype = audiotype self.audiotype = audiotype
local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"]
self.audiotype = audiotype self.audiotype = audiotype
local label = "" local label = ""
if (self.audiotype == "sfx") then if (self.audiotype == "sfx") then
@ -277,7 +253,7 @@ function widgets.Audio:new(scene, menu, audiotype)
end end
local label2 = self:getLabel() local label2 = self:getLabel()
widgets.Audio.super.new(self, widgetmenu, font, label, label2) widgets.Audio.super.new(self, label, label2)
self.order = 0 self.order = 0
end end
@ -306,15 +282,16 @@ function widgets.Audio:setVolume(vol)
core.options.data.audio.music = vol core.options.data.audio.music = vol
end end
self.label2 = self:getLabel() self:replaceLabel(2, self:getLabel())
self:invalidateCanvas() self:invalidateCanvas()
end end
function widgets.Audio:action() function widgets.Audio:action()
local value = self:getVolume() local value = self:getVolume()
self:setVolume(value - 20) self:setVolume(value - 20)
self.scene.assets:playSFX("confirm") local scene = core.scenemanager.currentScene
self.scene.assets.music:setVolume(core.options.data.audio.music / 100) scene.assets:playSFX("confirm")
core.music:applyVolume()
core.options:write() core.options:write()
end end