update assets errors handling & add 'atlases' to preload

This commit is contained in:
MihailRis 2024-07-23 19:27:46 +03:00
parent ed60bdc333
commit f9df873382
7 changed files with 112 additions and 51 deletions

View File

@ -6,5 +6,17 @@
],
"models": [
"drop-item"
],
"shaders": [
"ui3d",
"entity",
"screen",
"background",
"skybox_gen"
],
"textures": [
"misc/moon",
"misc/sun",
"gui/crosshair"
]
}

View File

@ -1,13 +1,27 @@
{
"shaders": [
"ui3d",
"screen",
"background",
"skybox_gen"
"ui",
"main",
"lines"
],
"textures": [
"misc/moon",
"misc/sun",
"gui/crosshair"
"gui/menubg",
"gui/delete_icon",
"gui/no_icon",
"gui/no_world_icon",
"gui/warning",
"gui/error",
"gui/cross",
"gui/refresh"
],
"fonts": [
{
"name": "normal",
"path": "fonts/font"
}
],
"atlases": [
"blocks",
"items"
]
}

View File

@ -14,6 +14,16 @@
class Assets;
enum class AssetType {
TEXTURE,
SHADER,
FONT,
ATLAS,
LAYOUT,
SOUND,
MODEL
};
namespace assetload {
/// @brief final work to do in the main thread
using postfunc = std::function<void(Assets*)>;
@ -22,6 +32,32 @@ namespace assetload {
template<class T>
void assets_setup(const Assets*);
class error : public std::runtime_error {
AssetType type;
std::string filename;
std::string reason;
public:
error(
AssetType type, std::string filename, std::string reason
) : std::runtime_error(filename + ": " + reason),
type(type),
filename(std::move(filename)),
reason(std::move(reason)) {
}
AssetType getAssetType() const {
return type;
}
const std::string& getFilename() const {
return filename;
}
const std::string& getReason() const {
return reason;
}
};
}
class Assets {

View File

@ -56,7 +56,7 @@ aloader_func AssetsLoader::getLoader(AssetType tag) {
return found->second;
}
bool AssetsLoader::loadNext() {
void AssetsLoader::loadNext() {
const aloader_entry& entry = entries.front();
logger.info() << "loading " << entry.filename << " as " << entry.alias;
try {
@ -64,11 +64,13 @@ bool AssetsLoader::loadNext() {
auto postfunc = loader(this, paths, entry.filename, entry.alias, entry.config);
postfunc(assets);
entries.pop();
return true;
} catch (std::runtime_error& err) {
logger.error() << err.what();
auto type = entry.tag;
std::string filename = entry.filename;
std::string reason = err.what();
entries.pop();
return false;
throw assetload::error(type, std::move(filename), std::move(reason));
}
}
@ -154,6 +156,7 @@ void AssetsLoader::processPreloadList(AssetType tag, dynamic::List* list) {
void AssetsLoader::processPreloadConfig(const fs::path& file) {
auto root = files::read_json(file);
processPreloadList(AssetType::ATLAS, root->list("atlases").get());
processPreloadList(AssetType::FONT, root->list("fonts").get());
processPreloadList(AssetType::SHADER, root->list("shaders").get());
processPreloadList(AssetType::TEXTURE, root->list("textures").get());
@ -163,6 +166,13 @@ void AssetsLoader::processPreloadConfig(const fs::path& file) {
}
void AssetsLoader::processPreloadConfigs(const Content* content) {
auto preloadFile = paths->getMainRoot()/fs::path("preload.json");
if (fs::exists(preloadFile)) {
processPreloadConfig(preloadFile);
}
if (content == nullptr) {
return;
}
for (auto& entry : content->getPacks()) {
const auto& pack = entry.second;
auto preloadFile = pack->getInfo().folder / fs::path("preload.json");
@ -170,29 +180,11 @@ void AssetsLoader::processPreloadConfigs(const Content* content) {
processPreloadConfig(preloadFile);
}
}
auto preloadFile = paths->getMainRoot()/fs::path("preload.json");
if (fs::exists(preloadFile)) {
processPreloadConfig(preloadFile);
}
}
void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
loader.add(AssetType::FONT, FONTS_FOLDER+"/font", "normal");
loader.add(AssetType::SHADER, SHADERS_FOLDER+"/ui", "ui");
loader.add(AssetType::SHADER, SHADERS_FOLDER+"/main", "main");
loader.add(AssetType::SHADER, SHADERS_FOLDER+"/entity", "entity");
loader.add(AssetType::SHADER, SHADERS_FOLDER+"/lines", "lines");
loader.add(AssetType::TEXTURE, TEXTURES_FOLDER+"/gui/menubg", "gui/menubg");
loader.add(AssetType::TEXTURE, TEXTURES_FOLDER+"/gui/delete_icon", "gui/delete_icon");
loader.add(AssetType::TEXTURE, TEXTURES_FOLDER+"/gui/no_icon", "gui/no_icon");
loader.add(AssetType::TEXTURE, TEXTURES_FOLDER+"/gui/no_world_icon", "gui/no_world_icon");
loader.add(AssetType::TEXTURE, TEXTURES_FOLDER+"/gui/warning", "gui/warning");
loader.add(AssetType::TEXTURE, TEXTURES_FOLDER+"/gui/error", "gui/error");
loader.add(AssetType::TEXTURE, TEXTURES_FOLDER+"/gui/cross", "gui/cross");
loader.add(AssetType::TEXTURE, TEXTURES_FOLDER+"/gui/refresh", "gui/refresh");
loader.processPreloadConfigs(content);
if (content) {
loader.processPreloadConfigs(content);
for (auto& entry : content->getBlockMaterials()) {
auto& material = *entry.second;
loader.tryAddSound(material.stepsSound);
@ -218,8 +210,6 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
}
}
}
loader.add(AssetType::ATLAS, TEXTURES_FOLDER+"/blocks", "blocks");
loader.add(AssetType::ATLAS, TEXTURES_FOLDER+"/items", "items");
}
bool AssetsLoader::loadExternalTexture(

View File

@ -19,16 +19,6 @@ namespace dynamic {
class List;
}
enum class AssetType {
TEXTURE,
SHADER,
FONT,
ATLAS,
LAYOUT,
SOUND,
MODEL
};
class ResPaths;
class AssetsLoader;
class Content;
@ -50,7 +40,7 @@ struct SoundCfg : AssetCfg {
};
using aloader_func = std::function<assetload::postfunc(
AssetsLoader*, // redundant?
AssetsLoader*,
const ResPaths*,
const std::string&,
const std::string&,
@ -93,7 +83,9 @@ public:
);
bool hasNext() const;
bool loadNext();
/// @throws assetload::error
void loadNext();
std::shared_ptr<Task> startTask(runnable onDone);

View File

@ -256,11 +256,13 @@ void Engine::loadAssets() {
auto task = loader.startTask([=](){});
task->waitForEnd();
} else {
while (loader.hasNext()) {
if (!loader.loadNext()) {
new_assets.reset();
throw std::runtime_error("could not to load assets");
try {
while (loader.hasNext()) {
loader.loadNext();
}
} catch (const assetload::error& err) {
new_assets.reset();
throw;
}
}
assets = std::move(new_assets);

View File

@ -84,6 +84,7 @@ static void show_content_missing(
}
static bool loadWorldContent(Engine* engine, const fs::path& folder) {
// TODO: combine errors handling with newWorld
try {
engine->loadWorldContent(folder);
return true;
@ -95,10 +96,17 @@ static bool loadWorldContent(Engine* engine, const fs::path& folder) {
util::str2wstr_utf8(error.getPackId())
);
return false;
} catch (const assetload::error& error) {
engine->setScreen(std::make_shared<MenuScreen>(engine));
guiutil::alert(
engine->getGUI(), langs::get(L"Assets Load Error", L"menu")+L":\n"+
util::str2wstr_utf8(error.what())
);
return false;
} catch (const std::runtime_error& error) {
engine->setScreen(std::make_shared<MenuScreen>(engine));
guiutil::alert(
engine->getGUI(), langs::get(L"Content Error", L"menu")+L": "+
engine->getGUI(), langs::get(L"Content Error", L"menu")+L":\n"+
util::str2wstr_utf8(error.what())
);
return false;
@ -189,11 +197,18 @@ void EngineController::createWorld(
)
);
return;
} catch (const std::runtime_error& error) {
} catch (const assetload::error& error) {
guiutil::alert(
engine->getGUI(),
langs::get(L"Content Error", L"menu")+
L": "+util::str2wstr_utf8(error.what())
langs::get(L"Assets Loading Error", L"menu")+
L":\n"+util::str2wstr_utf8(error.what())
);
return;
} catch (const std::runtime_error& error) {
engine->setScreen(std::make_shared<MenuScreen>(engine));
guiutil::alert(
engine->getGUI(), langs::get(L"Content Error", L"menu")+L":\n"+
util::str2wstr_utf8(error.what())
);
return;
}