From 0cf7d9b1ed6d02e2e7a3ec8c035eb055ebb2b77c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 23 Jan 2026 22:40:57 +0300 Subject: [PATCH] add background assets loader --- src/assets/AssetsLoader.cpp | 30 +++++++++------ src/assets/AssetsLoader.hpp | 3 +- src/engine/AssetsManagement.cpp | 47 +++++++++++++++++++---- src/engine/AssetsManagement.hpp | 13 ++++++- src/engine/Engine.cpp | 40 ++++++++++--------- src/engine/Engine.hpp | 3 ++ src/engine/EnginePaths.cpp | 3 ++ src/logic/scripting/lua/libs/libpack.cpp | 4 +- src/logic/scripting/lua/libs/libworld.cpp | 7 ++-- 9 files changed, 104 insertions(+), 46 deletions(-) diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index cf64a9c8e..ca9ee93df 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -319,28 +319,27 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) { } bool AssetsLoader::loadExternalTexture( - Assets* assets, + AssetsLoader& loader, const std::string& name, const std::vector& alternatives ) { - if (assets->get(name) != nullptr) { + if (loader.getAssets().get(name) != nullptr) { return true; } for (auto& path : alternatives) { - if (io::exists(path)) { - try { - auto image = imageio::read(path); - assets->store(Texture::from(image.get()), name); - return true; - } catch (const std::exception& err) { - logger.error() << "error while loading external " - << path.string() << ": " << err.what(); - } + logger.info() << (path.string() + ".png"); + if (io::exists(path.string() + ".png")) { + loader.add(AssetType::TEXTURE, path.string(), name, nullptr); + return true; // TODO: fallbacks support } } return false; } +Assets& AssetsLoader::getAssets() { + return assets; +} + Engine& AssetsLoader::getEngine() { return engine; } @@ -376,6 +375,15 @@ std::shared_ptr AssetsLoader::startTask(runnable onDone) { [this](const assetload::postfunc& func) { func(&assets); } ); pool->setOnComplete(std::move(onDone)); + pool->setJobsSource([this]() -> std::optional { + if (entries.empty()) { + return std::nullopt; + } + aloader_entry entry = std::move(entries.front()); + entries.pop(); + return entry; + }); + while (!entries.empty()) { aloader_entry entry = std::move(entries.front()); entries.pop(); diff --git a/src/assets/AssetsLoader.hpp b/src/assets/AssetsLoader.hpp index 78152b6ac..c34eb822d 100644 --- a/src/assets/AssetsLoader.hpp +++ b/src/assets/AssetsLoader.hpp @@ -124,10 +124,11 @@ public: static void addDefaults(AssetsLoader& loader, const Content* content); static bool loadExternalTexture( - Assets* assets, + AssetsLoader& loader, const std::string& name, const std::vector& alternatives ); + Assets& getAssets(); Engine& getEngine(); }; diff --git a/src/engine/AssetsManagement.cpp b/src/engine/AssetsManagement.cpp index 2135f568f..55bfb9401 100644 --- a/src/engine/AssetsManagement.cpp +++ b/src/engine/AssetsManagement.cpp @@ -1,13 +1,12 @@ #include "AssetsManagement.hpp" -#include "assets/Assets.hpp" #include "assets/AssetsLoader.hpp" -#include "engine/Engine.hpp" -#include "debug/Logger.hpp" -#include "content/Content.hpp" -#include "graphics/core/Shader.hpp" -#include "EnginePaths.hpp" #include "coders/GLSLExtension.hpp" +#include "content/Content.hpp" +#include "debug/Logger.hpp" +#include "engine/Engine.hpp" +#include "EnginePaths.hpp" +#include "graphics/core/Shader.hpp" #include "graphics/render/ModelsGenerator.hpp" #include "graphics/ui/GUI.hpp" @@ -15,6 +14,10 @@ static debug::Logger logger("assets-management"); AssetsManagement::AssetsManagement(Engine& engine) : engine(engine) {} +AssetsManagement::~AssetsManagement() { + finishBackgroundLoader(); +} + const Assets* AssetsManagement::getStorage() const { return assets.get(); } @@ -23,7 +26,23 @@ Assets* AssetsManagement::getStorage() { return assets.get(); } +AssetsLoader& AssetsManagement::acquireBackgroundLoader() { + if (backgroundLoader) { + return *backgroundLoader; + } + if (assets == nullptr) { + throw std::runtime_error("no assets storage available"); + } + backgroundLoader = std::make_unique( + engine, *assets, engine.getResPaths() + ); + backgroundLoaderTask = backgroundLoader->startTask(nullptr); + return *backgroundLoader; +} + void AssetsManagement::loadAssets(Content* content) { + finishBackgroundLoader(); + const auto& paths = engine.getPaths(); logger.info() << "loading assets"; Shader::preprocessor->setPaths(&paths.resPaths); @@ -34,7 +53,7 @@ void AssetsManagement::loadAssets(Content* content) { // no need // correct log messages order is more useful - // todo: before setting to true, check if GLSLExtension thread safe + // todo: before setting to true, check if GLSLExtension thread safe bool threading = false; // look at three upper lines if (threading) { auto task = loader.startTask([=](){}); @@ -51,3 +70,17 @@ void AssetsManagement::loadAssets(Content* content) { assets->setup(); engine.getGUI().onAssetsLoad(assets.get()); } + +void AssetsManagement::update() { + if (backgroundLoaderTask) { + backgroundLoaderTask->update(); + } +} + +void AssetsManagement::finishBackgroundLoader() { + if (backgroundLoaderTask == nullptr) { + return; + } + backgroundLoaderTask.reset(); + backgroundLoader.reset(); +} diff --git a/src/engine/AssetsManagement.hpp b/src/engine/AssetsManagement.hpp index 5b06e6d8c..f88bc281a 100644 --- a/src/engine/AssetsManagement.hpp +++ b/src/engine/AssetsManagement.hpp @@ -1,22 +1,31 @@ #pragma once +#include "assets/Assets.hpp" + #include -class Assets; class AssetsLoader; class Engine; class Content; +class Task; -class AssetsManagement { +class AssetsManagement final { public: AssetsManagement(Engine& engine); + ~AssetsManagement(); void loadAssets(Content* content); + void update(); Assets* getStorage(); const Assets* getStorage() const; + + AssetsLoader& acquireBackgroundLoader(); private: + void finishBackgroundLoader(); + Engine& engine; std::unique_ptr assets; std::unique_ptr backgroundLoader; + std::shared_ptr backgroundLoaderTask; }; diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index 6cc976799..9afe0824a 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -4,48 +4,45 @@ #define GLEW_STATIC #endif -#include "debug/Logger.hpp" -#include "assets/AssetsLoader.hpp" +#include "AssetsManagement.hpp" #include "audio/audio.hpp" +#include "coders/commons.hpp" #include "coders/GLSLExtension.hpp" #include "coders/toml.hpp" -#include "coders/commons.hpp" -#include "devtools/Editor.hpp" -#include "devtools/Project.hpp" -#include "devtools/DebuggingServer.hpp" #include "content/ContentControl.hpp" #include "core_defs.hpp" -#include "io/io.hpp" -#include "io/settings_io.hpp" +#include "debug/Logger.hpp" +#include "devtools/DebuggingServer.hpp" +#include "devtools/Editor.hpp" +#include "devtools/Project.hpp" +#include "EnginePaths.hpp" #include "frontend/locale.hpp" #include "frontend/menu.hpp" #include "frontend/screens/Screen.hpp" -#include "graphics/render/ModelsGenerator.hpp" #include "graphics/core/DrawContext.hpp" #include "graphics/core/Shader.hpp" -#include "graphics/ui/GUI.hpp" #include "graphics/ui/elements/Menu.hpp" -#include "logic/EngineController.hpp" +#include "graphics/ui/GUI.hpp" +#include "io/io.hpp" +#include "io/settings_io.hpp" #include "logic/CommandsInterpreter.hpp" -#include "logic/scripting/scripting.hpp" +#include "logic/EngineController.hpp" #include "logic/scripting/scripting_hud.hpp" +#include "logic/scripting/scripting.hpp" +#include "Mainloop.hpp" #include "network/Network.hpp" +#include "ServerMainloop.hpp" #include "util/platform.hpp" +#include "util/stringutil.hpp" #include "window/input.hpp" #include "window/Window.hpp" -#include "world/Level.hpp" -#include "AssetsManagement.hpp" -#include "Mainloop.hpp" -#include "ServerMainloop.hpp" #include "WindowControl.hpp" -#include "EnginePaths.hpp" +#include "world/Level.hpp" -#include #include #include #include #include -#include static debug::Logger logger("engine"); @@ -266,6 +263,7 @@ void Engine::applicationTick() { void Engine::updateFrontend() { double delta = time.getDelta(); + assets->update(); updateHotkeys(); audio::update(delta); gui->act(delta, window->getSize()); @@ -421,6 +419,10 @@ Assets* Engine::getAssets() { return assets->getStorage(); } +AssetsLoader& Engine::acquireBackgroundLoader() { + return assets->acquireBackgroundLoader(); +} + EnginePaths& Engine::getPaths() { return *paths; } diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index 7ecff05c6..4f4e68280 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -10,6 +10,7 @@ #include class Assets; +class AssetsLoader; class AssetsManagement; class ContentControl; class EngineController; @@ -110,6 +111,8 @@ public: /// @brief Get active assets storage instance Assets* getAssets(); + AssetsLoader& acquireBackgroundLoader(); + /// @brief Get writeable engine settings structure instance EngineSettings& getSettings(); diff --git a/src/engine/EnginePaths.cpp b/src/engine/EnginePaths.cpp index 7cb71079c..c61d27f89 100644 --- a/src/engine/EnginePaths.cpp +++ b/src/engine/EnginePaths.cpp @@ -274,6 +274,9 @@ ResPaths::ResPaths(std::vector roots) } io::path ResPaths::find(const std::string& filename) const { + if (filename.find(':') != std::string::npos) { + return filename; + } for (int i = roots.size() - 1; i >= 0; i--) { auto& root = roots[i]; auto file = root.path / filename; diff --git a/src/logic/scripting/lua/libs/libpack.cpp b/src/logic/scripting/lua/libs/libpack.cpp index b7162b4d0..66fa86426 100644 --- a/src/logic/scripting/lua/libs/libpack.cpp +++ b/src/logic/scripting/lua/libs/libpack.cpp @@ -87,10 +87,10 @@ static int l_pack_get_info( lua::setfield(L, "path"); if (!engine->isHeadless()) { - auto assets = engine->getAssets(); + auto& assetsLoader = engine->acquireBackgroundLoader(); std::string icon = pack.id + ".icon"; if (!AssetsLoader::loadExternalTexture( - assets, icon, {pack.folder / "icon.png"} + assetsLoader, icon, {pack.folder / "icon"} )) { icon = "gui/no_icon"; } diff --git a/src/logic/scripting/lua/libs/libworld.cpp b/src/logic/scripting/lua/libs/libworld.cpp index 9b28c719f..a9567ea97 100644 --- a/src/logic/scripting/lua/libs/libworld.cpp +++ b/src/logic/scripting/lua/libs/libworld.cpp @@ -56,13 +56,12 @@ static int l_get_list(lua::State* L) { lua::pushstring(L, name); lua::setfield(L, "name"); - auto assets = engine->getAssets(); std::string icon = "world#" + name + ".icon"; if (!engine->isHeadless() && !AssetsLoader::loadExternalTexture( - assets, + engine->acquireBackgroundLoader(), icon, - {worlds[i] / "icon.png", - worlds[i] / "preview.png"} + {worlds[i] / "icon", + worlds[i] / "preview"} )) { icon = "gui/no_world_icon"; }