Compare commits

..

No commits in common. "master" and "big-refactor" have entirely different histories.

423 changed files with 7643 additions and 10858 deletions

View file

@ -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"
]
}

View file

@ -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/)

View file

@ -1 +0,0 @@
love ./sonic-radiance.love DEBUGLEVEL=4

View file

@ -1 +0,0 @@
love ./sonic-radiance.love

View file

@ -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"}
}
}

View file

@ -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"}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View file

@ -1,6 +0,0 @@
return {
metadata = {
height = 7,
width = 14,
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 906 B

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +1,4 @@
return {
glyphs = " 0123456789/ABCDEFGHIJKLMNOPQRSTUVWXYZ",
glyphs = " 0123456789/",
extraspacing = 0,
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

View file

@ -0,0 +1,4 @@
return {
glyphs = "abcdefghijklmnopqrstuvwxyz0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ",
extraspacing = 1
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

View file

@ -1,6 +0,0 @@
return {
metadata = {
width = 17,
height = 17,
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -1,6 +0,0 @@
return {
metadata = {
width = 24,
height = 24,
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -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,
},
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -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,
},
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View 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

View 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

View 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

View 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

View 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

View file

@ -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

View file

@ -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

View file

@ -111,4 +111,8 @@ function BaseActor:drawEnd()
end
function BaseActor:drawHUD(id, height, width)
end
return BaseActor

View file

@ -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

View file

@ -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

Some files were not shown because too many files have changed in this diff Show more