diff --git a/depends.txt b/depends.txt index 112bf8c2..b60a7a40 100644 --- a/depends.txt +++ b/depends.txt @@ -1,2 +1,3 @@ sqlite3 opengl +nlohmann/json \ No newline at end of file diff --git a/include/asset_loader.h b/include/asset_loader.h index eabc6ef5..4e77cbad 100644 --- a/include/asset_loader.h +++ b/include/asset_loader.h @@ -30,7 +30,6 @@ class load_failure_t public: enum type_t { - ASSETS_ALREADY_LOADED, ASSET_FOLDER_NOT_FOUND, MODEL_FOLDER_NOT_FOUND, TEXTURE_FOLDER_NOT_FOUND, @@ -73,6 +72,11 @@ struct namespaced_object { std::string namespace_str; std::string key_str; + + [[nodiscard]] std::string string() const + { + return namespace_str + ':' + key_str; + } }; struct model_data_t @@ -86,34 +90,32 @@ struct namespace_data_t blt::hashmap_t models; }; -struct assets_data_t +struct asset_data_t { - database_t db; - std::string asset_folder; - std::optional data_folder; - std::string name; + blt::hashmap_t json_data; + blt::hashmap_t solid_textures_to_load; + blt::hashmap_t non_solid_textures_to_load; - assets_data_t(database_t&& db, std::string asset_folder, std::optional data_folder, std::string name) : db{std::move(db)}, - asset_folder{ - std::move(asset_folder) - }, - data_folder{ - std::move(data_folder) - }, name{std::move(name)} - {} + blt::hashmap_t namespace_asset_folders; + blt::hashmap_t namespace_data_folders; + blt::hashmap_t namespace_texture_folders; + + [[nodiscard]] std::vector resolve_parents(const namespaced_object& model) const; }; class asset_loader_t { public: - asset_loader_t(std::string folder, std::string name, std::optional data_folder = std::nullopt); + explicit asset_loader_t(std::string name); - blt::expected load_assets(); + std::optional load_assets(const std::string& asset_folder, const std::optional& data_folder = {}); + + asset_data_t& load_textures(); private: - // feels like a weird hack? - bool contains = true; - assets_data_t data; + asset_data_t data; + database_t db; + std::string name; }; #endif //ASSET_LOADER_H diff --git a/include/sql.h b/include/sql.h index e7c5a80d..92d52a37 100644 --- a/include/sql.h +++ b/include/sql.h @@ -250,6 +250,13 @@ public: return *this; } + table_column_builder_t& auto_increment() + { + primary_key(); + attributes.push_back("AUTOINCREMENT"); + return *this; + } + table_column_builder_t& unique() { attributes.emplace_back("UNIQUE"); diff --git a/src/asset_loader.cpp b/src/asset_loader.cpp index 1c8ec76f..5c697fed 100644 --- a/src/asset_loader.cpp +++ b/src/asset_loader.cpp @@ -20,39 +20,30 @@ #include #include #include +#include #include #include #include #include + using json = nlohmann::json; -asset_loader_t::asset_loader_t(std::string asset_folder, std::string name, std::optional data_folder): data{ - database_t{name + ".assets"}, std::move(asset_folder), std::move(data_folder), std::move(name) -} +inline namespaced_object empty_object{"NULL", "NULL"}; + +asset_loader_t::asset_loader_t(std::string name): + db{name + ".assets"}, name{std::move(name)} {} -blt::expected asset_loader_t::load_assets() +std::optional asset_loader_t::load_assets(const std::string& asset_folder, const std::optional& data_folder) { - if (!contains) - return blt::unexpected(load_failure_t::ASSETS_ALREADY_LOADED); - if (!std::filesystem::exists(data.asset_folder)) - return blt::unexpected(load_failure_t::ASSET_FOLDER_NOT_FOUND); - - /* - * Tables - */ - auto texture_table = data.db.builder().create_table("textures"); - texture_table.with_column("name").primary_key(); - texture_table.with_column("width").not_null(); - texture_table.with_column("height").not_null(); - texture_table.with_column("data").not_null(); - texture_table.build().execute(); + if (!std::filesystem::exists(asset_folder)) + return load_failure_t::ASSET_FOLDER_NOT_FOUND; std::optional model_folder; std::optional texture_folder; std::optional tags_folder; - for (const auto& entry : std::filesystem::recursive_directory_iterator(data.asset_folder)) + for (const auto& entry : std::filesystem::recursive_directory_iterator(asset_folder)) { if (!entry.is_directory()) continue; @@ -67,22 +58,22 @@ blt::expected asset_loader_t::load_assets() } if (!model_folder) - return blt::unexpected(load_failure_t::MODEL_FOLDER_NOT_FOUND); + return load_failure_t::MODEL_FOLDER_NOT_FOUND; if (!texture_folder) - return blt::unexpected(load_failure_t::TEXTURE_FOLDER_NOT_FOUND); + return load_failure_t::TEXTURE_FOLDER_NOT_FOUND; if (!exists(*model_folder / "block")) - return blt::unexpected(load_failure_t::MODEL_FOLDER_NOT_FOUND); + return load_failure_t::MODEL_FOLDER_NOT_FOUND; if (!exists(*texture_folder / "block")) - return blt::unexpected(load_failure_t::TEXTURE_FOLDER_NOT_FOUND); + return load_failure_t::TEXTURE_FOLDER_NOT_FOUND; const auto namespace_name = model_folder->parent_path().filename(); - if (data.data_folder) + if (data_folder) { - for (const auto& entry : std::filesystem::recursive_directory_iterator(*data.data_folder)) + for (const auto& entry : std::filesystem::recursive_directory_iterator(*data_folder)) { if (!entry.is_directory()) continue; @@ -94,19 +85,25 @@ blt::expected asset_loader_t::load_assets() } } - if (data.data_folder && !tags_folder) - return blt::unexpected(load_failure_t::TAGS_FOLDER_NOT_FOUND); + if (data_folder && !tags_folder) + return load_failure_t::TAGS_FOLDER_NOT_FOUND; - if (data.data_folder && !exists(*tags_folder / "block")) - return blt::unexpected(load_failure_t::TAGS_FOLDER_NOT_FOUND); + if (data_folder && !exists(*tags_folder / "block")) + return load_failure_t::TAGS_FOLDER_NOT_FOUND; - BLT_INFO("Loading assets '{}' for namespace '{}'", data.name, namespace_name.string()); + if (data_folder) + data.namespace_data_folders[namespace_name] = data_folder->parent_path().string(); + + data.namespace_asset_folders[namespace_name] = model_folder->parent_path().string(); + data.namespace_texture_folders[namespace_name] = texture_folder->string(); + + BLT_INFO("Loading assets '{}' for namespace '{}'", name, namespace_name.string()); if (texture_folder->parent_path().filename() != namespace_name) - return blt::unexpected(load_failure_t::INCORRECT_NAMESPACE); + return load_failure_t::INCORRECT_NAMESPACE; - blt::hashmap_t namespaced_models; + blt::hashmap_t& namespaced_models = data.json_data; - for (auto entry : std::filesystem::recursive_directory_iterator(*model_folder / "block")) + for (const auto& entry : std::filesystem::recursive_directory_iterator(*model_folder / "block")) { if (!entry.path().has_extension()) continue; @@ -162,10 +159,77 @@ blt::expected asset_loader_t::load_assets() if (!namespaced_models.contains(namespace_name.string())) namespaced_models[namespace_name.string()] = {}; namespaced_models[namespace_name.string()].models.insert({ - relative_path.string(), model_data_t{parent, textures.empty() ? std::nullopt : std::move(textures)} + relative_path.string(), + model_data_t{parent, textures.empty() ? std::optional>{} : std::optional{std::move(textures)}} }); } - contains = false; - return std::move(data); + auto& map = data.json_data[namespace_name.string()]; + + std::vector textures_to_load; + + for (auto& [name, model] : map.models) + { + auto parents = data.resolve_parents(model.parent.value_or(empty_object)); + bool solid = false; + for (const auto& [namespace_str, key_str] : parents) + { + if (namespace_str == "minecraft" && key_str == "block/cube") + { + if (model.textures) + { + for (auto& texture : *model.textures) + data.solid_textures_to_load[texture.namespace_str] = texture.key_str; + } + solid = true; + break; + } + } + if (!solid) + { + if (model.textures) + { + for (auto& texture : *model.textures) + data.non_solid_textures_to_load[texture.namespace_str] = texture.key_str; + } + } + } + + return {}; +} + +asset_data_t& asset_loader_t::load_textures() +{ + auto texture_table = db.builder().create_table("solid_textures"); + texture_table.with_column("namespace").primary_key(); + texture_table.with_column("name").primary_key(); + texture_table.with_column("width").not_null(); + texture_table.with_column("height").not_null(); + texture_table.with_column("data").not_null(); + texture_table.build().execute(); + + for (const auto& [namespace_str, texture] : data.solid_textures_to_load) + { + auto texture_path = std::filesystem::path(data.namespace_texture_folders.at(namespace_str)); + texture_path /= texture; + + } + + return data; +} + +std::vector asset_data_t::resolve_parents(const namespaced_object& model) const +{ + std::vector parents; + auto current_parent = model; + while (json_data.contains(current_parent.namespace_str) && json_data.at(current_parent.namespace_str).models.contains(current_parent.key_str)) + { + const auto& [parent, textures] = json_data.at(current_parent.namespace_str).models.at(current_parent.key_str); + parents.push_back(current_parent); + if (parent) + current_parent = *parent; + else + break; + } + return parents; } diff --git a/src/main.cpp b/src/main.cpp index 57a96d16..fcccc50e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,16 +60,15 @@ int main() { // blt::gfx::init(blt::gfx::window_data{"Minecraft Color Picker", init, update, destroy}.setSyncInterval(1)); - asset_loader_t loader{"../res/assets", "1.21.5", "../res/data"}; - auto result = loader.load_assets(); + asset_loader_t loader{"1.21.5"}; - if (!result) + if (const auto result = loader.load_assets("../res/assets", "../res/data")) { - BLT_ERROR("Failed to load assets. Reason: {}", result.error().to_string()); + BLT_ERROR("Failed to load assets. Reason: {}", result->to_string()); return 1; } - + auto asset_data = loader.load_textures(); return 0; } \ No newline at end of file