From 5837fd8b5121ad5663b20ac64293bb4dbb9a4340 Mon Sep 17 00:00:00 2001 From: Kazhnuz Date: Fri, 13 Nov 2020 19:11:09 +0100 Subject: [PATCH] feat: add a global asset system --- birb/core/assets.lua | 97 +++++ birb/core/init.lua | 3 + birb/core/scenemanager.lua | 1 - birb/modules/assets/init.lua | 346 +++++++++--------- birb/modules/menusystem/parent.lua | 2 +- birb/modules/world/actors/gfx2D.lua | 3 +- birb/modules/world/actors/gfx3D.lua | 3 +- .../world/actors/utils/boxes/textured.lua | 4 +- birb/modules/world/actors/utils/sprites.lua | 6 +- examples/scenes/gameplay/plateform/pause.lua | 6 +- examples/scenes/mainmenu/init.lua | 6 +- 11 files changed, 282 insertions(+), 195 deletions(-) create mode 100644 birb/core/assets.lua diff --git a/birb/core/assets.lua b/birb/core/assets.lua new file mode 100644 index 0000000..291dae5 --- /dev/null +++ b/birb/core/assets.lua @@ -0,0 +1,97 @@ +-- core/assets :: a simple assets manager, aim to put every assets in a simple +-- serie of table in order to find them easily. + +--[[ + 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 AssetManager = Object:extend() + +function AssetManager:new() + self.locals = {} + self.globals = {} + self.updatables = {} + + self.isActive = true +end + +function AssetManager:update(dt) + if (self.isActive) then + for key, updatable in pairs(self.updatables) do + updatable:update(dt) + end + end +end + +function AssetManager:add(name, asset, isGlobal) + if (isGlobal == true) then + self:addGlobal(name, asset) + else + self:addLocal(name, asset) + end +end + +function AssetManager:addGlobal(name, asset) + self.globals[name] = asset +end + +function AssetManager:addLocal(name, asset) + self.locals[name] = asset +end + +function AssetManager:clear() + self.locals = {} + self.globals = {} + collectgarbage() +end + +function AssetManager:clearLocal() + self.locals = {} +end + +function AssetManager:get(name) + if self.locals[name] ~= nil then + return self.locals[name] + end + return self.globals[name] +end + +-- Specific functions + +function AssetManager:playSFX(name) + local asset = self:get(name) + asset:play() +end + +-- Activity Functions + +function AssetManager:setActivity(isActive) + self.isActive = isActive +end + +function AssetManager:switchActivity() + self.isActive = (self.isActive == false) +end + +function AssetManager:getActivity() + return self.isActive +end + +return AssetManager \ No newline at end of file diff --git a/birb/core/init.lua b/birb/core/init.lua index 8f374bb..e0d69e8 100644 --- a/birb/core/init.lua +++ b/birb/core/init.lua @@ -34,6 +34,7 @@ local Screen = require(cwd .. "screen") local Lang = require(cwd .. "lang") local SceneManager = require(cwd .. "scenemanager") local MusicManager = require(cwd .. "music") +local Assets = require(cwd .. "assets") -- INIT FUNCTIONS -- Initialize and configure the core object @@ -51,6 +52,7 @@ function CoreSystem:new(debugLevel) self.scenemanager = SceneManager(self) self.lang = Lang(self) self.music = MusicManager(self) + self.assets = Assets(self) self.debug:logDebug("birbcore","Birb initialized") end @@ -106,6 +108,7 @@ function CoreSystem:update(dt) self.input:update(dt) self.screen:update(dt) self.music:update(dt) + self.assets:update(dt) if (self.game ~= nil) then self.game:update(dt) diff --git a/birb/core/scenemanager.lua b/birb/core/scenemanager.lua index 69e4878..5cdc189 100644 --- a/birb/core/scenemanager.lua +++ b/birb/core/scenemanager.lua @@ -75,7 +75,6 @@ function SceneManager:update(dt) if (self.currentScene ~= nil) then self.currentScene:updateStart(dt) self.currentScene:setKeys() - self.currentScene.assets:update(dt) self.currentScene.menusystem:update(dt) self.currentScene:updateWorld(dt) self.currentScene:update(dt) diff --git a/birb/modules/assets/init.lua b/birb/modules/assets/init.lua index b94b5a7..9a116f0 100644 --- a/birb/modules/assets/init.lua +++ b/birb/modules/assets/init.lua @@ -1,5 +1,5 @@ --- modules/assets :: a simple assets manager, aim to put every assets in a simple --- serie of table in order to find them easily. +-- modules/assets/import :: a simple assets importer, to import easily everything into +-- the asset manager. --[[ Copyright © 2019 Kazhnuz @@ -41,252 +41,236 @@ local SFX = require(cwd .. "sfx") -- INIT FUNCTIONS -- Initilizing and configuring option -function Assets:new() - self:clear() - - self.isActive = true +function Assets:new(isGlobal) + self.isGlobal = isGlobal end function Assets:clear() - -- TODO: destroy individually each texture/image when assets are cleared - self:clearSprites() - self:clearSFX() - self:clearFonts() - self:resetMusic() - self:clearBackgrounds() - self:clearFonts() - self:clearTileset() - - self:clearImages() + if (self.isGlobal) then + core.assets:clear() + else + core.assets:clearLocal() + end end -function Assets:update(dt) - if (self.isActive) then - self:animationsUpdate(dt) - end +-- WRAPPER FUNCTIONS +-- Basic wrappers to ensure compatibility + +function Assets:get(key) + return core.assets:get(key) +end + +function Assets:getFont(key) + return self:getWithType(key, "font") +end + +function Assets:getWithType(key, type) + return core.assets:get(key) +end + +function Assets:draw(name, x, y, r, sx, sy, ox, oy, kx, ky) + core.assets:draw(name, x, y, r, sx, sy, ox, oy, kx, ky) +end + +function Assets:newSFX(name, filepath) + self:addSFX(name, filepath) +end + +function Assets:addImage(name, filename) + self:addTexture(name, filename) +end + +function Assets:playSFX(name) + core.assets:playSFX(name) +end + +function Assets:drawImage(name, x, y, r, sx, sy, ox, oy, kx, ky) + self:draw(name, x, y, r, sx, sy, ox, oy, kx, ky) +end + +-- Music + +function Assets:setMusic(filename, loop) + core.debug:logDebug("assets", "Assets:setMusic is deprecated") + core.music:addMusic(filename, true) +end + +function Assets:silence() + core.debug:logDebug("assets", "Assets:silence is deprecated") + core.music:silence() +end + +function Assets:resetMusic() + core.debug:logDebug("assets", "Assets:resetMusic is deprecated") + core.music:purge() +end + +function Assets:playMusic() + core.debug:logDebug("assets", "Assets:playMusic is deprecated") + core.music:playMusic() +end + +-- Activity + +function Assets:setActivity(activity) + core.assets:setActivity(activity) +end + +function Assets:switchActivity() + core.assets:switchActivity() +end + +function Assets:getActivity() + core.assets:getActivity() end -- IMPORT FUNCTIONS -- Easilly import assets function Assets:batchImport(datafile) - local datas = require(datafile) + local datas = require(datafile) - for asset_type, assets in pairs(datas) do - if (asset_type == "autotiles") then - self:importAutotiles(assets) - elseif (asset_type == "backgrounds") then - self:importBackgrounds(assets) - elseif (asset_type == "fonts") then - self:importFonts(assets) - elseif (asset_type == "imagefonts") then - self:importImageFonts(assets) - elseif (asset_type == "images") then - self:importTextures(assets) - elseif (asset_type == "sprites") then - self:importSprites(assets) - elseif (asset_type == "textures") then - self:importTextures(assets) - elseif (asset_type == "tilesets") then - self:importTilesets(assets) - elseif (asset_type == "sfx") then - self:importSFX(assets) - else - core.debug:logWarn("assets/importer", "unkown asset type " .. asset_type) + for asset_type, assets in pairs(datas) do + if (asset_type == "autotiles") then + self:importAutotiles(assets) + elseif (asset_type == "backgrounds") then + self:importBackgrounds(assets) + elseif (asset_type == "fonts") then + self:importFonts(assets) + elseif (asset_type == "imagefonts") then + self:importImageFonts(assets) + elseif (asset_type == "images") then + self:importTextures(assets) + elseif (asset_type == "sprites") then + self:importSprites(assets) + elseif (asset_type == "textures") then + self:importTextures(assets) + elseif (asset_type == "tilesets") then + self:importTilesets(assets) + elseif (asset_type == "sfx") then + self:importSFX(assets) + else + core.debug:logWarn("assets/importer", "unkown asset type " .. asset_type) + end end - end end function Assets:importAutotiles(assets) - for i, asset in ipairs(assets) do - self:addAutotile(asset[1], asset[2]) - end + for i, asset in ipairs(assets) do + self:addAutotile(asset[1], asset[2]) + end end function Assets:importBackgrounds(assets) - for i, asset in ipairs(assets) do - self:addBackground(asset[1], asset[2]) - end + for i, asset in ipairs(assets) do + self:addBackground(asset[1], asset[2]) + end end function Assets:importFonts(assets) - for i, asset in ipairs(assets) do - self:addFont(asset[1], asset[2], asset[3]) - end + for i, asset in ipairs(assets) do + self:addFont(asset[1], asset[2], asset[3]) + end end function Assets:importImageFonts(assets) - for i, asset in ipairs(assets) do - self:addImageFont(asset[1], asset[2], asset[3]) - end + for i, asset in ipairs(assets) do + self:addImageFont(asset[1], asset[2], asset[3]) + end end function Assets:importSprites(assets) - for i, asset in ipairs(assets) do - self:addSprite(asset[1], asset[2]) - end + for i, asset in ipairs(assets) do + self:addSprite(asset[1], asset[2]) + end end function Assets:importTextures(assets) - for i, asset in ipairs(assets) do - self:addImage(asset[1], asset[2]) - end + for i, asset in ipairs(assets) do + self:addImage(asset[1], asset[2]) + end end function Assets:importTilesets(assets) - for i, asset in ipairs(assets) do - self:addTileset(asset[1], asset[2]) - end + for i, asset in ipairs(assets) do + self:addTileset(asset[1], asset[2]) + end end function Assets:importSFX(assets) - for i, asset in ipairs(assets) do - self:addSFX(asset[1], asset[2]) - end + for i, asset in ipairs(assets) do + self:addSFX(asset[1], asset[2]) + end end --- SFX & MUSICS --- Handle sound effects and musics +-- ADD FUNCTIONS +-- Different wrapper to create easily asset objects -function Assets:addSFX(name, filepath) - self:newSFX(name, filepath) +function Assets:add(name, assetObject) + core.assets:add(name, assetObject, self.isGlobal) end -function Assets:newSFX(name, filepath) - self.sfx[name] = SFX(filepath) -end - -function Assets:clearSFX() - love.audio.stop( ) - self.sfx = {} -end - -function Assets:playSFX(filename) - if not (self.sfx[filename] == nil) then - self.sfx[filename]:play() - end -end - -function Assets:setMusic(filename, loop) - core.debug:logDebug("assets", "Assets:setMusic is deprecated") - core.music:addMusic(filename, true) -end - -function Assets:silence() - core.debug:logDebug("assets", "Assets:silence is deprecated") - core.music:silence() -end - -function Assets:resetMusic() - core.debug:logDebug("assets", "Assets:resetMusic is deprecated") - core.music:purge() -end - -function Assets:playMusic() - core.debug:logDebug("assets", "Assets:playMusic is deprecated") - core.music:playMusic() -end - --- IMAGES FUNCTIONS --- Create directly texture items - -function Assets:addImage(name, filename) - self.images[name] = Texture(filename) -end - -function Assets:drawImage(name, x, y, r, sx, sy, ox, oy, kx, ky) - self.images[name]:draw(x, y, r, sx, sy, ox, oy, kx, ky) -end - -function Assets:clearImages() - self.images = {} -end - --- BACKGROUNDS FUNCTIONS --- Automatic tiling texture - function Assets:addBackground(name, filepath) - -- TODO: rework entirely background to work at any size - self.backgrounds[name] = Background(filepath) + self:add(name, Background(filepath)) end -function Assets:clearBackgrounds() - self.backgrounds = {} -end - --- SPRITES FUNCTIONS --- Animated tileset - function Assets:addSprite(name, filepath) - self.sprites[name] = Sprite(filepath) + self:add(name, Sprite(filepath)) end -function Assets:animationsUpdate(dt) - for i,v in pairs(self.sprites) do - v:update(dt) - end -end - -function Assets:clearSprites() - self.sprites = {} -end - --- FONTS FUNCTIONS --- Handles fonts and imagesfonts - function Assets:addFont(key, filename, size) - local font = Font(filename, size) - self.fonts[key] = font + self:add(key, Font(filename, size)) end function Assets:addImageFont(key, filename, extraspacing) - local font = ImageFont(filename, extraspacing) - self.fonts[key] = font + self:add(key, ImageFont(filename, extraspacing)) end -function Assets:getFont(filename) - return self.fonts[filename] -end - -function Assets:clearFonts() - self.fonts = {} -end - --- TILESET FUNCTIONS --- Automatically create quads for a texture - function Assets:addTileset(name, filepath) - self.tileset[name] = Tileset(filepath) + self:add(name, Tileset(filepath)) +end + +function Assets:addAutotile(name, tilesize) + self:add(name, Autotile(name, tilesize)) +end + +function Assets:addSFX(name, filepath) + self:add(name, SFX(filepath)) +end + +function Assets:addTexture(name, filename) + self:add(name, Texture(filename)) +end + +-- DEPRECATED FUNCTIONS +-- Don't do anything and will be removed soon + +function Assets:clearFonts() + core.debug:logDebug("assets", "Assets:clearFonts is deprecated") end function Assets:clearTileset() - self.tileset = {} -end - --- AUTOTILE FUNCTIONS --- Automatically draw tiles - -function Assets:addAutotile(name, tilesize) - self.autotile[name] = Autotile(name, tilesize) + core.debug:logDebug("assets", "Assets:clearTileset is deprecated") end function Assets:clearAutotile() - self.autotile = {} + core.debug:logDebug("assets", "Assets:clearAutotile is deprecated") end --- ACTIVITY FUNCTIONS --- Handle activity - -function Assets:setActivity(activity) - self.isActive = activity +function Assets:clearSFX() + core.debug:logDebug("assets", "Assets:clearSFX is deprecated") end -function Assets:switchActivity() - self.isActive = (self.isActive == false) +function Assets:clearBackgrounds() + core.debug:logDebug("assets", "Assets:clearBackgrounds is deprecated") end -function Assets:getActivity() - return self.isActive +function Assets:clearSprites() + core.debug:logDebug("assets", "Assets:clearSprites is deprecated") +end + +function Assets:clearImages() + core.debug:logDebug("assets", "Assets:clearImages is deprecated") end return Assets diff --git a/birb/modules/menusystem/parent.lua b/birb/modules/menusystem/parent.lua index bc6b3fd..050f0a8 100644 --- a/birb/modules/menusystem/parent.lua +++ b/birb/modules/menusystem/parent.lua @@ -257,7 +257,7 @@ function Menu:resetSound() end function Menu:setSoundFromSceneAssets(name) - self:setSound(self.menusystem.scene.assets.sfx[name]) + self:setSound(self.menusystem.scene.assets:getWithType(name, "sfx")) end function Menu:setSound(soundasset) diff --git a/birb/modules/world/actors/gfx2D.lua b/birb/modules/world/actors/gfx2D.lua index 666369f..e352310 100644 --- a/birb/modules/world/actors/gfx2D.lua +++ b/birb/modules/world/actors/gfx2D.lua @@ -26,7 +26,8 @@ local Actor2D = require(cwd .. "actor2D") local GFX = Actor2D:extend() function GFX:new(world, x, y, spritename) - local width, height = world.scene.assets.sprites[spritename]:getDimensions() + local baseSprite = world.scene.assets:getWithType(spritename, "sprite") + local width, height = baseSprite:getDimensions() GFX.super.new(self, world, "gfx", x - (width/2), y - (height/2), width, height) self:setSprite(spritename, true) diff --git a/birb/modules/world/actors/gfx3D.lua b/birb/modules/world/actors/gfx3D.lua index 868cdc4..fe271d4 100644 --- a/birb/modules/world/actors/gfx3D.lua +++ b/birb/modules/world/actors/gfx3D.lua @@ -26,7 +26,8 @@ local Actor3D = require(cwd .. "actor3D") local GFX = Actor3D:extend() function GFX:new(world, x, y, z, spritename) - local width, height = world.scene.assets.sprites[spritename]:getDimensions() + local baseSprite = world.scene.assets:getWithType(spritename, "sprite") + local width, height = baseSprite:getDimensions() GFX.super.new(self, world, "gfx", x - (width/2), y - (width/2), z - (height/2), width, width, height) self:setSprite(spritename, true) diff --git a/birb/modules/world/actors/utils/boxes/textured.lua b/birb/modules/world/actors/utils/boxes/textured.lua index 1b79162..df6de22 100644 --- a/birb/modules/world/actors/utils/boxes/textured.lua +++ b/birb/modules/world/actors/utils/boxes/textured.lua @@ -29,8 +29,8 @@ local TexturedBox = Box3D:extend() function TexturedBox:new(owner, w, h, d, topTexture, bottomTexture) local bottomTexture = bottomTexture or topTexture - self.topTexture = owner.assets.images[topTexture] - self.bottomTexture = owner.assets.images[bottomTexture] + self.topTexture = owner.assets:getWithType(topTexture, "texture") + self.bottomTexture = owner.assets:getWithType(bottomTexture, "texture") TexturedBox.super.new(self, owner, w, h, d) self.haveLine = false diff --git a/birb/modules/world/actors/utils/sprites.lua b/birb/modules/world/actors/utils/sprites.lua index d56db7f..bc11127 100644 --- a/birb/modules/world/actors/utils/sprites.lua +++ b/birb/modules/world/actors/utils/sprites.lua @@ -17,7 +17,8 @@ end function Sprite:clone() if self.name ~= nil then - self.spriteClone = self.assets.sprites[self.name]:clone() + local baseSprite = self.assets:getWithType(self.name, "sprite") + self.spriteClone = baseSprite:clone() self.spriteClone:setCallbackTarget(self.owner) end end @@ -110,7 +111,8 @@ function Sprite:draw(x, y, r, sx, sy, ox, oy, kx, ky) if (self.spriteClone ~= nil) then self.spriteClone:draw(x, y, r, sx, sy, ox, oy, kx, ky) else - self.assets.sprites[self.name]:drawAnimation(x, y, r, sx, sy, ox, oy, kx, ky) + local sprite = self.assets:getWithType(self.name, "sprite") + sprite:drawAnimation(x, y, r, sx, sy, ox, oy, kx, ky) end end end diff --git a/examples/scenes/gameplay/plateform/pause.lua b/examples/scenes/gameplay/plateform/pause.lua index e20f4a4..734e005 100644 --- a/examples/scenes/gameplay/plateform/pause.lua +++ b/examples/scenes/gameplay/plateform/pause.lua @@ -24,7 +24,7 @@ end function ResumeWidget:new(menu) self.scene = menu.scene - local font = self.scene.assets.fonts["medium"] + local font = self.scene.assets:getFont("medium") local label = "resume" ResumeWidget.super.new(self, menu, font, label) end @@ -36,7 +36,7 @@ end function RestartWidget:new(menu) self.scene = menu.scene - local font = self.scene.assets.fonts["medium"] + local font = self.scene.assets:getFont("medium") local label = "restart" RestartWidget.super.new(self, menu, font, label) end @@ -48,7 +48,7 @@ end function ExitWidget:new(menu) self.scene = menu.scene - local font = self.scene.assets.fonts["medium"] + local font = self.scene.assets:getFont("medium") local label = "exit" ExitWidget.super.new(self, menu, font, label) end diff --git a/examples/scenes/mainmenu/init.lua b/examples/scenes/mainmenu/init.lua index d23539b..68041d1 100644 --- a/examples/scenes/mainmenu/init.lua +++ b/examples/scenes/mainmenu/init.lua @@ -97,7 +97,7 @@ end function SubMenuWidget:new(scene, menu, newmenu, fullname, order) self.scene = scene local widgetmenu = self.scene.menusystem.menus[menu] - local font = self.scene.assets.fonts["medium"] + local font = self.scene.assets:getFont("medium") self.newmenu = newmenu local label = "" if fullname == "back" then @@ -122,7 +122,7 @@ function SceneWidget:new(scene, menu, newscene, fullname, args) self.scene = scene self.args = args local widgetmenu = self.scene.menusystem.menus[menu] - local font = self.scene.assets.fonts["medium"] + local font = self.scene.assets:getFont("medium") self.newscene = newscene local label = core.lang:translate("mainmenu", fullname) SceneWidget.super.new(self, widgetmenu, font, label) @@ -139,7 +139,7 @@ end function ExitWidget:new(scene, menu) self.scene = scene local widgetmenu = self.scene.menusystem.menus[menu] - local font = self.scene.assets.fonts["medium"] + local font = self.scene.assets:getFont("medium") local label = core.lang:translate("commons", "exit") SceneWidget.super.new(self, widgetmenu, font, label) end