Compare commits
No commits in common. "master" and "big-refactor" have entirely different histories.
master
...
big-refact
8
.vscode/settings.json
vendored
|
@ -9,13 +9,5 @@
|
|||
"utils",
|
||||
"birb",
|
||||
"enum"
|
||||
],
|
||||
"Lua.runtime.version": "LuaJIT",
|
||||
"Lua.workspace.library": [
|
||||
"${3rd}/love2d/library"
|
||||
],
|
||||
"Lua.workspace.checkThirdParty": false,
|
||||
"Lua.diagnostics.disable": [
|
||||
"redundant-parameter"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -45,7 +45,4 @@ Some elements have been modified from the sources used. If you use some elements
|
|||
|
||||
### HUD elements used
|
||||
|
||||
|
||||
- [Sonic Heroes HUD](https://www.spriters-resource.com/custom_edited/sonicthehedgehogcustoms/sheet/104761/) by [FieryExplosion](https://www.spriters-resource.com/submitter/FieryExplosion/)
|
||||
- [Sonic Adventure 2](https://www.spriters-resource.com/custom_edited/sonicthehedgehogcustoms/sheet/104763/) by [FieryExplosion](https://www.spriters-resource.com/submitter/FieryExplosion/)
|
||||
- [Sonic Unleashed Mini QTE Prompt](https://www.spriters-resource.com/fullview/150622/) by [FieryExplosion](https://www.spriters-resource.com/submitter/FieryExplosion/)
|
||||
- [Sonic Heroes HUD](https://www.spriters-resource.com/custom_edited/sonicthehedgehogcustoms/sheet/104761/), [Sonic Adventure 2](https://www.spriters-resource.com/custom_edited/sonicthehedgehogcustoms/sheet/104763/) pixel versions by [FieryExplosion](https://www.spriters-resource.com/submitter/FieryExplosion/)
|
||||
|
|
1
debug.sh
|
@ -1 +0,0 @@
|
|||
love ./sonic-radiance.love DEBUGLEVEL=4
|
|
@ -1 +0,0 @@
|
|||
love ./sonic-radiance.love
|
|
@ -1,32 +0,0 @@
|
|||
return {
|
||||
["tilesets"] = {
|
||||
{"charicons", "assets/sprites/characters/charicons"},
|
||||
{"normaltiles", "assets/backgrounds/normaltile"},
|
||||
{"sptiles", "assets/backgrounds/specialtile"},
|
||||
{"borders", "assets/backgrounds/borders"},
|
||||
{"ranks", "assets/gui/ranks"},
|
||||
{"qtebtn", "assets/gui/qtebtn"}
|
||||
},
|
||||
["textures"] = {
|
||||
{"expbar", "assets/gui/expbar.png"},
|
||||
{"actorsShadow", "assets/sprites/shadow.png"},
|
||||
{"emptytile", "assets/backgrounds/tilemask.png"},
|
||||
|
||||
{"badnicsIcon", "assets/sprites/characters/badnics.png"},
|
||||
|
||||
{"hudturn", "assets/gui/strings/hudturn.png"},
|
||||
{"battlecompleted", "assets/gui/strings/battle_completed.png" },
|
||||
{"egghead", "assets/gui/egghead.png"},
|
||||
|
||||
{"crown", "assets/gui/crown.png"}
|
||||
},
|
||||
["sfx"] = {
|
||||
{"hit", "assets/sfx/hit.wav"},
|
||||
{"hitconnect", "assets/sfx/hitconnect.wav"},
|
||||
{"jump", "assets/sfx/jump.wav"},
|
||||
{"woosh", "assets/sfx/woosh.wav"},
|
||||
{"spincharge", "assets/sfx/spincharge.wav"},
|
||||
{"spinrelease", "assets/sfx/spinrelease.wav"},
|
||||
{"badnicsBoom", "assets/sfx/badnicsDestroyed.wav"}
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
return {
|
||||
["tilesets"] = {
|
||||
{"charicons", "assets/sprites/characters/charicons"},
|
||||
{"normaltiles", "assets/backgrounds/normaltile"},
|
||||
{"sptiles", "assets/backgrounds/specialtile"},
|
||||
{"borders", "assets/backgrounds/borders"},
|
||||
},
|
||||
["sprites"] = {
|
||||
{"cursorground", "assets/gui/cursor/ground"},
|
||||
{"hitGFX", "assets/sprites/gfx/hit1"},
|
||||
},
|
||||
["textures"] = {
|
||||
{"statusbar", "assets/gui/status_bar.png"},
|
||||
{"actorsShadow", "assets/sprites/shadow.png"},
|
||||
{"emptytile", "assets/backgrounds/tilemask.png"},
|
||||
|
||||
{"hudturn", "assets/gui/strings/hudturn.png"},
|
||||
{"battlecompleted", "assets/gui/strings/battle_completed.png" }
|
||||
},
|
||||
["sfx"] = {
|
||||
{"hit", "assets/sfx/hit.wav"},
|
||||
{"hitconnect", "assets/sfx/hitconnect.wav"},
|
||||
{"jump", "assets/sfx/jump.wav"},
|
||||
{"woosh", "assets/sfx/woosh.wav"},
|
||||
{"spincharge", "assets/sfx/spincharge.wav"},
|
||||
{"spinrelease", "assets/sfx/spinrelease.wav"}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 3.2 KiB |
BIN
sonic-radiance.love/assets/gui/arrow.png
Normal file
After Width: | Height: | Size: 463 B |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.4 KiB |
|
@ -1,6 +0,0 @@
|
|||
return {
|
||||
metadata = {
|
||||
height = 7,
|
||||
width = 14,
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 719 B |
Before Width: | Height: | Size: 906 B After Width: | Height: | Size: 444 B |
BIN
sonic-radiance.love/assets/gui/fonts/Pokemon DPPt.ttf
Normal file
BIN
sonic-radiance.love/assets/gui/fonts/RussoOne-Regular.ttf
Normal file
BIN
sonic-radiance.love/assets/gui/fonts/Teko-Bold.ttf
Normal file
|
@ -1,4 +1,4 @@
|
|||
return {
|
||||
glyphs = " 0123456789/ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
glyphs = " 0123456789/",
|
||||
extraspacing = 0,
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
sonic-radiance.love/assets/gui/fonts/kimberley bl.ttf
Normal file
4
sonic-radiance.love/assets/gui/fonts/sadv.lua
Normal file
|
@ -0,0 +1,4 @@
|
|||
return {
|
||||
glyphs = "abcdefghijklmnopqrstuvwxyz0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
extraspacing = 1
|
||||
}
|
BIN
sonic-radiance.love/assets/gui/fonts/sadv.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
sonic-radiance.love/assets/gui/fonts/vipnagorgialla.ttf
Normal file
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 7.7 KiB |
BIN
sonic-radiance.love/assets/gui/progressbar.png
Normal file
After Width: | Height: | Size: 790 B |
|
@ -1,6 +0,0 @@
|
|||
return {
|
||||
metadata = {
|
||||
width = 17,
|
||||
height = 17,
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.3 KiB |
|
@ -1,6 +0,0 @@
|
|||
return {
|
||||
metadata = {
|
||||
width = 24,
|
||||
height = 24,
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 4.5 KiB |
BIN
sonic-radiance.love/assets/gui/strings/game.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
sonic-radiance.love/assets/gui/strings/over.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
sonic-radiance.love/assets/gui/strings/press_start.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
@ -1,18 +0,0 @@
|
|||
return {
|
||||
metadata = {
|
||||
width = 33,
|
||||
height = 44,
|
||||
defaultAnim = "default",
|
||||
ox = 16,
|
||||
oy = 22,
|
||||
},
|
||||
animations = {
|
||||
["default"] = {
|
||||
startAt = 1,
|
||||
endAt = 7,
|
||||
loop = 1,
|
||||
speed = 15,
|
||||
pauseAtEnd = false,
|
||||
},
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 2.4 KiB |
|
@ -1,18 +0,0 @@
|
|||
return {
|
||||
metadata = {
|
||||
width = 64,
|
||||
height = 54,
|
||||
defaultAnim = "default",
|
||||
ox = 32,
|
||||
oy = 48,
|
||||
},
|
||||
animations = {
|
||||
["default"] = {
|
||||
startAt = 1,
|
||||
endAt = 15,
|
||||
loop = 1,
|
||||
speed = 30,
|
||||
pauseAtEnd = false,
|
||||
},
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 15 KiB |
|
@ -67,10 +67,6 @@ function Rect:getRelativeCoordinate(dx, dy)
|
|||
return dx - self.x, dy - self.y
|
||||
end
|
||||
|
||||
function Rect:getDimensions()
|
||||
return self.w, self.h
|
||||
end
|
||||
|
||||
function Rect:drawBox()
|
||||
utils.graphics.box(self.x, self.y, self.w, self.h)
|
||||
end
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
-- datapack.lua :: a categorized and indexed pack of data. Aim to make easy to get
|
||||
-- the category from an element, without having
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 DataPack = Object:extend()
|
||||
|
||||
local UNCATEGORIZED = "uncategorized"
|
||||
|
||||
function DataPack:new(foldername, categories, areFiles, subfiles)
|
||||
self.foldername = foldername
|
||||
self.areFiles = (areFiles ~= false)
|
||||
self.subfiles = subfiles or {}
|
||||
self.categories = categories or {}
|
||||
--print("loading " .. foldername)
|
||||
self:loadAllDatas()
|
||||
end
|
||||
|
||||
function DataPack:getBaseDirectory(lua)
|
||||
local foldername = self.foldername
|
||||
if (not lua) then
|
||||
foldername = string.gsub(foldername, "%.", "/")
|
||||
end
|
||||
return utils.datas.concatDataFolder(foldername, lua)
|
||||
end
|
||||
|
||||
function DataPack:getCategoryDirectory(category, lua)
|
||||
if (category == UNCATEGORIZED) then
|
||||
return self:getBaseDirectory(lua)
|
||||
else
|
||||
return utils.datas.concatFolder(self:getBaseDirectory(lua), category, lua)
|
||||
end
|
||||
end
|
||||
|
||||
function DataPack:haveCategories()
|
||||
return (#self.categories > 0)
|
||||
end
|
||||
|
||||
function DataPack:loadAllDatas()
|
||||
self.index = {}
|
||||
self.reverseIndex = {}
|
||||
|
||||
if (self:haveCategories()) then
|
||||
for i, category in ipairs(self.categories) do
|
||||
self:loadDatas(category)
|
||||
end
|
||||
else
|
||||
self:loadDatas(UNCATEGORIZED)
|
||||
end
|
||||
end
|
||||
|
||||
function DataPack:loadDatas(category)
|
||||
local directory = self:getCategoryDirectory(category)
|
||||
local items = love.filesystem.getDirectoryItems(directory)
|
||||
self.reverseIndex[category] = {}
|
||||
for i, filename in ipairs(items) do
|
||||
if (utils.datas.isLuaFile(filename) == self.areFiles) then
|
||||
if (self.areFiles) then
|
||||
filename = utils.datas.luaFileToModule(filename)
|
||||
end
|
||||
|
||||
if (self.index[filename] ~= nil) then
|
||||
error("Data " .. filename .. " already exists for " .. self.foldername)
|
||||
end
|
||||
--print("loading " .. filename .. " from category " .. category .. " for " .. self.foldername)
|
||||
self.index[filename] = category
|
||||
table.insert(self.reverseIndex[category], filename)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DataPack:dataExists(name)
|
||||
return (self.index[name] ~= nil)
|
||||
end
|
||||
|
||||
function DataPack:getPath(name, lua)
|
||||
if (not self:dataExists(name)) then
|
||||
error("Data " .. name .. " do not exist for " .. self.foldername)
|
||||
end
|
||||
local category = self.index[name]
|
||||
|
||||
local categoryDirectory = self:getCategoryDirectory(category, true)
|
||||
|
||||
return utils.datas.concatFolder(categoryDirectory, name, lua)
|
||||
end
|
||||
|
||||
function DataPack:get(name)
|
||||
local path = self:getPath(name, true)
|
||||
local data = utils.datas.copy(path)
|
||||
if (not self.areFiles) then
|
||||
for i, subfile in ipairs(self.subfiles) do
|
||||
data[subfile] = utils.datas.copyDataset(path, subfile)
|
||||
end
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
function DataPack:getFromCategory(category)
|
||||
return self.reverseIndex[category] or {}
|
||||
end
|
||||
|
||||
return DataPack
|
|
@ -1,63 +0,0 @@
|
|||
-- parser.lua :: a data parser, used to parse data from arguments
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 Parser = Object:extend()
|
||||
|
||||
function Parser:new(headings, argumentsList, argumentwrapper, nullableNbr)
|
||||
self.headings = headings
|
||||
self.argumentsList = argumentsList
|
||||
self.argumentwrapper = argumentwrapper or ""
|
||||
self.nullableNbr = nullableNbr or 0
|
||||
end
|
||||
|
||||
function Parser:getArguments(name)
|
||||
if (self.argumentsList[name] ~= nil) then
|
||||
local arguments = {}
|
||||
utils.table.mergeList(arguments, self.headings)
|
||||
utils.table.mergeList(arguments, self.argumentsList[name])
|
||||
return arguments
|
||||
else
|
||||
error("No arguments data for argumentList " .. name)
|
||||
end
|
||||
end
|
||||
|
||||
function Parser:parse(datas)
|
||||
local arguments = self:getArguments(datas[1])
|
||||
--print(utils.table.toString(arguments))
|
||||
local parsedData = utils.table.parse(datas, arguments, self.nullableNbr)
|
||||
if (utils.string.isEmpty(self.argumentwrapper)) then
|
||||
-- print(utils.table.toString(parsedData))
|
||||
return parsedData
|
||||
else
|
||||
local finalTable = {}
|
||||
for i, heading in ipairs(self.headings) do
|
||||
finalTable[heading] = parsedData[heading]
|
||||
parsedData[heading] = nil
|
||||
end
|
||||
finalTable[self.argumentwrapper] = parsedData
|
||||
-- print(utils.table.toString(finalTable))
|
||||
return finalTable
|
||||
end
|
||||
end
|
||||
|
||||
return Parser
|
|
@ -1,115 +0,0 @@
|
|||
-- classes/predicates :: a predicate system, to be an intermediary between condition
|
||||
-- solvers and complex conditions. You simply create a predicate with your data and the
|
||||
-- solver to create a predicate, then use the Predicate:solve() API to get your response
|
||||
|
||||
-- To create a Predicate, prefer the Predicate.createPredicate instead of Predicate:new()
|
||||
-- As it'll allow you to dynamically create simple or complex predicate on the fly
|
||||
-- while Predicate:new() will try to create a complex predicate
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 Predicate = Object:extend()
|
||||
local SimplePredicate = require "birb.classes.predicate.simple"
|
||||
|
||||
function Predicate.createPredicate(data, solver, asker)
|
||||
local predicate = nil
|
||||
if (type(data) == "table") then
|
||||
predicate = Predicate(data, solver, asker)
|
||||
end
|
||||
if (type(data) == "string") then
|
||||
predicate = SimplePredicate(data, solver, asker)
|
||||
end
|
||||
|
||||
if (predicate ~= nil) then
|
||||
return predicate
|
||||
else
|
||||
error("Predicate data aren't a table or a string : " .. tostring(data))
|
||||
end
|
||||
end
|
||||
|
||||
function Predicate:new(data ,solver, asker)
|
||||
self.solver = solver
|
||||
self.asker = asker
|
||||
self.beginAt = 1
|
||||
self:setType(data)
|
||||
self.notTag = false
|
||||
self:setList(data)
|
||||
end
|
||||
|
||||
function Predicate:solve()
|
||||
local predicateSolved
|
||||
if (self.type == "or") then
|
||||
predicateSolved = self:solveOr()
|
||||
else
|
||||
predicateSolved = self:solveAnd()
|
||||
end
|
||||
|
||||
if (self.notTag) then
|
||||
predicateSolved = (predicateSolved == false)
|
||||
end
|
||||
|
||||
return predicateSolved
|
||||
end
|
||||
|
||||
-- INTERNAL FUNCTIONS
|
||||
-- Handle the complex predicate
|
||||
|
||||
function Predicate:setType(data)
|
||||
self.type = "and"
|
||||
if (type(data[1]) == "string") then
|
||||
if (data[1] == "or") or (data[1] == "and") then
|
||||
self.beginAt = 2
|
||||
self.type = data[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Predicate:setList(data)
|
||||
self.list = {}
|
||||
for i = self.beginAt, #data, 1 do
|
||||
if (i == #data) and (data[i] == "not") then
|
||||
self.notTag = true
|
||||
else
|
||||
table.insert(self.list, Predicate.createPredicate(data[i], self.solver, self.asker))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Predicate:solveOr()
|
||||
for i, predicate in ipairs(self.list) do
|
||||
if (predicate:solve()) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Predicate:solveAnd()
|
||||
for i, predicate in ipairs(self.list) do
|
||||
if (not predicate:solve()) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return Predicate
|
|
@ -1,68 +0,0 @@
|
|||
-- classes/simple :: the actual solver of the predicate system. It parse a condition
|
||||
-- system, and pass the data to a solver function. If the last argument of a condition
|
||||
-- is "not", it'll negate the whole condition.
|
||||
|
||||
-- Each solver function will get as argument the list of conditions, the predicate and the
|
||||
-- asker. The predicate contain an utility subclass with some function to handle easily
|
||||
-- some stuff like converting truth tags or comparing numbers
|
||||
-- An empty string will return true, a non-existing solver question an error, except if the solver have a
|
||||
-- default function.
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 SimplePredicate = Object:extend()
|
||||
local SEPARATOR = ":"
|
||||
local NOT = "not"
|
||||
local DEFAULT = "default"
|
||||
|
||||
SimplePredicate.utils = require "birb.classes.predicate.utils"
|
||||
|
||||
function SimplePredicate:new(data, solver, asker)
|
||||
self.solver = solver
|
||||
self.asker = asker
|
||||
self.data = data
|
||||
end
|
||||
|
||||
function SimplePredicate:solve()
|
||||
if (utils.string.isEmpty(self.data)) then
|
||||
return true
|
||||
end
|
||||
local conditionArgs = utils.string.split(self.data, SEPARATOR)
|
||||
local solverFunction = self:getFunction(conditionArgs[1])
|
||||
local conditionFulfilled = solverFunction(conditionArgs, self, self.asker)
|
||||
if (conditionArgs[#conditionArgs] == NOT) then
|
||||
conditionFulfilled = (not conditionFulfilled)
|
||||
end
|
||||
return conditionFulfilled
|
||||
end
|
||||
|
||||
function SimplePredicate:getFunction(functionName)
|
||||
if (self.solver[functionName] == nil) then
|
||||
if (self.solver[DEFAULT] == nil) then
|
||||
error("Function " .. functionName .. " doesn't exist in solver, and it doesn't have a 'default' function.")
|
||||
end
|
||||
return self.solver[DEFAULT]
|
||||
end
|
||||
return self.solver[functionName]
|
||||
end
|
||||
|
||||
return SimplePredicate
|
|
@ -1,65 +0,0 @@
|
|||
-- predicate/utils :: Simple utilities for predicates
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 ConditionsUtils = {}
|
||||
|
||||
function ConditionsUtils.testVariables(var1, testType, var2)
|
||||
local var2 = tonumber(var2)
|
||||
if (testType == "eq" and var1 == var2) then
|
||||
return true
|
||||
end
|
||||
if (testType == "ne" and var1 ~= var2) then
|
||||
return true
|
||||
end
|
||||
if (testType == "gt" and var1 > var2) then
|
||||
return true
|
||||
end
|
||||
if (testType == "ge" and var1 >= var2) then
|
||||
return true
|
||||
end
|
||||
if (testType == "lt" and var1 < var2) then
|
||||
return true
|
||||
end
|
||||
if (testType == "le" and var1 <= var2) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function ConditionsUtils.testBool(bool, boolType)
|
||||
return (bool == (boolType == "V"))
|
||||
end
|
||||
|
||||
function ConditionsUtils.merge(cond)
|
||||
local returnString = ""
|
||||
for i, condElement in ipairs(cond) do
|
||||
returnString = returnString .. condElement
|
||||
if (i < #cond) then
|
||||
returnString = returnString .. ":"
|
||||
end
|
||||
end
|
||||
return returnString
|
||||
end
|
||||
|
||||
return ConditionsUtils;
|
|
@ -1,139 +0,0 @@
|
|||
-- classes/serializable :: a serializable object, can give its field as data
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 Serializable = Object:extend()
|
||||
|
||||
function Serializable:new(serializeFields, listSerializable)
|
||||
self.serializeFields = serializeFields
|
||||
self.listSerializable = listSerializable
|
||||
end
|
||||
|
||||
function Serializable:getData()
|
||||
local data = {}
|
||||
-- We serialize all fields
|
||||
if (self.serializeFields ~= nil) then
|
||||
for _, key in ipairs(self.serializeFields) do
|
||||
data[key] = self:wrapField(key)
|
||||
end
|
||||
end
|
||||
-- We serialize all list of serializable
|
||||
if (self.listSerializable ~= nil) then
|
||||
for _, key in ipairs(self.listSerializable) do
|
||||
data[key] = self:wrapList(key)
|
||||
end
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
function Serializable:wrapField(key)
|
||||
local serializedField = self[key]
|
||||
if (serializedField ~= nil) then
|
||||
if (type(serializedField) == "table" and serializedField.is ~= nil) then
|
||||
if (serializedField:is(Serializable)) then
|
||||
serializedField = serializedField:getData()
|
||||
serializedField.isSerializable = true
|
||||
end
|
||||
end
|
||||
self:print(key, serializedField, false)
|
||||
return serializedField
|
||||
end
|
||||
end
|
||||
|
||||
function Serializable:wrapList(key)
|
||||
local serializedList = {}
|
||||
serializedList.isListSerializable = true
|
||||
for listKey, listElement in pairs(self[key]) do
|
||||
serializedList[listKey] = listElement:getData()
|
||||
end
|
||||
self:print(key, serializedList, false)
|
||||
return serializedList
|
||||
end
|
||||
|
||||
function Serializable:setData(data)
|
||||
for key, value in pairs(data) do
|
||||
if (key ~= "serializedField") then
|
||||
self:unwrapField(key, value)
|
||||
end
|
||||
end
|
||||
self:finishDeserialization()
|
||||
end
|
||||
|
||||
function Serializable:unwrapField(key, value)
|
||||
local serializedField = value
|
||||
if (serializedField ~= nil) then
|
||||
if (type(serializedField) == "table") then
|
||||
if (serializedField.isSerializable == true) then
|
||||
self[key]:setData(serializedField)
|
||||
elseif (serializedField.isListSerializable) then
|
||||
self:unwrapList(key, serializedField)
|
||||
else
|
||||
self[key] = serializedField or self[key]
|
||||
end
|
||||
else
|
||||
self[key] = serializedField or self[key]
|
||||
self:print(key, serializedField, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Serializable:unwrapList(key, list)
|
||||
if (list == nil) then
|
||||
error("List " .. key .. " shouldn't be null in the save")
|
||||
end
|
||||
for listKey, listElement in pairs(list) do
|
||||
if (listKey ~= "isListSerializable") then
|
||||
self[key][listKey]:setData(listElement)
|
||||
end
|
||||
end
|
||||
self:print(key, list, true)
|
||||
end
|
||||
|
||||
function Serializable:print(key, value, isLoading)
|
||||
local loadString = "Loading "
|
||||
if (isLoading == false) then
|
||||
loadString = "Saving "
|
||||
end
|
||||
local valueString = value
|
||||
if type(valueString) == "boolean" then
|
||||
if valueString then
|
||||
valueString = "true"
|
||||
else
|
||||
valueString = "false"
|
||||
end
|
||||
end
|
||||
if (type(value) == "table") then
|
||||
valueString = utils.table.toString(value)
|
||||
end
|
||||
loadString = loadString .. key .. " " .. ": " .. valueString
|
||||
if (core ~= nil) then
|
||||
core.debug:debug("serializable", loadString)
|
||||
else
|
||||
--print("serializable", loadString)
|
||||
end
|
||||
end
|
||||
|
||||
function Serializable:finishDeserialization()
|
||||
-- Empty function callback
|
||||
end
|
||||
|
||||
return Serializable
|
|
@ -1,73 +0,0 @@
|
|||
-- classes/serializable/serializer :: a serializer, able to put stuff into a bin file
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 Serializable = require "birb.classes.serializable"
|
||||
local Serializer = Serializable:extend()
|
||||
local binser = require("birb.libs.binser")
|
||||
|
||||
function Serializer:new(serializeFields, listSerializable)
|
||||
Serializer.super.new(self, serializeFields, listSerializable)
|
||||
end
|
||||
|
||||
function Serializer:reset()
|
||||
|
||||
end
|
||||
|
||||
function Serializer:delete(filename)
|
||||
local filepath = self:getFile(true, filename)
|
||||
if utils.filesystem.exists(filename) then
|
||||
love.filesystem.remove(filepath)
|
||||
end
|
||||
end
|
||||
|
||||
function Serializer:deserialize(filename)
|
||||
local filepath = self:getFile(true, filename)
|
||||
if utils.filesystem.exists(filename) then
|
||||
local loadedDatas = binser.readFile(filepath)
|
||||
self:setData(loadedDatas[1])
|
||||
else
|
||||
self:reset()
|
||||
end
|
||||
end
|
||||
|
||||
function Serializer:serialize(filename)
|
||||
local data = self:getData()
|
||||
|
||||
local filepath = self:getFile(true, filename)
|
||||
binser.writeFile(filepath, data)
|
||||
end
|
||||
|
||||
function Serializer:getFile(absolute, filename)
|
||||
local dir = ""
|
||||
if absolute then
|
||||
dir = love.filesystem.getSaveDirectory() .. "/"
|
||||
if (not utils.filesystem.exists(dir)) then
|
||||
love.filesystem.createDirectory("")
|
||||
end
|
||||
end
|
||||
|
||||
local filepath = dir .. filename
|
||||
|
||||
return filepath
|
||||
end
|
||||
|
||||
return Serializer
|
|
@ -1,14 +0,0 @@
|
|||
local Timer = require "birb.classes.time.timer"
|
||||
local TimedFunction = Timer:extend()
|
||||
|
||||
function TimedFunction:new(actor, name, func, t)
|
||||
TimedFunction.super.new(self, actor, name, t)
|
||||
self.func = func
|
||||
end
|
||||
|
||||
function TimedFunction:finish()
|
||||
self.actor.funcs[self.name] = nil
|
||||
self.func()
|
||||
end
|
||||
|
||||
return TimedFunction
|
|
@ -27,7 +27,6 @@ local TweenManager = Object:extend()
|
|||
|
||||
local tween = require "birb.libs.tween"
|
||||
local Timer = require "birb.classes.time.timer"
|
||||
local TimedFunction = require "birb.classes.time.func"
|
||||
|
||||
function TweenManager:new(subject)
|
||||
self.subject = subject
|
||||
|
@ -37,85 +36,22 @@ function TweenManager:new(subject)
|
|||
self.switches = {}
|
||||
|
||||
self.timers = {}
|
||||
self.funcs = {}
|
||||
end
|
||||
|
||||
function TweenManager:newTween(start, duration, target, easing)
|
||||
table.insert(self.tweens, self:createTween(start, duration, target, easing))
|
||||
end
|
||||
|
||||
function TweenManager:setNamedTween(name, start, duration, target, easing)
|
||||
self.tweens[name] = nil
|
||||
self.tweens[name] = self:createTween(start, duration, target, easing)
|
||||
end
|
||||
|
||||
function TweenManager:createTween(start, duration, target, easing)
|
||||
local newTween = {}
|
||||
-- we add the data into a tween wrapper
|
||||
newTween.tween = tween.new(duration, self.subject, target, easing)
|
||||
newTween.start = self.time + start -- /!\ START IS RELATIVE TO CURRENT TIME
|
||||
newTween.clear = newTween.start + duration
|
||||
|
||||
return newTween
|
||||
table.insert(self.tweens, newTween)
|
||||
end
|
||||
|
||||
function TweenManager:removeNamedTween(name)
|
||||
self.tweens[name] = nil
|
||||
end
|
||||
|
||||
function TweenManager:haveTween()
|
||||
return #self.tweens > 0
|
||||
end
|
||||
|
||||
-- TIMER FUNCTIONS
|
||||
-- Help to get info from timers
|
||||
|
||||
function TweenManager:newTimer(start, name)
|
||||
self.timers[name] = Timer(self, name, start)
|
||||
end
|
||||
|
||||
function TweenManager:delayTimer(time, name, absolute)
|
||||
if (self.timers[name] ~= nil) then
|
||||
self.timers[name]:delay(time, absolute)
|
||||
end
|
||||
end
|
||||
|
||||
function TweenManager:getTimerInfo(name)
|
||||
if (self.timers[name] ~= nil) then
|
||||
return self.timers[name]:getInfo()
|
||||
end
|
||||
end
|
||||
|
||||
function TweenManager:removeTimer(name)
|
||||
self.timers[name] = nil
|
||||
end
|
||||
|
||||
-- FUNCTION FUNCTIONS
|
||||
-- Help to get functions
|
||||
|
||||
function TweenManager:newFunc(start, name, func)
|
||||
self.funcs[name] = TimedFunction(self, name, func, start)
|
||||
end
|
||||
|
||||
function TweenManager:delayFunc(time, name, absolute)
|
||||
if (self.funcs[name] ~= nil) then
|
||||
self.funcs[name]:delay(time, absolute)
|
||||
end
|
||||
end
|
||||
|
||||
function TweenManager:getFuncInfo(name)
|
||||
if (self.funcs[name] ~= nil) then
|
||||
return self.funcs[name]:getInfo()
|
||||
end
|
||||
end
|
||||
|
||||
function TweenManager:removeFunc(name)
|
||||
self.funcs[name] = nil
|
||||
end
|
||||
|
||||
-- SWITCH FUNCTIONS
|
||||
-- Help to handle switches
|
||||
|
||||
function TweenManager:newSwitch(start, bools)
|
||||
local newSwitch = {}
|
||||
-- we add the data into a tween wrapper
|
||||
|
@ -129,16 +65,13 @@ end
|
|||
function TweenManager:update(dt)
|
||||
self.time = self.time + dt
|
||||
|
||||
for key, tweenWrapper in pairs(self.tweens) do
|
||||
for i, tweenWrapper in ipairs(self.tweens) do
|
||||
if (self.time > tweenWrapper.start) then
|
||||
tweenWrapper.tween:update(dt)
|
||||
if (self.time > tweenWrapper.clear) then
|
||||
self.tweens[key] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, switch in pairs(self.switches) do
|
||||
for i, switch in ipairs(self.switches) do
|
||||
if (self.time > switch.start) then
|
||||
-- We test each boolean in the switch
|
||||
for i, bool in ipairs(switch.bools) do
|
||||
|
@ -158,10 +91,6 @@ function TweenManager:update(dt)
|
|||
timer:update(dt)
|
||||
end
|
||||
|
||||
for k, func in pairs(self.funcs) do
|
||||
func:update(dt)
|
||||
end
|
||||
|
||||
self:clearEndedTweens()
|
||||
end
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
local Timer = Object:extend()
|
||||
|
||||
function Timer:new(actor, name, t)
|
||||
self.baseTime = t
|
||||
self.time = t
|
||||
self.actor = actor
|
||||
self.name = name
|
||||
|
@ -37,23 +36,9 @@ function Timer:update(dt)
|
|||
end
|
||||
end
|
||||
|
||||
function Timer:delay(time, absolute)
|
||||
if (absolute == true) then
|
||||
self.baseTime = self.baseTime + (time - self.time)
|
||||
self.time = time
|
||||
else
|
||||
self.baseTime = self.baseTime + time
|
||||
self.time = self.time + time
|
||||
end
|
||||
end
|
||||
|
||||
function Timer:getInfo()
|
||||
return self.time, self.baseTime, (self.time / self.baseTime)
|
||||
end
|
||||
|
||||
function Timer:finish()
|
||||
self.actor.timers[self.name] = nil
|
||||
self.actor:timerResponse(self.name)
|
||||
self.actor.timers[self.name] = nil
|
||||
end
|
||||
|
||||
return Timer
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
-- datas.lua :: The main file of the core system, an object full of subsystem
|
||||
-- loaded by the game to handle the main functions (like screen, translation,
|
||||
-- inputs…)
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 DataManager = Object:extend()
|
||||
local DataPack = require "birb.classes.datapack"
|
||||
local Parser = require "birb.classes.parser"
|
||||
local index = require "datas.gamedata.index"
|
||||
|
||||
function DataManager:new(core)
|
||||
self.core = core
|
||||
self:loadDatas()
|
||||
self:loadParsers()
|
||||
end
|
||||
|
||||
function DataManager:loadDatas()
|
||||
self.datapacks = {}
|
||||
for key, datas in pairs(index.datapacks) do
|
||||
self.core.debug:debug("datamanager", "loading data for " .. key)
|
||||
self.datapacks[key] = DataPack(datas[1], datas[2], datas[3], datas[4], datas[5])
|
||||
end
|
||||
end
|
||||
|
||||
function DataManager:get(datapack, name)
|
||||
return self.datapacks[datapack]:get(name)
|
||||
end
|
||||
|
||||
function DataManager:exists(datapack, name)
|
||||
return self.datapacks[datapack]:dataExists(name)
|
||||
end
|
||||
|
||||
function DataManager:getFromCategory(datapack, category)
|
||||
return self.datapacks[datapack]:getFromCategory(category)
|
||||
end
|
||||
|
||||
function DataManager:getCategories(datapack)
|
||||
return self.datapacks[datapack].categories
|
||||
end
|
||||
|
||||
-- Load parsers
|
||||
|
||||
function DataManager:loadParsers()
|
||||
self.parsers = {}
|
||||
local items = love.filesystem.getDirectoryItems("datas/parsers")
|
||||
for i, item in ipairs(items) do
|
||||
local filename = utils.datas.luaFileToModule(item)
|
||||
local data = require("datas.parsers." .. filename)
|
||||
|
||||
self.core.debug:debug("datamanager", "creating parser for " .. filename)
|
||||
self.parsers[filename] = Parser(data.headings, data.argumentLists, data.argumentWrapper, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function DataManager:parse(parser, data)
|
||||
return self.parsers[parser]:parse(data)
|
||||
end
|
||||
|
||||
|
||||
return DataManager
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
local DebugSystem = Object:extend()
|
||||
|
||||
local lovebird
|
||||
local lovebird = require "birb.libs.lovebird"
|
||||
|
||||
local Levels = enum {
|
||||
"ERROR",
|
||||
|
@ -32,19 +32,18 @@ local Levels = enum {
|
|||
"DEBUG"
|
||||
}
|
||||
|
||||
function DebugSystem:new(controller, debugLevel)
|
||||
function DebugSystem:new(controller)
|
||||
self.controller = controller
|
||||
|
||||
self.debugLevel = debugLevel or Levels.WARNING
|
||||
self.debugLevel = self.controller.conf.debugLevel or Levels.INFO
|
||||
self.active = (self.debugLevel == Levels.DEBUG)
|
||||
if (self.active) then
|
||||
lovebird = require "birb.libs.lovebird"
|
||||
lovebird.update()
|
||||
end
|
||||
end
|
||||
|
||||
function DebugSystem:update(dt)
|
||||
if (self.active and lovebird ~= nil) then
|
||||
if (self.active) then
|
||||
lovebird.update(dt)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,23 +35,20 @@ local Screen = require(cwd .. "screen")
|
|||
local Lang = require(cwd .. "lang")
|
||||
local SceneManager = require(cwd .. "scenemanager")
|
||||
local MusicManager = require(cwd .. "music")
|
||||
local DataManager = require(cwd .. "datas")
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure the core object
|
||||
|
||||
function CoreSystem:new(args)
|
||||
self.args = args
|
||||
function CoreSystem:new()
|
||||
self:setDefaultConf()
|
||||
|
||||
self.debug = DebugSystem(self, self:getArg("DEBUGLEVEL", true))
|
||||
self.debug = DebugSystem(self)
|
||||
self.options = Options(self)
|
||||
self.input = Input(self)
|
||||
self.screen = Screen(self)
|
||||
self.scenemanager = SceneManager(self)
|
||||
self.lang = Lang(self)
|
||||
self.music = MusicManager(self)
|
||||
self.datas = DataManager(self)
|
||||
end
|
||||
|
||||
function CoreSystem:setDefaultConf()
|
||||
|
@ -78,19 +75,6 @@ function CoreSystem:getIdentity(versionned)
|
|||
return identity
|
||||
end
|
||||
|
||||
function CoreSystem:getArg(name, isNumber)
|
||||
for _, arg in ipairs(self.args) do
|
||||
local argData = utils.string.split(arg, "=")
|
||||
if (argData[1] == name) then
|
||||
if (isNumber == true) then
|
||||
return tonumber(argData[2])
|
||||
else
|
||||
return argData[2]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- MOUSE FUNCTIONS
|
||||
-- get directly the mouse when needed
|
||||
|
||||
|
@ -138,7 +122,6 @@ end
|
|||
-- Draw the whole game
|
||||
|
||||
function CoreSystem:draw()
|
||||
self.scenemanager:redraw()
|
||||
self.scenemanager:draw()
|
||||
end
|
||||
|
||||
|
|
|
@ -21,30 +21,26 @@
|
|||
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 Serializer = require "birb.classes.serializable.serializer"
|
||||
local OptionsManager = Serializer:extend()
|
||||
|
||||
local OptionsManager = Object:extend()
|
||||
|
||||
local binser = require("birb.libs.binser")
|
||||
|
||||
local TRANSLATION_PATH = "datas/languages/"
|
||||
|
||||
local OPTION_FILE = "options.data"
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure the game options
|
||||
|
||||
function OptionsManager:new(controller)
|
||||
OptionsManager.super.new(self, {"data"})
|
||||
|
||||
self.controller = controller
|
||||
-- We begin by creating an empty data table before reading the data.
|
||||
self:reset()
|
||||
self.data = {}
|
||||
self:read()
|
||||
end
|
||||
|
||||
function OptionsManager:reset()
|
||||
local conf = self.controller:getDefaultConf()
|
||||
-- Reset the option to the game defaults.
|
||||
self.data = {}
|
||||
|
||||
self.data.video = {}
|
||||
self.data.video.crtfilter = (conf.window.crtfilter == true)
|
||||
self.data.video.resolution = conf.window.resolution or 1
|
||||
|
@ -66,6 +62,20 @@ end
|
|||
-- INFO FUNCTIONS
|
||||
-- Get informations from the option managers
|
||||
|
||||
function OptionsManager:getFile(absolute)
|
||||
local dir = ""
|
||||
if absolute then
|
||||
dir = love.filesystem.getSaveDirectory() .. "/"
|
||||
if not utils.filesystem.exists(dir) then
|
||||
love.filesystem.createDirectory( "" )
|
||||
end
|
||||
end
|
||||
|
||||
local filepath = dir .. "options.data"
|
||||
|
||||
return filepath
|
||||
end
|
||||
|
||||
function OptionsManager:getInputDefaultData()
|
||||
local _path = "datas/inputs.lua"
|
||||
local datas = {}
|
||||
|
@ -132,11 +142,30 @@ end
|
|||
-- FIXME: maybe subclass a special module for that ?
|
||||
|
||||
function OptionsManager:write()
|
||||
self:serialize(OPTION_FILE)
|
||||
local data = self:getData()
|
||||
|
||||
local filepath = self:getFile(true)
|
||||
binser.writeFile(filepath, data)
|
||||
end
|
||||
|
||||
function OptionsManager:read()
|
||||
self:deserialize(OPTION_FILE)
|
||||
local filepath = self:getFile(true)
|
||||
if utils.filesystem.exists("options.data") then
|
||||
local loadedDatas = binser.readFile(filepath)
|
||||
self.controller.debug:print("core/options", "data file found, loading it")
|
||||
self:setData(loadedDatas[1])
|
||||
else
|
||||
self:reset()
|
||||
self.controller.debug:print("core/options", "no data file found, reseting data")
|
||||
end
|
||||
end
|
||||
|
||||
function OptionsManager:getData(data)
|
||||
return self.data
|
||||
end
|
||||
|
||||
function OptionsManager:setData(data)
|
||||
self.data = data
|
||||
end
|
||||
|
||||
return OptionsManager
|
||||
|
|
|
@ -78,7 +78,14 @@ function SceneManager:update(dt)
|
|||
end
|
||||
|
||||
if (self.currentScene ~= nil) then
|
||||
self.currentScene:updateScene(dt)
|
||||
self.currentScene:updateStart(dt)
|
||||
self.currentScene:setKeys()
|
||||
self.currentScene.assets:update(dt)
|
||||
self.currentScene:updateMenus(dt)
|
||||
self.currentScene:updateDialog(dt)
|
||||
self.currentScene:updateWorld(dt)
|
||||
self.currentScene:update(dt)
|
||||
self.currentScene:updateEnd(dt)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -90,12 +97,14 @@ function SceneManager:mousemoved(x, y, dx, dy)
|
|||
self.currentScene.mouse.x,
|
||||
self.currentScene.mouse.y = x, y
|
||||
self.currentScene:mousemoved(x, y, dx, dy)
|
||||
self.currentScene.menusystem:mousemoved(x, y, dx, dy)
|
||||
end
|
||||
end
|
||||
|
||||
function SceneManager:mousepressed( x, y, button, istouch )
|
||||
if (self.currentScene ~= nil) then
|
||||
self.currentScene:mousepressed( x, y, button, istouch )
|
||||
self.currentScene.menusystem:mousepressed( x, y, button, istouch )
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -120,13 +129,16 @@ end
|
|||
function SceneManager:draw()
|
||||
self.controller.screen:apply()
|
||||
if (self.currentScene ~= nil) then
|
||||
self.currentScene:drawScene()
|
||||
self.currentScene:drawStart()
|
||||
self.currentScene:drawWorld()
|
||||
self.currentScene:draw()
|
||||
self.currentScene:drawMenus()
|
||||
self.currentScene:drawDialog()
|
||||
self.currentScene:drawEnd()
|
||||
self.controller.screen:drawTransition()
|
||||
self.currentScene:drawOverTransition()
|
||||
end
|
||||
self.controller.screen:cease()
|
||||
end
|
||||
|
||||
function SceneManager:redraw()
|
||||
self.currentScene:redraw()
|
||||
end
|
||||
|
||||
return SceneManager
|
||||
|
|
|
@ -33,15 +33,15 @@ enum = require("birb.utils.enum")
|
|||
|
||||
birb.Core = require("birb.core")
|
||||
|
||||
function birb.start(gamemodule, args)
|
||||
birb.startCore(args)
|
||||
function birb.start(gamemodule)
|
||||
birb.startCore()
|
||||
if (gamemodule ~= nil) then
|
||||
birb.startGame(gamemodule)
|
||||
end
|
||||
end
|
||||
|
||||
function birb.startCore(args)
|
||||
core = birb.Core(args)
|
||||
function birb.startCore()
|
||||
core = birb.Core()
|
||||
end
|
||||
|
||||
function birb.startGame(gamemodule)
|
||||
|
|
|
@ -102,7 +102,7 @@ local Talkies = {
|
|||
titleBackgroundColor = nil,
|
||||
titleBorderColor = nil,
|
||||
messageColor = {1, 1, 1},
|
||||
messageBackgroundColor = {0, 0, 0, 0.8},
|
||||
messageBackgroundColor = {0, 0, 0, 0.5},
|
||||
messageBorderColor = nil,
|
||||
|
||||
rounding = 0,
|
||||
|
|
|
@ -35,7 +35,6 @@ function Animator:new(sprite)
|
|||
self.animationData = {}
|
||||
|
||||
self.customSpeed = 0
|
||||
self.speedFactor = 1
|
||||
|
||||
self:changeToDefaultAnimation()
|
||||
end
|
||||
|
@ -44,10 +43,6 @@ function Animator:setCustomSpeed(customSpeed)
|
|||
self.customSpeed = customSpeed or 0
|
||||
end
|
||||
|
||||
function Animator:setSpeedFactor(speedFactor)
|
||||
self.speedFactor = speedFactor or 1
|
||||
end
|
||||
|
||||
-- UPDATE FUNCTIONS
|
||||
-- Update the animation of the animator
|
||||
|
||||
|
@ -61,7 +56,7 @@ function Animator:update(dt)
|
|||
if (self.animationData.speed) == -1 then
|
||||
speed = self.customSpeed --math.abs(self.xsp / 16)
|
||||
end
|
||||
self.frameTimer = self.frameTimer + (speed * dt * self.speedFactor)
|
||||
self.frameTimer = self.frameTimer + (speed * dt)
|
||||
if self.frameTimer > 1 then
|
||||
self.frameTimer = 0
|
||||
if self.frame == self.animationData.endAt then
|
||||
|
@ -71,7 +66,6 @@ function Animator:update(dt)
|
|||
self:sendCallback()
|
||||
else
|
||||
self.frame = self.frame + 1
|
||||
self:sendFrameSignal()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -145,24 +139,6 @@ function Animator:sendCallback()
|
|||
end
|
||||
end
|
||||
|
||||
function Animator:sendFrameSignal()
|
||||
if (self.animationData.signal ~= nil) then
|
||||
if (type(self.animationData.signal[1]) ~= "table") then
|
||||
self:trySendSignal(self:getRelativeFrame(), self.animationData.signal)
|
||||
else
|
||||
for _, signal in ipairs(self.animationData.signal) do
|
||||
self:trySendSignal(self:getRelativeFrame(), signal)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Animator:trySendSignal(frame, signal)
|
||||
if (signal[1] == frame) and (self.actor ~= nil) and (self.actor.receiveFrameSignal ~= nil) then
|
||||
self.actor:receiveFrameSignal(signal[2])
|
||||
end
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Draw animations using these functions
|
||||
|
||||
|
|
|
@ -63,10 +63,6 @@ function Sprite:changeAnimation(name, restart)
|
|||
self.animator:changeAnimation(name, restart)
|
||||
end
|
||||
|
||||
function Sprite:setSpeedFactor(speedFactor)
|
||||
self.animator:setSpeedFactor(speedFactor)
|
||||
end
|
||||
|
||||
-- INFO FUNCTIONS
|
||||
-- get information with these functions
|
||||
|
||||
|
@ -97,11 +93,11 @@ end
|
|||
-- DRAW FUNCTIONS
|
||||
-- Draw sprites using these functions
|
||||
|
||||
function Sprite:draw(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
function Sprite:drawAnimation(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
self.animator:draw(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
end
|
||||
|
||||
function Sprite:drawMask(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
function Sprite:drawAnimationMask(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
self.animator:drawMask(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
end
|
||||
|
||||
|
@ -122,7 +118,7 @@ function Sprite:drawPart(x, y, w, h, r, sx, sy, ox, oy, kx, ky)
|
|||
end
|
||||
|
||||
love.graphics.setScissor(x - ox, y - oy, w, h)
|
||||
self:draw(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
self:drawAnimation(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
love.graphics.setScissor( )
|
||||
end
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.drawable"
|
||||
local AssetElement = Parent:extend()
|
||||
|
||||
function AssetElement:new(name, assetType, assetName, x, y,r,sx,sy,ox,oy, opacity)
|
||||
self:initWrapper()
|
||||
local asset = self.assets[assetType][assetName]
|
||||
assert(asset ~= nil, assetName .. ' (' .. assetType .. ") doesn't exist")
|
||||
|
||||
AssetElement.super.new(self, name, asset, x, y,r,sx,sy,ox,oy, opacity)
|
||||
end
|
||||
|
||||
function AssetElement:draw()
|
||||
self.drawable:draw(self.x,self.y,self.r,self.sx,self.sy,self.ox,self.oy)
|
||||
end
|
||||
|
||||
return AssetElement
|
|
@ -1,96 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.parent"
|
||||
local CanvasElement = Parent:extend()
|
||||
|
||||
function CanvasElement:new(name, x, y, w, h, r,sx,sy,ox,oy, opacity)
|
||||
self:initCanvas()
|
||||
CanvasElement.super.new(self, name, x, y, w, h)
|
||||
self.r = r or 0
|
||||
self.sx, self.sy = sx or 1, sy or 1
|
||||
self.ox, self.oy = self:parseOrigin(ox, w), self:parseOrigin(oy, h)
|
||||
self.opacity = opacity or 1
|
||||
end
|
||||
|
||||
function CanvasElement:initCanvas()
|
||||
self.canvas = {}
|
||||
self.canvas.needRedraw = true
|
||||
self.canvas.texture = nil
|
||||
self.canvas.isAnimated = false
|
||||
self.canvas.padding = 8
|
||||
self.canvas.final = nil
|
||||
self.canvas.dual = false
|
||||
end
|
||||
|
||||
function CanvasElement:updateElement(dt)
|
||||
CanvasElement.super.updateElement(self, dt)
|
||||
end
|
||||
|
||||
function CanvasElement:getCanvasDimensions()
|
||||
return self:getDimensions()
|
||||
end
|
||||
|
||||
function CanvasElement:redraw()
|
||||
if (self.canvas.needRedraw or self.canvas.isAnimated) then
|
||||
self:generateTexture()
|
||||
end
|
||||
|
||||
if (self.canvas.dual) then
|
||||
local w, h = self:getDimensions()
|
||||
local canvas = love.graphics.newCanvas(w + (self.canvas.padding*2), h + (self.canvas.padding*2))
|
||||
love.graphics.setCanvas(canvas)
|
||||
|
||||
love.graphics.draw(self.canvas.texture, 0, 0)
|
||||
self:drawFinalTexture()
|
||||
|
||||
self.canvas.final = canvas
|
||||
love.graphics.setCanvas()
|
||||
end
|
||||
end
|
||||
|
||||
function CanvasElement:generateTexture()
|
||||
local w, h = self:getDimensions()
|
||||
|
||||
local canvas = love.graphics.newCanvas(w + (self.canvas.padding*2), h + (self.canvas.padding*2))
|
||||
love.graphics.setCanvas(canvas)
|
||||
|
||||
self:drawTexture()
|
||||
self.canvas.needRedraw = false
|
||||
love.graphics.setCanvas()
|
||||
if (self.canvas.isAnimated) then
|
||||
self.canvas.texture = canvas
|
||||
else
|
||||
local imageData = canvas:newImageData()
|
||||
self.canvas.texture = love.graphics.newImage(imageData)
|
||||
canvas:release()
|
||||
imageData:release()
|
||||
end
|
||||
end
|
||||
|
||||
function CanvasElement:drawTexture()
|
||||
|
||||
end
|
||||
|
||||
function CanvasElement:drawFinalTexture()
|
||||
|
||||
end
|
||||
|
||||
function CanvasElement:parseOrigin(origin, size)
|
||||
if (origin == "center") then
|
||||
return size/2
|
||||
elseif (origin == "end") then
|
||||
return size
|
||||
else
|
||||
return origin or 0
|
||||
end
|
||||
end
|
||||
|
||||
function CanvasElement:draw()
|
||||
love.graphics.setColor(1, 1, 1, self.opacity)
|
||||
local texture = self.canvas.texture
|
||||
if (self.canvas.dual) then
|
||||
texture = self.canvas.final
|
||||
end
|
||||
love.graphics.draw(texture, self.x - self.canvas.padding,self.y - self.canvas.padding,self.r,self.sx,self.sy,self.ox,self.oy)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
return CanvasElement
|
|
@ -1,19 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.parent"
|
||||
local ColorElement = Parent:extend()
|
||||
|
||||
function ColorElement:new(name, r, g, b, opacity)
|
||||
local w, h = core.screen:getDimensions()
|
||||
ColorElement.super.new(self, name, self.x, self.y, w, h)
|
||||
self.r = r or 1
|
||||
self.g = g or 1
|
||||
self.b = b or 1
|
||||
self.opacity = opacity or 1
|
||||
end
|
||||
|
||||
function ColorElement:draw()
|
||||
love.graphics.setColor(self.r, self.g, self.b, self.opacity)
|
||||
love.graphics.rectangle("fill", 0, 0, self.w, self.h)
|
||||
utils.graphics.resetColor()
|
||||
end
|
||||
|
||||
return ColorElement
|
|
@ -1,35 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.parent"
|
||||
local CompositeElement = Parent:extend()
|
||||
|
||||
function CompositeElement:new(name, x, y, childrenList)
|
||||
self.children = {}
|
||||
self:addChildren(childrenList)
|
||||
CompositeElement.super.new(self, name, x, y, 1, 1)
|
||||
self.isVisible = true
|
||||
end
|
||||
|
||||
function CompositeElement:addChildren(list)
|
||||
for _, childData in ipairs(list) do
|
||||
self:addChild(childData[1], childData[2], childData[3])
|
||||
end
|
||||
end
|
||||
|
||||
function CompositeElement:addChild(children, relx, rely)
|
||||
local child = {}
|
||||
child.name = children.name
|
||||
child.relx = relx
|
||||
child.rely = rely
|
||||
table.insert(self.children, child)
|
||||
end
|
||||
|
||||
function CompositeElement:update(dt)
|
||||
for _, child in ipairs(self.children) do
|
||||
local childElement = self.gui.elements[child.name]
|
||||
childElement.x = self.x + child.relx
|
||||
childElement.y = self.y + child.rely
|
||||
childElement.isVisible = self.isVisible
|
||||
childElement.depth = self.depth
|
||||
end
|
||||
end
|
||||
|
||||
return CompositeElement
|
|
@ -1,13 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.variable"
|
||||
local CounterElement = Parent:extend()
|
||||
|
||||
function CounterElement:new(name, fontName, object, varName, nbrs, x, y, align)
|
||||
CounterElement.super.new(self, name, fontName, object, varName, x, y, align)
|
||||
self.nbrs = nbrs or 0
|
||||
end
|
||||
|
||||
function CounterElement:getText()
|
||||
return utils.math.numberToString(CounterElement.super.getText(self), self.nbrs)
|
||||
end
|
||||
|
||||
return CounterElement
|
|
@ -1,31 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.parent"
|
||||
local DrawableElement = Parent:extend()
|
||||
|
||||
function DrawableElement:new(name, drawable, x, y,r,sx,sy,ox,oy, opacity)
|
||||
self.drawable = drawable
|
||||
|
||||
local w, h = self.drawable:getDimensions()
|
||||
DrawableElement.super.new(self, name, x, y, w, h)
|
||||
self.r = r or 0
|
||||
self.sx, self.sy = sx or 1, sy or 1
|
||||
self.ox, self.oy = self:parseOrigin(ox, w), self:parseOrigin(oy, h)
|
||||
self.opacity = opacity or 1
|
||||
end
|
||||
|
||||
function DrawableElement:parseOrigin(origin, size)
|
||||
if (origin == "center") then
|
||||
return size/2
|
||||
elseif (origin == "end") then
|
||||
return size
|
||||
else
|
||||
return origin or 0
|
||||
end
|
||||
end
|
||||
|
||||
function DrawableElement:draw()
|
||||
love.graphics.setColor(1, 1, 1, self.opacity)
|
||||
love.graphics.draw(self.drawable, self.x,self.y,self.r,self.sx,self.sy,self.ox,self.oy)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
return DrawableElement
|
|
@ -1,157 +0,0 @@
|
|||
local Rect = require "birb.classes.2D.rect"
|
||||
local GuiElement = Rect:extend()
|
||||
|
||||
local TweenManager = require "birb.classes.time"
|
||||
|
||||
function GuiElement:new(name, x, y, w, h)
|
||||
GuiElement.super.new(self, x, y, w, h)
|
||||
self.name = name
|
||||
|
||||
self.isVisible = true
|
||||
self.screen = nil
|
||||
|
||||
self.depth = 10
|
||||
|
||||
self.tweens = TweenManager(self)
|
||||
self:initWrapper()
|
||||
|
||||
self:register()
|
||||
end
|
||||
|
||||
function GuiElement:initWrapper()
|
||||
self.scene = core.scenemanager.nextScene or core.scenemanager.currentScene
|
||||
self.gui = self.scene.gui
|
||||
self.assets = self.scene.assets
|
||||
end
|
||||
|
||||
function GuiElement:setKeyPressAction(func)
|
||||
self.func = func
|
||||
end
|
||||
|
||||
function GuiElement:register()
|
||||
self.creationId = self.gui:addElement(self.name, self)
|
||||
end
|
||||
|
||||
function GuiElement:destroy()
|
||||
self.gui:deleteElement(self.name)
|
||||
if (self.screen ~= nil) then
|
||||
self.screen:deleteElement(self.name)
|
||||
end
|
||||
end
|
||||
|
||||
-- VISIBILITY/ACTIVITY
|
||||
-- Handle drawing and how we interact with
|
||||
|
||||
function GuiElement:setDepth(depth)
|
||||
self.depth = depth or 0
|
||||
end
|
||||
|
||||
function GuiElement:getVisibility()
|
||||
if (self.screen ~= nil) then
|
||||
return (self.isVisible and self.screen.isVisible)
|
||||
else
|
||||
return self.isVisible
|
||||
end
|
||||
end
|
||||
|
||||
function GuiElement:setVisibility(visibility)
|
||||
self.isVisible = visibility
|
||||
end
|
||||
|
||||
function GuiElement:getFocus(widgetId, page)
|
||||
self.gui:setFocus(self.name, widgetId, page)
|
||||
end
|
||||
|
||||
function GuiElement:haveFocus()
|
||||
return (self.gui.focusedElement == self.name)
|
||||
end
|
||||
|
||||
function GuiElement:looseFocus()
|
||||
if (self:haveFocus()) then
|
||||
self.gui:removeFocus()
|
||||
end
|
||||
end
|
||||
|
||||
function GuiElement:setSubFocus()
|
||||
-- Useless for basic element
|
||||
end
|
||||
|
||||
function GuiElement:isTransforming()
|
||||
return self.tweens:haveTween()
|
||||
end
|
||||
|
||||
-- UPDATE FUNCTIONS
|
||||
-- Update the menu every game update
|
||||
|
||||
-- External update function
|
||||
function GuiElement:updateElement(dt)
|
||||
self:update(dt)
|
||||
self.tweens:update(dt)
|
||||
end
|
||||
|
||||
-- Internal update function
|
||||
function GuiElement:update(dt)
|
||||
-- Cette fonction ne contient rien par défaut
|
||||
end
|
||||
|
||||
-- TWEEN FUNCTIONS
|
||||
-- Handle tweening
|
||||
|
||||
function GuiElement:newTween(start, duration, target, easing)
|
||||
self.tweens:newTween(start, duration, target, easing)
|
||||
end
|
||||
|
||||
function GuiElement:newMovement(start, duration, x, y, easing)
|
||||
self:newTween(start, duration, {x = x, y = y}, easing)
|
||||
end
|
||||
|
||||
function GuiElement:newSwitch(start, bools)
|
||||
self.tweens:newSwitch(start, bools)
|
||||
end
|
||||
|
||||
function GuiElement:newFunc(start, name, func)
|
||||
self.tweens:newFunc(start, name, func)
|
||||
end
|
||||
|
||||
function GuiElement:delayFocus(start)
|
||||
self.tweens:newFunc(start, "focus", function ()
|
||||
self:getFocus()
|
||||
end)
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Draw the menu and its content
|
||||
|
||||
function GuiElement:redraw()
|
||||
|
||||
end
|
||||
|
||||
function GuiElement:drawElement()
|
||||
self:draw()
|
||||
end
|
||||
|
||||
function GuiElement:draw()
|
||||
-- nothing here
|
||||
end
|
||||
|
||||
-- KEYBOARD FUNCTIONS
|
||||
-- Handle key press
|
||||
|
||||
function GuiElement:keypressed(key)
|
||||
if (self.func ~= nil) then
|
||||
self.func(key)
|
||||
end
|
||||
end
|
||||
|
||||
-- MOUSE FUNCTIONS
|
||||
-- Handle pointers (clic/touch)
|
||||
|
||||
function GuiElement:mousemoved(x, y)
|
||||
-- Cette fonction ne contient rien par défaut
|
||||
end
|
||||
|
||||
function GuiElement:mousepressed(x, y, button, istouch)
|
||||
-- Cette fonction ne contient rien par défaut
|
||||
end
|
||||
|
||||
return GuiElement
|
|
@ -1,23 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.parent"
|
||||
local TextElement = Parent:extend()
|
||||
|
||||
function TextElement:new(name, fontName, text, x, y, align)
|
||||
TextElement.super.new(self, name, x, y, 1, 1)
|
||||
self.text = text
|
||||
self.font = self.assets.fonts[fontName]
|
||||
|
||||
self.align = align
|
||||
self.opacity = 1
|
||||
end
|
||||
|
||||
function TextElement:getText()
|
||||
return self.text
|
||||
end
|
||||
|
||||
function TextElement:draw()
|
||||
self.font:setColor(1, 1, 1, self.opacity)
|
||||
self.font:draw(self:getText(), self.x, self.y, -1, self.align)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
return TextElement
|
|
@ -1,19 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.drawable"
|
||||
local TileElement = Parent:extend()
|
||||
|
||||
function TileElement:new(name, assetName, id, x, y,r,sx,sy,ox,oy, opacity)
|
||||
self:initWrapper()
|
||||
local asset = self.assets.tileset[assetName]
|
||||
assert(asset ~= nil, assetName .. " ( tileset ) doesn't exist")
|
||||
self.tileId = id
|
||||
|
||||
TileElement.super.new(self, name, asset, x, y,r,sx,sy,ox,oy, opacity)
|
||||
end
|
||||
|
||||
function TileElement:draw()
|
||||
love.graphics.setColor(1, 1, 1, self.opacity)
|
||||
self.drawable:drawTile(self.tileId, self.x,self.y,self.r,self.sx,self.sy,self.ox,self.oy)
|
||||
utils.graphics.resetColor()
|
||||
end
|
||||
|
||||
return TileElement
|
|
@ -1,14 +0,0 @@
|
|||
local Parent = require "birb.modules.gui.elements.text"
|
||||
local VariableElement = Parent:extend()
|
||||
|
||||
function VariableElement:new(name, fontName, object, varName, x, y, align)
|
||||
VariableElement.super.new(self, name, fontName, "", x, y, align)
|
||||
self.object = object
|
||||
self.variable = varName
|
||||
end
|
||||
|
||||
function VariableElement:getText()
|
||||
return self.object[self.variable]
|
||||
end
|
||||
|
||||
return VariableElement
|
|
@ -1,187 +0,0 @@
|
|||
-- modules/gui :: a simple gui system, that manage all overhead elements of the game.
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 Gui = Object:extend()
|
||||
|
||||
local ElementList = require "birb.modules.gui.mixins.elements"
|
||||
local ScreenList = require "birb.modules.gui.mixins.screens"
|
||||
Gui:implement(ScreenList)
|
||||
Gui:implement(ElementList)
|
||||
|
||||
local TransformDataStruct = require "birb.structures.tween"
|
||||
|
||||
function Gui:new(scene)
|
||||
self.scene = scene
|
||||
self:reset()
|
||||
self.sfx = {}
|
||||
end
|
||||
|
||||
function Gui:reset()
|
||||
self:initElements()
|
||||
self:initScreens()
|
||||
end
|
||||
|
||||
function Gui:update(dt)
|
||||
for _, element in pairs(self.elements) do
|
||||
if (element ~= nil) then
|
||||
element:updateElement(dt)
|
||||
end
|
||||
end
|
||||
for _, screen in pairs(self.screens) do
|
||||
if (screen ~= nil) then
|
||||
screen:update(dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TWEEN FUNCTIONS
|
||||
-- Handle tweening
|
||||
|
||||
function Gui:transform(data, delay)
|
||||
delay = delay or 0
|
||||
|
||||
local time = 0
|
||||
for _, rawTransform in ipairs(data) do
|
||||
local newTime = self:transformOne(rawTransform, delay)
|
||||
time = math.max(time, newTime)
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
function Gui:playScreenTransform(screenname, name, delay)
|
||||
return self.screens[screenname]:playTransform(name, delay)
|
||||
end
|
||||
|
||||
function Gui:transformOne(rawTransform, delay)
|
||||
delay = delay or 0
|
||||
|
||||
local struct = TransformDataStruct[rawTransform[2]]
|
||||
assert(struct ~= nil, "Structure " .. rawTransform[1] .. " doesn't exists ")
|
||||
local transform = utils.table.parse(rawTransform, struct, 0)
|
||||
|
||||
local time = transform.start + delay
|
||||
|
||||
if transform.type == "tween" then
|
||||
self:newTween(transform.name, time, transform.duration, transform.target, transform.easing)
|
||||
elseif transform.type == "movement" then
|
||||
self:newMovement(transform.name, time, transform.duration, transform.x, transform.y, transform.easing)
|
||||
elseif transform.type == "switch" then
|
||||
self:newSwitch(transform.name, time, transform.bools)
|
||||
elseif transform.type == "delayFocus" then
|
||||
self:delayFocus(transform.name, time)
|
||||
end
|
||||
|
||||
if (transform.duration ~= nil) then
|
||||
time = time + transform.duration
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
function Gui:newTween(element, start, duration, target, easing)
|
||||
assert(self.elements[element] ~= nil, element .. " does not exists")
|
||||
self.elements[element]:newTween(start, duration, target, easing)
|
||||
end
|
||||
|
||||
function Gui:newMovement(element, start, duration, x, y, easing)
|
||||
assert(self.elements[element] ~= nil, element .. " does not exists")
|
||||
self.elements[element]:newMovement(start, duration, x, y, easing)
|
||||
end
|
||||
|
||||
function Gui:newSwitch(element, start, bools)
|
||||
assert(self.elements[element] ~= nil, element .. " does not exists")
|
||||
self.elements[element]:newSwitch(start, bools)
|
||||
end
|
||||
|
||||
function Gui:delayFocus(element, start)
|
||||
assert(self.elements[element] ~= nil, element .. " does not exists")
|
||||
self.elements[element]:delayFocus(start)
|
||||
end
|
||||
|
||||
function Gui:hideScreen(screenname)
|
||||
self.screens[screenname]:hide()
|
||||
end
|
||||
|
||||
|
||||
function Gui:showScreen(screenname, focusElement, widgetId, page, arbitraryDatas)
|
||||
self.screens[screenname]:show(focusElement, widgetId, page)
|
||||
self.screens[screenname]:setDatas(arbitraryDatas)
|
||||
end
|
||||
|
||||
-- SOUND FUNCTIONS
|
||||
-- Handle SFX
|
||||
|
||||
function Gui:addSFX(guiName, sfxName)
|
||||
self.sfx[guiName] = sfxName
|
||||
end
|
||||
|
||||
function Gui:playSFX(type)
|
||||
local sfxName = self.sfx[type]
|
||||
if (sfxName ~= nil) then
|
||||
local sfx = self.scene.assets.sfx[sfxName]
|
||||
if (sfx ~= nil) then
|
||||
sfx:play()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- KEYBOARD FUNCTIONS
|
||||
-- Handle keyboard
|
||||
|
||||
function Gui:keycheck(keys)
|
||||
local haveFocus = self:haveFocus()
|
||||
if (haveFocus) then
|
||||
local elem = self:getFocusedElement()
|
||||
for key,_ in pairs(keys) do
|
||||
if (keys[key].isPressed and not elem:isTransforming()) then
|
||||
elem:keypressed(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
return haveFocus
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Draw the menu and its content
|
||||
|
||||
function Gui:redraw()
|
||||
for _, element in pairs(self:getVisibleElement(true)) do
|
||||
element:redraw()
|
||||
end
|
||||
for _, element in pairs(self:getVisibleElement(false)) do
|
||||
element:redraw()
|
||||
end
|
||||
end
|
||||
|
||||
function Gui:drawTop()
|
||||
for _, element in ipairs(self:getVisibleElement(true)) do
|
||||
element:drawElement()
|
||||
end
|
||||
end
|
||||
|
||||
function Gui:drawBottom()
|
||||
for _, element in ipairs(self:getVisibleElement(false)) do
|
||||
element:drawElement()
|
||||
end
|
||||
end
|
||||
|
||||
return Gui
|
|
@ -1,148 +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 View2D = require(cwd .. "views.view2D")
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure the flowbox
|
||||
|
||||
function FlowBox:new(name, x, y, w, h, slots_hor, slots_vert)
|
||||
self.view = View2D(slots_hor, slots_vert)
|
||||
FlowBox.super.new(self, 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)
|
||||
self:playNavigationSound()
|
||||
end
|
||||
|
||||
if key == 'right' then
|
||||
self:moveCursor2D(col + 1, line)
|
||||
self:playNavigationSound()
|
||||
end
|
||||
|
||||
if key == 'up' then
|
||||
self:moveCursor2D(col, line - 1)
|
||||
self:playNavigationSound()
|
||||
end
|
||||
|
||||
if key == 'down' then
|
||||
self:moveCursor2D(col, line + 1)
|
||||
self:playNavigationSound()
|
||||
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:drawTexture()
|
||||
self.view:updateFirstSlot(self.widget:getSelected())
|
||||
local widgety = self.canvas.padding
|
||||
local widgetx = self.canvas.padding
|
||||
|
||||
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 x, y, w, h
|
||||
end
|
||||
|
||||
return FlowBox
|
|
@ -1,105 +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 View1D = require(cwd .. "views.view1D")
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure functions.
|
||||
|
||||
function HListBox:new(name, x, y, w, h, slotNumber)
|
||||
self.view = View1D(slotNumber)
|
||||
HListBox.super.new(self, 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)
|
||||
self.canvas.needRedraw = true
|
||||
self:playNavigationSound()
|
||||
end
|
||||
|
||||
if key == 'right' then
|
||||
self.widget:moveCursor(1)
|
||||
self.canvas.needRedraw = true
|
||||
self:playNavigationSound()
|
||||
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:drawTexture()
|
||||
self.view:updateFirstSlot(self.widget:getSelected())
|
||||
|
||||
local widgetx = self.canvas.padding
|
||||
|
||||
local listWidget = self.widget:getList(self.view.firstSlot, self.view.slotNumber)
|
||||
|
||||
for _, widget in ipairs(listWidget) do
|
||||
widget:drawWidget(widgetx, self.canvas.padding, 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 x, 0, w, h
|
||||
end
|
||||
|
||||
return HListBox
|
|
@ -1,116 +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 View1D = require(cwd .. "views.view1D")
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure functions.
|
||||
|
||||
function ListBox:new(name, x, y, w, h, slotNumber)
|
||||
self.view = View1D(slotNumber)
|
||||
ListBox.super.new(self, 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
|
||||
self.lateralFunc = nil
|
||||
self.packAtEnd = false
|
||||
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
|
||||
|
||||
function ListBox:addLateralAction(func)
|
||||
self.lateralFunc = func
|
||||
end
|
||||
|
||||
-- KEYBOARD FUNCTIONS
|
||||
-- Handle input from keyboard/controllers.
|
||||
|
||||
function ListBox:moveByKeys(key)
|
||||
if key == 'up' then
|
||||
self.widget:moveCursor(-1)
|
||||
self:playNavigationSound()
|
||||
self.canvas.needRedraw = true
|
||||
end
|
||||
|
||||
if key == 'down' then
|
||||
self.widget:moveCursor(1)
|
||||
self:playNavigationSound()
|
||||
self.canvas.needRedraw = true
|
||||
end
|
||||
|
||||
if (self.lateralFunc ~= nil and (key == 'left' or key == 'right')) then
|
||||
self.widget:lateralAction(self.lateralFunc, key)
|
||||
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:getListPart(relativeNumber)
|
||||
if (self.packAtEnd) then relativeNumber = relativeNumber + math.max(0, self.view.slotNumber - self.widget:lenght()) end
|
||||
return 0, (relativeNumber) * self.widgetSize.h, self.w, self.widgetSize.h
|
||||
end
|
||||
|
||||
function ListBox:drawTexture()
|
||||
self.view:updateFirstSlot(self.widget:getSelected())
|
||||
local listWidget = self.widget:getList(self.view.firstSlot, self.view.slotNumber)
|
||||
|
||||
for i, widget in ipairs(listWidget) do
|
||||
local x, y, w, h = self:getListPart(i - 1)
|
||||
self:drawWidgetBackground(x + self.canvas.padding, y + self.canvas.padding, w, h)
|
||||
widget:drawWidget(x + self.canvas.padding, y + self.canvas.padding, w, h)
|
||||
end
|
||||
end
|
||||
|
||||
function ListBox:getGraphicalCursorPosition()
|
||||
local x, y, w, h = self:getListPart(self.widget:getSelected() - self.view.firstSlot)
|
||||
|
||||
return self:getListPart(self.widget:getSelected() - self.view.firstSlot)
|
||||
end
|
||||
|
||||
return ListBox
|
|
@ -1,227 +0,0 @@
|
|||
local MenuModel = Object:extend()
|
||||
local Page = require "birb.modules.gui.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()
|
||||
self.hoverFunc = nil
|
||||
end
|
||||
|
||||
function MenuModel:clear()
|
||||
self.pages = {}
|
||||
self:addPage("main")
|
||||
end
|
||||
|
||||
-- PAGE FUNCTIONS
|
||||
-- Handle pages
|
||||
|
||||
function MenuModel:addPage(pageName)
|
||||
local page = Page()
|
||||
page.name = pageName
|
||||
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
|
||||
self:hoverAction()
|
||||
end
|
||||
end
|
||||
|
||||
function MenuModel:back()
|
||||
local page = self:getCurrentPage()
|
||||
self:switch(page:getParent())
|
||||
end
|
||||
|
||||
function MenuModel:getCurrentPage()
|
||||
return self:getPage(self.currentPage)
|
||||
end
|
||||
|
||||
function MenuModel:getCurrentPageName()
|
||||
return 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:addHoverAction(func)
|
||||
self.hoverFunc = func
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
function MenuModel:hoverAction()
|
||||
local page = self:getCurrentPage()
|
||||
if (self.hoverFunc ~= nil) then
|
||||
page:hoverAction(self.hoverFunc)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuModel:lateralAction(func, key)
|
||||
local page = self:getCurrentPage()
|
||||
page:lateralAction(func, key)
|
||||
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(id)
|
||||
local page = self:getCurrentPage()
|
||||
page:setCancelWidget(id)
|
||||
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()
|
||||
local isSuccess = page:trySelectWidget(cursorid)
|
||||
if (isSuccess) then
|
||||
self:hoverAction()
|
||||
end
|
||||
return isSuccess
|
||||
end
|
||||
|
||||
function MenuModel:setCursor(cursorid)
|
||||
local page = self:getCurrentPage()
|
||||
page:setCursor(cursorid)
|
||||
self:hoverAction()
|
||||
end
|
||||
|
||||
function MenuModel:moveCursorAbsolute(newSelected)
|
||||
local page = self:getCurrentPage()
|
||||
page:moveCursorAbsolute(newSelected)
|
||||
self:hoverAction()
|
||||
end
|
||||
|
||||
function MenuModel:moveCursor(relative)
|
||||
local page = self:getCurrentPage()
|
||||
page:moveCursor(relative)
|
||||
self:hoverAction()
|
||||
end
|
||||
|
||||
-- DRAW
|
||||
-- Draw widget
|
||||
function MenuModel:redraw()
|
||||
local page = self:getCurrentPage()
|
||||
page:redraw()
|
||||
end
|
||||
|
||||
|
||||
return MenuModel
|
|
@ -1,211 +0,0 @@
|
|||
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:getCancelWidget() ~= 0) then
|
||||
self:action(self:getCancelWidget(), "key")
|
||||
end
|
||||
end
|
||||
|
||||
function Page:action(id, type)
|
||||
if (self:widgetExist(id)) then
|
||||
self.widgets[id]:action(type)
|
||||
self.widgets[id]:playSFX()
|
||||
end
|
||||
end
|
||||
|
||||
function Page:selectedAction()
|
||||
if (self.selected ~= 0) then
|
||||
self:action(self.selected, "key")
|
||||
end
|
||||
end
|
||||
|
||||
function Page:hoverAction(func)
|
||||
if (self:widgetExist(self.selected)) then
|
||||
func(self.widgets[self.selected])
|
||||
end
|
||||
end
|
||||
|
||||
function Page:lateralAction(func, key)
|
||||
if (self:widgetExist(self.selected)) then
|
||||
func(key, self.widgets[self.selected], self.selected, self.name)
|
||||
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)
|
||||
if (id == nil) then
|
||||
id = #self.widgets
|
||||
end
|
||||
self.cancel = id
|
||||
end
|
||||
|
||||
function Page:getCancelWidget()
|
||||
if (self.cancel == "last") then
|
||||
return #self.widgets
|
||||
else
|
||||
return self.cancel
|
||||
end
|
||||
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
|
||||
|
||||
-- DRAW
|
||||
function Page:redraw()
|
||||
for _, widget in ipairs(self.widgets) do
|
||||
widget:redraw()
|
||||
end
|
||||
end
|
||||
|
||||
return Page
|
|
@ -1,278 +0,0 @@
|
|||
-- 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.gui.elements.canvas"
|
||||
|
||||
local Menu = GuiElement:extend()
|
||||
local MenuModel = require "birb.modules.gui.menus.model"
|
||||
|
||||
local menuUtils = require "birb.modules.gui.utils"
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure functions.
|
||||
|
||||
function Menu:new(name, x, y, w, h)
|
||||
Menu.super.new(self, name, x, y, w, h)
|
||||
|
||||
--TODO: remove this
|
||||
self.menusystem = self.gui
|
||||
|
||||
self.widget = MenuModel()
|
||||
self.widgetSize = {}
|
||||
self:updateWidgetSize()
|
||||
|
||||
self:initCanvas()
|
||||
self.cancelFunc = nil
|
||||
self.canvas.dual = true
|
||||
end
|
||||
|
||||
-- FUNCTIONS FUNCTIONS
|
||||
-- Add functions to the menu system
|
||||
|
||||
function Menu:addCancelAction(func)
|
||||
self.cancelFunc = func
|
||||
end
|
||||
|
||||
function Menu:addHoverAction(func)
|
||||
self.widget:addHoverAction(func)
|
||||
end
|
||||
|
||||
-- INTERACTION FUNCTIONS
|
||||
-- Keyboard and mouse
|
||||
|
||||
function Menu:keypressed(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()
|
||||
self.canvas.needRedraw = true
|
||||
end
|
||||
|
||||
if key == "B" then
|
||||
self:cancelAction()
|
||||
self.canvas.needRedraw = true
|
||||
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:getCurrentPageName()
|
||||
return self.widget:getCurrentPageName()
|
||||
end
|
||||
|
||||
function Menu:switch(pageName)
|
||||
self.widget:switch(pageName)
|
||||
self:resetView()
|
||||
self.canvas.needRedraw = true
|
||||
end
|
||||
|
||||
function Menu:back()
|
||||
self.widget:back()
|
||||
self:resetView()
|
||||
self.canvas.needRedraw = true
|
||||
end
|
||||
|
||||
function GuiElement:setSubFocus(widgetId, pageName)
|
||||
if (pageName ~= nil) then
|
||||
self.widget:switch(pageName)
|
||||
end
|
||||
self.widget:trySelectWidget(widgetId)
|
||||
end
|
||||
|
||||
-- ACTION FUNCTIONS
|
||||
-- Send actions to the widgets
|
||||
|
||||
function Menu:cancelAction()
|
||||
if (self.cancelFunc ~= nil) then
|
||||
self.cancelFunc(self)
|
||||
else
|
||||
self.widget:cancelAction()
|
||||
end
|
||||
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.widget:update(dt)
|
||||
Menu.super.updateElement(self, dt)
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Draw the menu and its content
|
||||
|
||||
function Menu:drawElement()
|
||||
self:draw()
|
||||
end
|
||||
|
||||
function Menu:drawFinalTexture()
|
||||
if (self:haveFocus()) then
|
||||
local x, y, w, h = self:getGraphicalCursorPosition()
|
||||
self:drawGraphicalCursor(self.canvas.padding + x, self.canvas.padding + y, w, h)
|
||||
end
|
||||
end
|
||||
|
||||
function Menu:drawGraphicalCursor(x, y, w, h)
|
||||
menuUtils.drawCursor(x, y, w, h)
|
||||
end
|
||||
|
||||
function Menu:drawCanvas()
|
||||
|
||||
end
|
||||
|
||||
function Menu:drawWidgetBackground(x, y, w, h)
|
||||
|
||||
end
|
||||
|
||||
function Menu:redraw()
|
||||
self.widget:redraw()
|
||||
Menu.super.redraw(self)
|
||||
end
|
||||
|
||||
-- WIDGET FUNCTIONS
|
||||
-- Handle widgets of the functions
|
||||
|
||||
function Menu:addWidget(newwidget)
|
||||
self.widget:addWidget(newwidget)
|
||||
self.canvas.needRedraw = true
|
||||
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)
|
||||
self.canvas.needRedraw = true
|
||||
end
|
||||
|
||||
function Menu:moveCursor(new_selected)
|
||||
self.widget:moveCursorAbsolute(new_selected)
|
||||
self.canvas.needRedraw = true
|
||||
end
|
||||
|
||||
-- SOUND FUNCTION
|
||||
-- Handle SFX
|
||||
|
||||
function Menu:playNavigationSound()
|
||||
self:playSFX("navigate")
|
||||
end
|
||||
|
||||
function Menu:playSFX(name)
|
||||
self.gui:playSFX(name)
|
||||
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
|
|
@ -1,48 +0,0 @@
|
|||
-- 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
|
||||
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
|
|
@ -1,61 +0,0 @@
|
|||
-- 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.gui.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
|
|
@ -1,171 +0,0 @@
|
|||
-- 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:initWrapper()
|
||||
self.menu = self:getMenuByName(menuName)
|
||||
|
||||
self.destroyed = false
|
||||
self.selectable = false
|
||||
self.selection_margin = 0
|
||||
self.margin = 2
|
||||
|
||||
self.canvas = {}
|
||||
self.canvas.texture = nil
|
||||
self.canvas.needRedraw = true
|
||||
self.canvas.isAnimated = false
|
||||
|
||||
self.order = 0
|
||||
self:register()
|
||||
self.func = nil
|
||||
self.type = "select"
|
||||
end
|
||||
|
||||
function BaseWidget:initWrapper()
|
||||
self.scene = core.scenemanager.nextScene or core.scenemanager.currentScene
|
||||
self.gui = self.scene.gui
|
||||
self.assets = self.scene.assets
|
||||
end
|
||||
|
||||
function BaseWidget:setFunc(func)
|
||||
self.func = func
|
||||
end
|
||||
|
||||
function BaseWidget:getMenuByName(name)
|
||||
assert(name ~= nil, "Name cant be nil")
|
||||
return self.gui.elements[name]
|
||||
end
|
||||
|
||||
function BaseWidget:getScene()
|
||||
return core.scenemanager.nextScene or core.scenemanager.currentScene
|
||||
end
|
||||
|
||||
function BaseWidget:getAssets()
|
||||
local scene = core.scenemanager.nextScene or core.scenemanager.currentScene
|
||||
return scene.assets
|
||||
end
|
||||
|
||||
function BaseWidget:register()
|
||||
self.creationID = self.menu:getWidgetNumber()
|
||||
self.menu:addWidget(self)
|
||||
end
|
||||
|
||||
function BaseWidget:redraw()
|
||||
if (self.canvas.needRedraw or self.canvas.isAnimated) then
|
||||
self:generateTexture()
|
||||
end
|
||||
end
|
||||
|
||||
function BaseWidget:generateTexture()
|
||||
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)
|
||||
-- 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:playSFX()
|
||||
self.menu:playSFX(self.type)
|
||||
end
|
||||
|
||||
function BaseWidget:action(source)
|
||||
if (self.func ~= nil) then
|
||||
self.func(self)
|
||||
end
|
||||
end
|
||||
|
||||
function BaseWidget:destroy()
|
||||
self.destroyed = true
|
||||
end
|
||||
|
||||
return BaseWidget
|
|
@ -1,30 +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 = {}
|
||||
|
||||
-- Add the widget as subvariable to the returned table
|
||||
Widget.Base = require "birb.modules.gui.menus.widgets.base"
|
||||
Widget.Text = require "birb.modules.gui.menus.widgets.text"
|
||||
|
||||
return Widget
|
|
@ -1,132 +0,0 @@
|
|||
-- 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.gui.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:setColor(1, 1, 1)
|
||||
end
|
||||
|
||||
function TextWidget:addLabel(label, position)
|
||||
local complexLabel = {}
|
||||
assert(label ~= nil, "Label can't be nil")
|
||||
complexLabel.label = label
|
||||
complexLabel.position = position or "left"
|
||||
table.insert(self.labels, complexLabel)
|
||||
end
|
||||
|
||||
function TextWidget:replaceLabel(id, newLabel)
|
||||
self.labels[id].label = newLabel
|
||||
end
|
||||
|
||||
function TextWidget:setColor(r, g, b)
|
||||
self.color = {}
|
||||
self.color.r = r
|
||||
self.color.g = g
|
||||
self.color.b = b
|
||||
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()
|
||||
if (self.selectedColor ~= nil) then
|
||||
return self.selectedColor.r, self.selectedColor.g, self.selectedColor.b
|
||||
else
|
||||
return self:getColor()
|
||||
end
|
||||
end
|
||||
|
||||
function TextWidget:getColor()
|
||||
return self.color.r, self.color.g, self.color.b
|
||||
end
|
||||
|
||||
function TextWidget:getPadding()
|
||||
return self.padding
|
||||
end
|
||||
|
||||
function TextWidget:getPaddingLeft()
|
||||
return self.paddingLeft or self:getPadding()
|
||||
end
|
||||
|
||||
function TextWidget:getPaddingRight()
|
||||
return self.paddingRight or self:getPadding()
|
||||
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:getPaddingLeft()
|
||||
elseif (complexLabel.position == "right") then
|
||||
w = math.floor(self.width - self:getPaddingRight())
|
||||
else
|
||||
error("Position " .. complexLabel.position .. " is unknown for label " .. complexLabel.label)
|
||||
end
|
||||
font:draw(complexLabel.label, w, h, -1, complexLabel.position)
|
||||
end
|
||||
end
|
||||
|
||||
function TextWidget:draw(x, y, w, h)
|
||||
local r, g, b = self:getColor()
|
||||
love.graphics.setColor(r, g, b, 1)
|
||||
if self.canvas.texture ~= nil then
|
||||
love.graphics.draw(self.canvas.texture, x, y)
|
||||
end
|
||||
utils.graphics.resetColor()
|
||||
end
|
||||
|
||||
function TextWidget:drawSelected(x, y, w, h)
|
||||
local r, g, b = self:getSelectedColor()
|
||||
love.graphics.setColor(r, g, b, 1)
|
||||
if self.canvas.texture ~= nil then
|
||||
love.graphics.draw(self.canvas.texture, x, y)
|
||||
end
|
||||
utils.graphics.resetColor()
|
||||
end
|
||||
|
||||
return TextWidget
|
|
@ -1,94 +0,0 @@
|
|||
local ElementList = Object:extend()
|
||||
|
||||
function ElementList:initElements()
|
||||
self.elements = {}
|
||||
self.focusedElement = nil
|
||||
self.lastFocused = nil
|
||||
self.nbrElement = 0
|
||||
end
|
||||
|
||||
function ElementList:addElement(name, element)
|
||||
self.nbrElement = self.nbrElement + 1
|
||||
self.elements[name] = element
|
||||
return self.nbrElement
|
||||
end
|
||||
|
||||
function ElementList:deleteElement(name)
|
||||
self.elements[name] = nil
|
||||
end
|
||||
|
||||
function ElementList:setFocus(name, widgetId, page)
|
||||
assert(self:elementExists(name), "Element " .. name .. " doesn't exists")
|
||||
self:storeLastFocus()
|
||||
self.focusedElement = name
|
||||
self.elements[name].isVisible = true
|
||||
if (widgetId ~= nil) then
|
||||
self.elements[name]:setSubFocus(widgetId, page)
|
||||
end
|
||||
end
|
||||
|
||||
function ElementList:removeFocus()
|
||||
self:storeLastFocus()
|
||||
self.focusedElement = nil
|
||||
end
|
||||
|
||||
function ElementList:storeLastFocus()
|
||||
if (self.focusedElement ~= nil) then
|
||||
self.lastFocused = self.focusedElement
|
||||
end
|
||||
end
|
||||
|
||||
function ElementList:setLastFocus()
|
||||
if (self:elementExists(self.lastFocused)) then
|
||||
self:setFocus(self.lastFocused)
|
||||
end
|
||||
end
|
||||
|
||||
function ElementList:elementExists(name)
|
||||
return (self:getElement(name) ~= nil)
|
||||
end
|
||||
|
||||
function ElementList:haveFocus()
|
||||
return self:elementIsVisible(self.focusedElement)
|
||||
end
|
||||
|
||||
function ElementList:getFocusedElement()
|
||||
return self:getElement(self.focusedElement)
|
||||
end
|
||||
|
||||
function ElementList:getElement(name)
|
||||
if (not utils.string.isEmpty(name)) then
|
||||
return self.elements[name]
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function ElementList:getVisibleElement(topLayer)
|
||||
local visibleList = {}
|
||||
for _, element in pairs(self.elements) do
|
||||
if (element ~= nil) then
|
||||
if (element:getVisibility() and ((element.depth) < 0 == topLayer)) then
|
||||
table.insert(visibleList, element)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(visibleList, function (a, b)
|
||||
if (a.depth == b.depth) then
|
||||
return (a.creationId < b.creationId)
|
||||
else
|
||||
return (a.depth > b.depth)
|
||||
end
|
||||
end)
|
||||
|
||||
return visibleList
|
||||
end
|
||||
|
||||
function ElementList:elementIsVisible(name)
|
||||
if (self:elementExists(name)) then
|
||||
return self.elements[name]:getVisibility()
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
return ElementList
|
|
@ -1,20 +0,0 @@
|
|||
local ScreenList = Object:extend()
|
||||
|
||||
function ScreenList:initScreens()
|
||||
self.screens = {}
|
||||
end
|
||||
|
||||
function ScreenList:addScreen(name, screen)
|
||||
self.screens[name] = screen
|
||||
end
|
||||
|
||||
function ScreenList:deleteScreen(name)
|
||||
self.screens[name]:purgeElements()
|
||||
self.screens[name] = nil
|
||||
end
|
||||
|
||||
function ScreenList:getScreen(name)
|
||||
return self.screens[name]
|
||||
end
|
||||
|
||||
return ScreenList
|
|
@ -1,160 +0,0 @@
|
|||
local GuiScreen = Object:extend()
|
||||
local ElementList = require "birb.modules.gui.mixins.elements"
|
||||
GuiScreen:implement(ElementList)
|
||||
|
||||
local TweenManager = require "birb.classes.time"
|
||||
local ScreenSet = require "birb.modules.gui.screen.screenset"
|
||||
|
||||
local elementDataStruct = require "birb.structures.elementData"
|
||||
|
||||
function GuiScreen:new(name)
|
||||
self:initWrapper()
|
||||
self.name = name
|
||||
self.isVisible = false
|
||||
self.transforms = {}
|
||||
self.tweens = TweenManager(self)
|
||||
|
||||
self:reset()
|
||||
self:registerElements()
|
||||
self.gui:addScreen(name, self)
|
||||
|
||||
self.defaultFocus = nil
|
||||
end
|
||||
|
||||
function GuiScreen:initWrapper()
|
||||
local scene = core.scenemanager.nextScene or core.scenemanager.currentScene
|
||||
self.scene = scene
|
||||
self.gui = scene.gui
|
||||
-- Présent pour la compatibilité
|
||||
self.controller = self.gui
|
||||
self.assets = scene.assets
|
||||
end
|
||||
|
||||
function GuiScreen:update(dt)
|
||||
self.tweens:update(dt)
|
||||
end
|
||||
|
||||
function GuiScreen:show(focusElement, widgetId, page)
|
||||
self:showSimple(focusElement, widgetId, page)
|
||||
if (self.set ~= nil) then
|
||||
self.set.owner:show()
|
||||
end
|
||||
end
|
||||
|
||||
function GuiScreen:showSimple(focusElement, widgetId, page)
|
||||
focusElement = focusElement or self.defaultFocus
|
||||
if (not self.isVisible) then
|
||||
self.isVisible = true
|
||||
local delay = 0
|
||||
if (self.set ~= nil) then
|
||||
delay = self.set:setCurrentScreen(self.name)
|
||||
end
|
||||
|
||||
if (self.transforms["show"] ~= nil) then
|
||||
if (delay == 0) then
|
||||
self:showWithSubScreen(focusElement, widgetId, page)
|
||||
else
|
||||
self.tweens:newFunc(delay, "focus", function () self:showWithSubScreen(focusElement, widgetId, page) end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GuiScreen:showWithSubScreen(focusElement, widgetId, page)
|
||||
self:playTransform("show")
|
||||
if (focusElement ~= nil) then
|
||||
self.gui:setFocus(focusElement, widgetId, page)
|
||||
end
|
||||
|
||||
if (self.subscreens ~= nil) then
|
||||
self.subscreens:show()
|
||||
end
|
||||
end
|
||||
|
||||
function GuiScreen:setDatas(datas)
|
||||
|
||||
end
|
||||
|
||||
function GuiScreen:hide()
|
||||
local time = 0
|
||||
if (self.isVisible) then
|
||||
if (self.transforms["hide"] ~= nil) then
|
||||
time = self:playTransform("hide")
|
||||
self.tweens:newFunc(time, "hide", function ()
|
||||
self.isVisible = false
|
||||
end)
|
||||
end
|
||||
|
||||
if (self.subscreens ~= nil) then
|
||||
self.subscreens:hideCurrent()
|
||||
end
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
function GuiScreen:addTransform(name, transform)
|
||||
self.transforms[name] = transform
|
||||
end
|
||||
|
||||
function GuiScreen:playTransform(name, delay)
|
||||
return self.gui:transform(self.transforms[name], delay)
|
||||
end
|
||||
|
||||
function GuiScreen:reset()
|
||||
self:initElements()
|
||||
end
|
||||
|
||||
function GuiScreen:registerElements()
|
||||
local elementList = self:createElements()
|
||||
for _, rawElement in ipairs(elementList) do
|
||||
if (rawElement.is ~= nil) then
|
||||
self:addElement(rawElement.name, rawElement)
|
||||
rawElement.screen = self
|
||||
else
|
||||
local elemData = utils.table.parse(rawElement, elementDataStruct, 3)
|
||||
local element = elemData.element
|
||||
self:addElement(element.name, element)
|
||||
if (elemData.focus == true) then
|
||||
element:getFocus()
|
||||
end
|
||||
if (elemData.delay > 0) then
|
||||
element.isVisible = false
|
||||
element:newSwitch(elemData.delay, {"isVisible"})
|
||||
end
|
||||
if (elemData.depth ~= nil) then
|
||||
element.depth = elemData.depth
|
||||
end
|
||||
if (elemData.keypress ~= nil) then
|
||||
element:setKeyPressAction(elemData.keypress)
|
||||
end
|
||||
element.screen = self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GuiScreen:createElements()
|
||||
-- Empty function
|
||||
end
|
||||
|
||||
function GuiScreen:setParentSet(set)
|
||||
self.set = set
|
||||
end
|
||||
|
||||
function GuiScreen:addSubscreen(screen)
|
||||
self:initSubscreen()
|
||||
self.subscreens:add(screen)
|
||||
end
|
||||
|
||||
function GuiScreen:showSubscreen(screenname)
|
||||
if (self.subscreens ~= nil) then
|
||||
self.subscreens:show(screenname)
|
||||
end
|
||||
end
|
||||
|
||||
function GuiScreen:initSubscreen()
|
||||
if (self.subscreens == nil) then
|
||||
self.subscreens = ScreenSet(self)
|
||||
end
|
||||
end
|
||||
|
||||
return GuiScreen
|
|
@ -1,73 +0,0 @@
|
|||
-- screens/screenset :: a set of exclusive screens
|
||||
-- Useful to handle a complexe menu with several screens
|
||||
|
||||
--[[
|
||||
Copyright © 2021 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 ScreenSet = Object:extend()
|
||||
|
||||
function ScreenSet:new(owner)
|
||||
self.set = {}
|
||||
self.defaultScreen = ""
|
||||
self.currentScreen = ""
|
||||
self.owner = owner
|
||||
self.delay = 0
|
||||
end
|
||||
|
||||
function ScreenSet:show(screenName)
|
||||
local screenName = screenName
|
||||
if (screenName == nil) then
|
||||
if self.currentScreen == "" then
|
||||
screenName = self.defaultScreen
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
if screenName ~= "" then
|
||||
self.set[screenName]:showSimple()
|
||||
end
|
||||
end
|
||||
|
||||
function ScreenSet:setCurrentScreen(screenName)
|
||||
screenName = screenName or self.defaultScreen
|
||||
local time = self:hideCurrent() + self.delay
|
||||
self.currentScreen = screenName
|
||||
return time
|
||||
end
|
||||
|
||||
function ScreenSet:hideCurrent()
|
||||
local time = 0
|
||||
if (self.currentScreen ~= "") then
|
||||
time = self.set[self.currentScreen]:hide()
|
||||
self.currentScreen = ""
|
||||
end
|
||||
return time
|
||||
end
|
||||
|
||||
function ScreenSet:add(screen, setAsDefault)
|
||||
self.set[screen.name] = screen
|
||||
if (setAsDefault == true or self.defaultScreen == "") then
|
||||
self.defaultScreen = screen.name
|
||||
end
|
||||
screen:setParentSet(self)
|
||||
end
|
||||
|
||||
return ScreenSet
|
|
@ -1,113 +0,0 @@
|
|||
-- 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.gui.menus.listbox"
|
||||
local TextMenu = ListBox:extend()
|
||||
|
||||
TextMenu.baseWidgets = require "birb.modules.gui.textmenu.widgets"
|
||||
|
||||
local BASE_PADDING = 8
|
||||
|
||||
function TextMenu:new(name, font, x, y, w, slotNumber, padding, lineSize)
|
||||
lineSize = lineSize or 1
|
||||
self:setFont(font)
|
||||
self.lineHeight = self.font:getHeight() * lineSize
|
||||
self.name = name
|
||||
|
||||
self.padding = padding or BASE_PADDING
|
||||
TextMenu.super.new(self, name, x, y, w, (self.lineHeight * slotNumber), slotNumber)
|
||||
end
|
||||
|
||||
function TextMenu:addItem(text, position, func, type, additionnalItems, color, additionnalDatas)
|
||||
local widget = TextMenu.baseWidgets.Base(self.name, text, position)
|
||||
widget:setFunc(func)
|
||||
widget.type = type or "select"
|
||||
if (additionnalItems ~= nil) then
|
||||
for _, item in ipairs(additionnalItems) do
|
||||
widget:addLabel(item[1], item[2])
|
||||
end
|
||||
end
|
||||
if (color ~= nil) then
|
||||
widget:setColor(color[1], color[2], color[3])
|
||||
end
|
||||
if (additionnalDatas ~= nil) then
|
||||
widget.datas = additionnalDatas
|
||||
end
|
||||
end
|
||||
|
||||
function TextMenu:generateSubmenu(pageName, label, parent, list, func, backWidget)
|
||||
self:addSubmenu(pageName, label, parent, backWidget)
|
||||
for _, data in ipairs(list) do
|
||||
self:addItem(func(data))
|
||||
end
|
||||
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
|
||||
end
|
||||
|
||||
function TextMenu:getPadding()
|
||||
return self.padding
|
||||
end
|
||||
|
||||
function TextMenu:getPaddingLeft()
|
||||
return self.paddingLeft or self:getPadding()
|
||||
end
|
||||
|
||||
function TextMenu:getPaddingRight()
|
||||
return self.paddingRight or self:getPadding()
|
||||
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)
|
||||
self:setCancelWidget("last")
|
||||
end
|
||||
end
|
||||
|
||||
return TextMenu
|
|
@ -1,37 +0,0 @@
|
|||
-- 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.gui.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
|
|
@ -1,60 +0,0 @@
|
|||
-- 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.gui.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()
|
||||
local selectedColor = self.menu:getSelectedColor()
|
||||
if (selectedColor ~= nil) then
|
||||
return selectedColor.r, selectedColor.g, selectedColor.b
|
||||
else
|
||||
return self:getColor()
|
||||
end
|
||||
end
|
||||
|
||||
function TextMenuWidget:getPadding()
|
||||
return self.menu:getPadding()
|
||||
end
|
||||
|
||||
function TextWidget:getPaddingLeft()
|
||||
return self.menu:getPaddingLeft() or self:getPadding()
|
||||
end
|
||||
|
||||
function TextWidget:getPaddingRight()
|
||||
return self.menu:getPaddingRight() or self:getPadding()
|
||||
end
|
||||
|
||||
return TextMenuWidget
|
|
@ -1,31 +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 = {}
|
||||
|
||||
-- Add the widget as subvariable to the returned table
|
||||
Widget.Base = require "birb.modules.gui.textmenu.widgets.basic"
|
||||
Widget.SubMenu= require "birb.modules.gui.textmenu.widgets.submenu"
|
||||
Widget.Back = require "birb.modules.gui.textmenu.widgets.back"
|
||||
|
||||
return Widget
|
|
@ -1,39 +0,0 @@
|
|||
-- 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.gui.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
|
231
sonic-radiance.love/birb/modules/menusystem/flowbox.lua
Normal file
|
@ -0,0 +1,231 @@
|
|||
-- 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()
|
||||
self:updateSelectedWidget(dt)
|
||||
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
|
|
@ -26,16 +26,20 @@ local cwd = (...):gsub('%.grid$', '') .. "."
|
|||
local Menu = require(cwd .. "parent")
|
||||
local GridBox = Menu:extend()
|
||||
|
||||
local View2D = require "birb.modules.gui.menus.views.view2D"
|
||||
local menuutils = require(cwd .. "widgets.utils")
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure the menu
|
||||
|
||||
function GridBox:new(name, x, y, w, h, colNumber, lineNumber)
|
||||
self.view = View2D(colNumber, lineNumber)
|
||||
GridBox.super.new(self, name, x, y, w, h)
|
||||
self.h = lineNumber * self.widgetSize.h -- On fait en sorte que la hauteur
|
||||
self.w = colNumber * self.widgetSize.w -- et la largeur
|
||||
function GridBox:new(menusystem, name, x, y, w, h, colNumber, lineNumber)
|
||||
self.view = {}
|
||||
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)
|
||||
self.h = lineNumber * self.widget.h -- On fait en sorte que la hauteur
|
||||
self.w = colNumber * self.widget.w -- et la largeur
|
||||
-- soit un multiple du nombre de slot et de leur dimensions
|
||||
self.cursor = {}
|
||||
self.cursor.x = 0
|
||||
|
@ -52,13 +56,14 @@ function GridBox:addSlot(widgetID, x, y, w, h)
|
|||
slot.y = y
|
||||
slot.w = w
|
||||
slot.h = h
|
||||
slot.widgetID = widgetID
|
||||
|
||||
table.insert(self.slots, slot)
|
||||
end
|
||||
|
||||
function GridBox:updateWidgetSize()
|
||||
self.widgetSize.h = math.floor( self.h / self.view.lineNumber )
|
||||
self.widgetSize.w = math.floor( self.w / self.view.colNumber )
|
||||
self.widget.h = math.floor( self.h / self.view.lineNumber )
|
||||
self.widget.w = math.floor( self.w / self.view.colNumber )
|
||||
end
|
||||
|
||||
-- INFO FUNCTIONS
|
||||
|
@ -66,19 +71,19 @@ end
|
|||
|
||||
function GridBox:getWidgetSize(id)
|
||||
local slot = self:getWidgetSlot(id)
|
||||
if (slot == 0) then
|
||||
if slot == 0 then
|
||||
return 1, 1
|
||||
else
|
||||
return self.widgetSize.w * self.slots[slot].w, self.widgetSize.h * self.slots[slot].h
|
||||
return self.widget.w * self.slots[slot].w, self.widget.h * self.slots[slot].h
|
||||
end
|
||||
end
|
||||
|
||||
function GridBox:getSlotHitbox(slot)
|
||||
local x, y, w, h
|
||||
x = self.slots[slot].x * self.widgetSize.w
|
||||
y = self.slots[slot].y * self.widgetSize.h
|
||||
w = self.slots[slot].w * self.widgetSize.w
|
||||
h = self.slots[slot].h * self.widgetSize.h
|
||||
x = self.slots[slot].x * self.widget.w
|
||||
y = self.slots[slot].y * self.widget.h
|
||||
w = self.slots[slot].w * self.widget.w
|
||||
h = self.slots[slot].h * self.widget.h
|
||||
|
||||
return x, y, w, h
|
||||
end
|
||||
|
@ -135,48 +140,40 @@ end
|
|||
|
||||
function GridBox:update(dt)
|
||||
self.view.firstSlot = 1
|
||||
self:updateSelectedWidget(dt)
|
||||
end
|
||||
|
||||
function GridBox:resetView()
|
||||
self.view:reset()
|
||||
end
|
||||
|
||||
|
||||
-- KEYS FUNCTIONS
|
||||
-- Handle the keyboard/manette functions
|
||||
|
||||
function GridBox:keyreleased(key, code)
|
||||
local slotID = self:getWidgetSlot(self.widget:getSelected())
|
||||
local slotID = self:getWidgetSlot(self.widget.selected)
|
||||
local col, line = self.cursor.x, self.cursor.y
|
||||
if key == 'left' then
|
||||
self:moveCol(-1)
|
||||
self:playNavigationSound()
|
||||
end
|
||||
|
||||
if key == 'right' then
|
||||
self:moveCol(1)
|
||||
self:playNavigationSound()
|
||||
end
|
||||
|
||||
if key == 'up' then
|
||||
self:moveLine(-1)
|
||||
self:playNavigationSound()
|
||||
end
|
||||
|
||||
if key == 'down' then
|
||||
self:moveLine(1)
|
||||
self:playNavigationSound()
|
||||
end
|
||||
|
||||
if key == "A" and self.widget:getSelected() <= self.widget:lenght() then
|
||||
self.widget.list[self.widget:getSelected()]:action("key")
|
||||
if key == "A" and self.widget.selected <= #self.widget.list then
|
||||
self.widget.list[self.widget.selected]:action("key")
|
||||
end
|
||||
end
|
||||
|
||||
function GridBox:moveCol(direction)
|
||||
local orig_x, orig_y = self:getSlotCenter(self.widget:getSelected())
|
||||
local orig_x, orig_y = self:getSlotCenter(self.widget.selected)
|
||||
local distance = self.w -- on met directement à la distance max possible le système
|
||||
local nearestWidget = 0
|
||||
local nearastWidget = 0
|
||||
for i,v in ipairs(self.slots) do
|
||||
local xx, yy = self:getSlotCenter(i)
|
||||
-- On commence par vérifier si le slot est bien positionné par rapport au
|
||||
|
@ -184,20 +181,20 @@ function GridBox:moveCol(direction)
|
|||
if utils.math.sign(xx - orig_x) == direction then
|
||||
if utils.math.pointDistance(orig_x, orig_y, xx, yy) < distance then
|
||||
distance = utils.math.pointDistance(orig_x, orig_y, xx, yy)
|
||||
nearestWidget = v.widgetID
|
||||
nearastWidget = v.widgetID
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (nearestWidget ~= 0) then
|
||||
self.widget:setCursor(nearestWidget)
|
||||
if nearastWidget ~= 0 then
|
||||
self.widget.selected = nearastWidget
|
||||
end
|
||||
end
|
||||
|
||||
function GridBox:moveLine(direction)
|
||||
local orig_x, orig_y = self:getSlotCenter(self.widget:getSelected())
|
||||
local orig_x, orig_y = self:getSlotCenter(self.widget.selected)
|
||||
local distance = self.h -- on met directement à la distance max possible le système
|
||||
local nearestWidget = 0
|
||||
local nearastWidget = 0
|
||||
for i,v in ipairs(self.slots) do
|
||||
local xx, yy = self:getSlotCenter(i)
|
||||
-- On commence par vérifier si le slot est bien positionné par rapport au
|
||||
|
@ -205,13 +202,13 @@ function GridBox:moveLine(direction)
|
|||
if utils.math.sign(yy - orig_y) == direction then
|
||||
if utils.math.pointDistance(orig_x, orig_y, xx, yy) < distance then
|
||||
distance = utils.math.pointDistance(orig_x, orig_y, xx, yy)
|
||||
nearestWidget = v.widgetID
|
||||
nearastWidget = v.widgetID
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (nearestWidget ~= 0) then
|
||||
self.widget:setCursor(nearestWidget)
|
||||
if nearastWidget ~= 0 then
|
||||
self.widget.selected = nearastWidget
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -221,43 +218,43 @@ end
|
|||
function GridBox:mousemoved(x, y)
|
||||
local widgetID = self:getWidgetAtPoint(x, y)
|
||||
|
||||
-- if (widgetID ~= nil) then
|
||||
-- self.widget:getSelected() = widgetID
|
||||
-- self:getFocus()
|
||||
-- end
|
||||
if widgetID ~= nil then
|
||||
self.widget.selected = widgetID
|
||||
self:getFocus()
|
||||
end
|
||||
|
||||
-- if self.widget:getSelected() < 1 then
|
||||
-- self.widget:getSelected() = 1
|
||||
-- end
|
||||
-- if self.widget:getSelected() > self.widget:lenght() then
|
||||
-- self.widget:getSelected() = self.widget:lenght()
|
||||
-- end
|
||||
if self.widget.selected < 1 then
|
||||
self.widget.selected = 1
|
||||
end
|
||||
if self.widget.selected > #self.widget.list then
|
||||
self.widget.selected = #self.widget.list
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function GridBox:mousepressed(x, y, button, isTouch)
|
||||
local widgetID = self:getWidgetAtPoint(x, y)
|
||||
|
||||
-- if (widgetID ~= nil) then
|
||||
-- self.widget:getSelected() = widgetID
|
||||
-- self:getFocus()
|
||||
if widgetID ~= nil then
|
||||
self.widget.selected = widgetID
|
||||
self:getFocus()
|
||||
|
||||
-- if self.widget:lenght() > 0 and self.widget:getSelected() > 1 and self.widget:getSelected() <= self.widget:lenght() then
|
||||
-- self.widget.list[self.widget:getSelected()]:action("pointer")
|
||||
-- end
|
||||
-- end
|
||||
if #self.widget.list > 0 and self.widget.selected > 1 and self.widget.selected <= #self.widget.list then
|
||||
self.widget.list[self.widget.selected]:action("pointer")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Draw the menu and its content
|
||||
|
||||
function GridBox:drawTexture()
|
||||
function GridBox:draw()
|
||||
|
||||
for i,v in ipairs(self.slots) do
|
||||
if self:haveWidget(i) then
|
||||
local widgetx = self.canvas.padding + (v.x * self.widgetSize.w)
|
||||
local widgety = self.canvas.padding + (v.y * self.widgetSize.h)
|
||||
if self.widget:getSelected() == v.widgetID and self:haveFocus() == true then
|
||||
local widgetx = self.x + (v.x * self.widget.w)
|
||||
local widgety = self.y + (v.y * self.widget.h)
|
||||
if self.widget.selected == v.widgetID and self:haveFocus() == true then
|
||||
self.widget.list[v.widgetID]:drawSelected(widgetx, widgety)
|
||||
else
|
||||
self.widget.list[v.widgetID]:draw(widgetx, widgety)
|
||||
|
@ -268,12 +265,12 @@ end
|
|||
|
||||
function GridBox:drawCursor()
|
||||
self:updateView()
|
||||
if (self.widget:getSelected() >= 1 and self.widget:getSelected() <= self.widget:lenght()) then
|
||||
local slot = self:getWidgetSlot(self.widget:getSelected())
|
||||
if (self.widget.selected >= 1 and self.widget.selected <= #self.widget.list) then
|
||||
local slot = self:getWidgetSlot(self.widget.selected)
|
||||
local w, h = self:getWidgetSize(slot)
|
||||
local x = self.slots[slot].x * self.widgetSize.w
|
||||
local y = self.slots[slot].y * self.widgetSize.h
|
||||
self:drawGraphicalCursor(x, y, w, h)
|
||||
local x = self.slots[slot].x * self.widget.w
|
||||
local y = self.slots[slot].y * self.widget.h
|
||||
menuutils.drawCursor(self.x + x, self.y + y, w, h)
|
||||
end
|
||||
end
|
||||
|
149
sonic-radiance.love/birb/modules/menusystem/hlistbox.lua
Normal file
|
@ -0,0 +1,149 @@
|
|||
-- 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()
|
||||
self:updateSelectedWidget(dt)
|
||||
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
|
290
sonic-radiance.love/birb/modules/menusystem/init.lua
Normal file
|
@ -0,0 +1,290 @@
|
|||
-- menusystem :: the controller of the menu system. This object handle the
|
||||
-- different menu objects
|
||||
|
||||
--[[
|
||||
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('%.init$', '') .. "."
|
||||
|
||||
local MenuSystem = Object:extend()
|
||||
|
||||
-- Load the differents menu object to get an easy access
|
||||
MenuSystem.Parent = require(cwd .. "parent")
|
||||
MenuSystem.ListBox = require(cwd .. "listbox")
|
||||
MenuSystem.FlowBox = require(cwd .. "flowbox")
|
||||
MenuSystem.Grid = require(cwd .. "grid")
|
||||
|
||||
-- load widgets object
|
||||
MenuSystem.Widget = require(cwd .. "widgets")
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure the menu controller
|
||||
|
||||
function MenuSystem:new(scene)
|
||||
self.scene = scene
|
||||
self.menus = {}
|
||||
self.focusedMenu = ""
|
||||
self.isActive = true
|
||||
self.lockWorld = false
|
||||
self.lockAssets = false
|
||||
end
|
||||
|
||||
function MenuSystem:reset()
|
||||
self.menus = {}
|
||||
end
|
||||
|
||||
-- ACTIVATION FUNCTIONS
|
||||
-- Activate and deactivate the whole menusystem
|
||||
|
||||
function MenuSystem:activate()
|
||||
self.isActive = true
|
||||
|
||||
if (self.lockWorld) then
|
||||
if (self.scene.world ~= nil) then
|
||||
self.scene.world:setActivity(false)
|
||||
end
|
||||
end
|
||||
|
||||
if (self.lockAssets) then
|
||||
if (self.scene.assets ~= nil) then
|
||||
self.scene.assets:setActivity(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:deactivate()
|
||||
self.isActive = false
|
||||
|
||||
if (self.lockWorld) then
|
||||
if (self.scene.world ~= nil) then
|
||||
self.scene.world:setActivity(true)
|
||||
end
|
||||
end
|
||||
|
||||
if (self.lockAssets) then
|
||||
if (self.scene.assets ~= nil) then
|
||||
self.scene.assets:setActivity(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:getActiveState()
|
||||
return self.isActive
|
||||
end
|
||||
|
||||
function MenuSystem:lockWorldWhenActive(state)
|
||||
self.lockWorld = state
|
||||
end
|
||||
|
||||
function MenuSystem:lockAssetsWhenActive(state)
|
||||
self.lockAssets = state
|
||||
end
|
||||
|
||||
|
||||
-- MENUS FUNCTIONS
|
||||
-- Controle the menus of the menusystem
|
||||
|
||||
function MenuSystem:addMenu(name, menu)
|
||||
self.menus[name] = menu
|
||||
end
|
||||
|
||||
function MenuSystem:menuExist(name)
|
||||
return (self.menus[name] ~= nil)
|
||||
end
|
||||
|
||||
function MenuSystem:switchMenu(menu)
|
||||
for k,v in pairs(self.menus) do
|
||||
if k == menu then
|
||||
v:getFocus()
|
||||
v:setVisibility(true)
|
||||
v:setActivity(true)
|
||||
else
|
||||
v:setVisibility(false)
|
||||
v:setActivity(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:lockMenu(menu, lock)
|
||||
local lock = lock or true
|
||||
if self:menuExist(menu) then
|
||||
self.menus[menu]:lock(lock)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:lockMenuVisibility(menu, lock)
|
||||
local lock = lock or true
|
||||
if self:menuExist(menu) then
|
||||
self.menus[menu]:lockVisibility(lock)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:setMenuActivity(menu, activity)
|
||||
local activity = activity or true
|
||||
if self:menuExist(menu) then
|
||||
self.menus[menu]:setActivity(activity)
|
||||
if activity == true then
|
||||
-- if we make the menu active, he have to be visible too
|
||||
self.menus[menu]:setVisibility(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:setMenuVisibility(menu, visibility)
|
||||
local visibility = visibility or true
|
||||
if self:menuExist(menu) then
|
||||
self.menus[menu]:setVisibility(visibility)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:setAllMenuVisibility(visibility)
|
||||
for k,v in pairs(self.menus) do
|
||||
v:setVisibility(visibility)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:setAllMenuActivity(activity)
|
||||
for k,v in pairs(self.menus) do
|
||||
v.isActive = activity
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:removeDestroyedMenus()
|
||||
-- On retire les entitées marquées comme supprimées
|
||||
for k,v in pairs(self.menus) do
|
||||
if (v.isDestroyed == true) then
|
||||
self.menus[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- SOUND FUNCTIONS
|
||||
-- Add sounds to every menus
|
||||
|
||||
function MenuSystem:setSoundFromSceneAssets(soundname)
|
||||
for k,v in pairs(self.menus) do
|
||||
v:setSoundFromSceneAssets(soundname)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:setSound(soundasset)
|
||||
for k,v in pairs(self.menus) do
|
||||
v:setSound(soundasset)
|
||||
end
|
||||
end
|
||||
|
||||
-- UPDATE FUNCTIONS
|
||||
-- Update the menus of the menusystem
|
||||
|
||||
function MenuSystem:update(dt)
|
||||
if (self.isActive) then
|
||||
self:removeDestroyedMenus()
|
||||
for k,v in pairs(self.menus) do
|
||||
v:update(dt)
|
||||
v:updateWidgets(dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:keycheck()
|
||||
if (self.isActive) then
|
||||
if self.menus[self.focusedMenu] ~= nil then
|
||||
-- Only check buttons if the current focused menu is actually active
|
||||
if self.menus[self.focusedMenu].isActive then
|
||||
for k,v in pairs(self.keys) do
|
||||
if self.keys[k].isPressed then
|
||||
self.menus[self.focusedMenu]:keyreleased(k)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- MOUSE FUNCTIONS
|
||||
-- Send mouse inputs to the menu
|
||||
|
||||
function MenuSystem:mousemoved(x, y, dx, dy)
|
||||
if (self.isActive) then
|
||||
|
||||
for k,v in pairs(self.menus) do
|
||||
if v.isActive then
|
||||
if (x > v.x) and (x < v.x + v.w) and (y > v.y) and (y < v.y + v.h) then
|
||||
v:mousemoved(x - v.x, y - v.y)
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function MenuSystem:mousepressed( x, y, button, istouch )
|
||||
if (self.isActive) then
|
||||
for k,v in pairs(self.menus) do
|
||||
if v.isActive then
|
||||
if (x > v.x) and (x < v.x + v.w) and (y > v.y) and (y < v.y + v.h) then
|
||||
v:mousepressed(x - v.x, y - v.y, button, istouch )
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- All functions to draw the menus of the menusystem
|
||||
|
||||
function MenuSystem:getDrawList()
|
||||
local drawList = {}
|
||||
for k,v in pairs(self.menus) do
|
||||
local drawObject = {}
|
||||
drawObject.name = k
|
||||
drawObject.depth = v.depth
|
||||
table.insert(drawList, drawObject)
|
||||
end
|
||||
table.sort(drawList, function(a,b) return a.depth > b.depth end)
|
||||
|
||||
return drawList
|
||||
end
|
||||
|
||||
function MenuSystem:draw(dt)
|
||||
if (self.isActive) then
|
||||
-- Draw all the menus
|
||||
self.drawList = self:getDrawList()
|
||||
|
||||
for i,v in ipairs(self.drawList) do
|
||||
local v2 = self.menus[v.name]
|
||||
if (v2.isVisible) then
|
||||
v2:draw(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
|
||||
|
||||
return MenuSystem
|
147
sonic-radiance.love/birb/modules/menusystem/listbox.lua
Normal file
|
@ -0,0 +1,147 @@
|
|||
-- 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()
|
||||
self:updateSelectedWidget(dt)
|
||||
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
|
||||
self:cancelAction()
|
||||
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
|
||||
if self.widget.selected == i and self:haveFocus() == true then
|
||||
v:drawSelected(self.x, widgety, self.w, self.widget.h)
|
||||
else
|
||||
utils.graphics.resetColor()
|
||||
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
|
302
sonic-radiance.love/birb/modules/menusystem/parent.lua
Normal file
|
@ -0,0 +1,302 @@
|
|||
-- 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 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
|
||||
end
|
||||
end
|
||||
|
||||
function Menu:setActivity(activity)
|
||||
if self.isLocked == false then
|
||||
self.isActive = activity
|
||||
else
|
||||
self.isActive = true
|
||||
end
|
||||
end
|
||||
|
||||
function Menu:lock(lock)
|
||||
self.isLocked = lock
|
||||
end
|
||||
|
||||
function Menu:lockVisibility(lock)
|
||||
self.isAlwaysVisible = lock
|
||||
end
|
||||
|
||||
function Menu:getFocus()
|
||||
self.menusystem.focusedMenu = self.name
|
||||
end
|
||||
|
||||
function Menu:haveFocus()
|
||||
return (self.menusystem.focusedMenu == self.name)
|
||||
end
|
||||
|
||||
function Menu:register()
|
||||
self.menusystem:addMenu(self.name, self)
|
||||
end
|
||||
|
||||
function Menu:setCancelWidget(id)
|
||||
self.widget.cancel = #self.widget.list
|
||||
end
|
||||
|
||||
function Menu:updateWidgetSize()
|
||||
self.widget.h = 0
|
||||
self.widget.w = 0
|
||||
end
|
||||
|
||||
function Menu:getWidgetSize(id)
|
||||
return self.widget.w, self.widget.h
|
||||
end
|
||||
|
||||
function Menu:getWidgetNumber()
|
||||
return #self.widget.list
|
||||
end
|
||||
|
||||
-- ACTION FUNCTIONS
|
||||
-- Send actions to the widgets
|
||||
|
||||
function Menu:cancelAction()
|
||||
if (self.widget.cancel >= 1 and self.widget.cancel <= #self.widget.list) 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.isDestroyed = true
|
||||
end
|
||||
|
||||
function Menu:updateWidgetsOrder()
|
||||
table.sort(self.widget.list, updateWidgetByOrder)
|
||||
end
|
||||
|
||||
-- UPDATE FUNCTIONS
|
||||
-- Update the menu every game update
|
||||
|
||||
function Menu:update(dt)
|
||||
-- Cette fonction ne contient rien par défaut
|
||||
self:updateSelectedWidget(dt)
|
||||
end
|
||||
|
||||
function Menu:updateSelectedWidget(dt)
|
||||
if (self.widget.selected ~= self.widget.previous) and (self.isActive) then
|
||||
if (self.widget.list[self.widget.selected] ~= nil) then
|
||||
self.widget.list[self.widget.selected]:selectAction()
|
||||
self.widget.previous = self.widget.selected
|
||||
end
|
||||
end
|
||||
if (self.widget.list[self.widget.selected] ~= nil) then
|
||||
self.widget.list[self.widget.selected]:updateSelected(dt)
|
||||
end
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Draw the menu and its content
|
||||
|
||||
function Menu:draw()
|
||||
-- nothing here
|
||||
end
|
||||
|
||||
function Menu:drawCursor()
|
||||
-- nothing here
|
||||
end
|
||||
|
||||
function Menu:drawCanvas()
|
||||
|
||||
end
|
||||
|
||||
-- KEYBOARD FUNCTIONS
|
||||
-- Handle key press
|
||||
|
||||
function Menu:keyreleased(key)
|
||||
-- Cette fonction ne contient rien par défaut
|
||||
end
|
||||
|
||||
-- MOUSE FUNCTIONS
|
||||
-- Handle pointers (clic/touch)
|
||||
|
||||
function Menu:mousemoved(x, y)
|
||||
-- Cette fonction ne contient rien par défaut
|
||||
end
|
||||
|
||||
function Menu:mousepressed( x, y, button, istouch )
|
||||
-- Cette fonction ne contient rien par défaut
|
||||
end
|
||||
|
||||
-- WIDGET FUNCTIONS
|
||||
-- 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.sfx[name])
|
||||
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
|
153
sonic-radiance.love/birb/modules/menusystem/widgets/init.lua
Normal file
|
@ -0,0 +1,153 @@
|
|||
-- 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 = {}
|
||||
|
||||
local BaseWidget = Object:extend()
|
||||
local 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.ox = 0
|
||||
self.oy = 0
|
||||
|
||||
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 * 2, self.height * 2)
|
||||
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
|
||||
|
||||
function BaseWidget:updateSelected(dt)
|
||||
-- Do nothing
|
||||
end
|
||||
|
||||
-- DRAW WIDGETS
|
||||
-- Draw the widget
|
||||
|
||||
function BaseWidget:draw(x, y)
|
||||
if self.canvas.texture ~= nil then
|
||||
love.graphics.draw(self.canvas.texture, x - self.ox, y - self.oy)
|
||||
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, color)
|
||||
TextWidget.super.new(self, menu)
|
||||
self.font = font
|
||||
self.label = label
|
||||
self.color = color or {1, 1, 1}
|
||||
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:setColor(self.color[1], self.color[2], self.color[3], 1)
|
||||
self.font:draw(self.label, w, h, -1, "center")
|
||||
self.font:setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
-- Add the widget as subvariable to the returned table
|
||||
Widget.Base = BaseWidget
|
||||
Widget.Text = TextWidget
|
||||
|
||||
return Widget
|
|
@ -1,4 +1,4 @@
|
|||
-- menusystem/utils :: basic utility functions for the gui
|
||||
-- widgets/utils :: basic utility functions for the widgets
|
||||
|
||||
--[[
|
||||
Copyright © 2019 Kazhnuz
|
||||
|
@ -21,9 +21,9 @@
|
|||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
|
||||
local guiUtils = {}
|
||||
local menuUtils = {}
|
||||
|
||||
function guiUtils.drawCursor(x, y, w, h)
|
||||
function menuUtils.drawCursor(x, y, w, h)
|
||||
love.graphics.setColor(0,0,0)
|
||||
|
||||
love.graphics.rectangle("fill", x, y, 4, 8)
|
||||
|
@ -54,4 +54,4 @@ function guiUtils.drawCursor(x, y, w, h)
|
|||
|
||||
end
|
||||
|
||||
return guiUtils
|
||||
return menuUtils
|
|
@ -27,7 +27,7 @@ local cwd = (...):gsub('%.scenes$', '') .. "."
|
|||
local Scene = Object:extend()
|
||||
|
||||
local Assets = require(cwd .. "assets")
|
||||
local Gui = require (cwd .. "gui")
|
||||
local MenuSystem = require(cwd .. "menusystem")
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialize and configure the scene
|
||||
|
@ -37,8 +37,8 @@ function Scene:new()
|
|||
self.mouse.x, self.mouse.y = core.screen:getMousePosition()
|
||||
|
||||
self.assets = Assets()
|
||||
self.menusystem = MenuSystem(self)
|
||||
self.sources = core.input:getSources()
|
||||
self.gui = Gui(self)
|
||||
|
||||
self.inputLocked = true
|
||||
self.inputLockedTimer = 2
|
||||
|
@ -65,16 +65,6 @@ end
|
|||
-- UPDATE FUNCTIONS
|
||||
-- Handle stuff that happens every steps
|
||||
|
||||
function Scene:updateScene(dt)
|
||||
self:updateStart(dt)
|
||||
self:setKeys()
|
||||
self.assets:update(dt)
|
||||
self:updateGUI(dt)
|
||||
self:updateWorld(dt)
|
||||
self:update(dt)
|
||||
self:updateEnd(dt)
|
||||
end
|
||||
|
||||
function Scene:updateStart(dt)
|
||||
|
||||
end
|
||||
|
@ -93,11 +83,17 @@ function Scene:updateWorld(dt)
|
|||
end
|
||||
end
|
||||
|
||||
function Scene:updateGUI(dt)
|
||||
if (self.gui ~= nil) then
|
||||
self.gui:update(dt)
|
||||
if (core.screen:isActive()) then
|
||||
self.gui:keycheck(self:getKeys(1))
|
||||
function Scene:updateDialog(dt)
|
||||
if (self.dialog ~= nil) then
|
||||
self.dialog:update(dt)
|
||||
end
|
||||
end
|
||||
|
||||
function Scene:updateMenus(dt)
|
||||
if (self.menusystem ~= nil) then
|
||||
self.menusystem:update(dt)
|
||||
if (core.screen:isActive() and (self.dialog == nil)) then
|
||||
self.menusystem:keycheck()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -138,21 +134,6 @@ end
|
|||
-- DRAW FUNCTIONS
|
||||
-- Draw the scene and its content
|
||||
|
||||
function Scene:redraw()
|
||||
self.gui:redraw()
|
||||
end
|
||||
|
||||
function Scene:drawScene()
|
||||
self:drawStart()
|
||||
self:drawWorld()
|
||||
self:draw()
|
||||
self.gui:drawBottom()
|
||||
self:drawEnd()
|
||||
core.screen:drawTransition()
|
||||
self.gui:drawTop()
|
||||
self:drawOverTransition()
|
||||
end
|
||||
|
||||
function Scene:drawStart()
|
||||
|
||||
end
|
||||
|
@ -175,6 +156,18 @@ function Scene:drawWorld(dt)
|
|||
end
|
||||
end
|
||||
|
||||
function Scene:drawDialog(dt)
|
||||
if (self.dialog ~= nil) then
|
||||
self.dialog:draw()
|
||||
end
|
||||
end
|
||||
|
||||
function Scene:drawMenus()
|
||||
if (self.menusystem ~= nil) then
|
||||
self.menusystem:draw()
|
||||
end
|
||||
end
|
||||
|
||||
-- INPUT FUNCTIONS
|
||||
-- Handle inputs from keyboard/controllers
|
||||
|
||||
|
@ -184,8 +177,10 @@ function Scene:setKeys()
|
|||
if (self.inputLockedTimer <= 0 ) then
|
||||
self.inputLocked = false
|
||||
end
|
||||
self.menusystem.keys = self:getKeys(1)
|
||||
else
|
||||
self.sources = core.input.sources
|
||||
self.menusystem.keys = self:getKeys(1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -111,4 +111,8 @@ function BaseActor:drawEnd()
|
|||
|
||||
end
|
||||
|
||||
function BaseActor:drawHUD(id, height, width)
|
||||
|
||||
end
|
||||
|
||||
return BaseActor
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
PhysicalActor = Object:extend()
|
||||
local hitboxStructure = require "birb.structures.hitbox"
|
||||
|
||||
-- PHYSICS FUNCTIONS
|
||||
-- Raw implementation of everything common in physics
|
||||
|
@ -177,22 +176,23 @@ end
|
|||
|
||||
function PhysicalActor:addHitboxFromFrameData(framedata, animationID, frameID, hitboxID)
|
||||
local sx, sy = self.sprite:getScalling()
|
||||
local hitbox = utils.table.parse(framedata, hitboxStructure, 1)
|
||||
local type = framedata[1]
|
||||
local box = framedata[2]
|
||||
local isSolid = framedata[3] or false
|
||||
local anim = animationID or "null"
|
||||
local frame = frameID or 0
|
||||
local id = hitboxID or 0
|
||||
|
||||
if (hitbox.type == "main") then
|
||||
self.mainHitbox:setFromData(hitbox.box, sx, sy)
|
||||
if (type == "main") then
|
||||
self.mainHitbox:setFromData(box, sx, sy)
|
||||
else
|
||||
local hitboxName = anim .. frame .. type .. id
|
||||
self:addHitbox(hitboxName, hitbox.type, hitbox.box, sx, sy, hitbox.isSolid)
|
||||
self:addHitbox(hitboxName, type, box, sx, sy, isSolid)
|
||||
return hitboxName
|
||||
end
|
||||
end
|
||||
|
||||
function PhysicalActor:addHitbox(name, type, data, sx, sy, isSolid)
|
||||
isSolid = (isSolid == true)
|
||||
if (self.hitboxes[name] ~= nil) then
|
||||
core.debug:logWarn("PhysicalActor", "the hitbox " .. name .. " already exists")
|
||||
else
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
]]
|
||||
|
||||
local Hitbox2D = Object:extend()
|
||||
local rectStructure = require "birb.structures.rect"
|
||||
|
||||
-- INIT FUNCTIONS
|
||||
-- Initialise the actor and its base functions
|
||||
|
@ -56,12 +55,10 @@ function Hitbox2D:modify(ox, oy, w, h)
|
|||
end
|
||||
|
||||
function Hitbox2D:setFromData(data, sx, sy)
|
||||
local rect = utils.table.parse(data, rectStructure)
|
||||
|
||||
self.ox = rect.x
|
||||
self.oy = rect.y
|
||||
self.w = rect.w
|
||||
self.h = rect.h
|
||||
self.ox = data[1]
|
||||
self.oy = data[2]
|
||||
self.w = data[3]
|
||||
self.h = data[4]
|
||||
|
||||
self:applyScale(sx, sy)
|
||||
end
|
||||
|
|