special textures
parent
d88531c11d
commit
260d40772e
|
@ -1,2 +1,3 @@
|
||||||
sqlite3
|
sqlite3
|
||||||
opengl
|
opengl
|
||||||
|
nlohmann/json
|
|
@ -30,7 +30,6 @@ class load_failure_t
|
||||||
public:
|
public:
|
||||||
enum type_t
|
enum type_t
|
||||||
{
|
{
|
||||||
ASSETS_ALREADY_LOADED,
|
|
||||||
ASSET_FOLDER_NOT_FOUND,
|
ASSET_FOLDER_NOT_FOUND,
|
||||||
MODEL_FOLDER_NOT_FOUND,
|
MODEL_FOLDER_NOT_FOUND,
|
||||||
TEXTURE_FOLDER_NOT_FOUND,
|
TEXTURE_FOLDER_NOT_FOUND,
|
||||||
|
@ -73,6 +72,11 @@ struct namespaced_object
|
||||||
{
|
{
|
||||||
std::string namespace_str;
|
std::string namespace_str;
|
||||||
std::string key_str;
|
std::string key_str;
|
||||||
|
|
||||||
|
[[nodiscard]] std::string string() const
|
||||||
|
{
|
||||||
|
return namespace_str + ':' + key_str;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct model_data_t
|
struct model_data_t
|
||||||
|
@ -86,34 +90,32 @@ struct namespace_data_t
|
||||||
blt::hashmap_t<std::string, model_data_t> models;
|
blt::hashmap_t<std::string, model_data_t> models;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct assets_data_t
|
struct asset_data_t
|
||||||
{
|
{
|
||||||
database_t db;
|
blt::hashmap_t<std::string, namespace_data_t> json_data;
|
||||||
std::string asset_folder;
|
blt::hashmap_t<std::string, std::string> solid_textures_to_load;
|
||||||
std::optional<std::string> data_folder;
|
blt::hashmap_t<std::string, std::string> non_solid_textures_to_load;
|
||||||
std::string name;
|
|
||||||
|
|
||||||
assets_data_t(database_t&& db, std::string asset_folder, std::optional<std::string> data_folder, std::string name) : db{std::move(db)},
|
blt::hashmap_t<std::string, std::string> namespace_asset_folders;
|
||||||
asset_folder{
|
blt::hashmap_t<std::string, std::string> namespace_data_folders;
|
||||||
std::move(asset_folder)
|
blt::hashmap_t<std::string, std::string> namespace_texture_folders;
|
||||||
},
|
|
||||||
data_folder{
|
[[nodiscard]] std::vector<namespaced_object> resolve_parents(const namespaced_object& model) const;
|
||||||
std::move(data_folder)
|
|
||||||
}, name{std::move(name)}
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class asset_loader_t
|
class asset_loader_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
asset_loader_t(std::string folder, std::string name, std::optional<std::string> data_folder = std::nullopt);
|
explicit asset_loader_t(std::string name);
|
||||||
|
|
||||||
blt::expected<assets_data_t, load_failure_t> load_assets();
|
std::optional<load_failure_t> load_assets(const std::string& asset_folder, const std::optional<std::string>& data_folder = {});
|
||||||
|
|
||||||
|
asset_data_t& load_textures();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// feels like a weird hack?
|
asset_data_t data;
|
||||||
bool contains = true;
|
database_t db;
|
||||||
assets_data_t data;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //ASSET_LOADER_H
|
#endif //ASSET_LOADER_H
|
||||||
|
|
|
@ -250,6 +250,13 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table_column_builder_t& auto_increment()
|
||||||
|
{
|
||||||
|
primary_key();
|
||||||
|
attributes.push_back("AUTOINCREMENT");
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
table_column_builder_t& unique()
|
table_column_builder_t& unique()
|
||||||
{
|
{
|
||||||
attributes.emplace_back("UNIQUE");
|
attributes.emplace_back("UNIQUE");
|
||||||
|
|
|
@ -20,39 +20,30 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <blt/gfx/stb/stb_image.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <blt/logging/logging.h>
|
#include <blt/logging/logging.h>
|
||||||
#include <blt/std/hashmap.h>
|
#include <blt/std/hashmap.h>
|
||||||
#include <blt/std/string.h>
|
#include <blt/std/string.h>
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
asset_loader_t::asset_loader_t(std::string asset_folder, std::string name, std::optional<std::string> data_folder): data{
|
inline namespaced_object empty_object{"NULL", "NULL"};
|
||||||
database_t{name + ".assets"}, std::move(asset_folder), std::move(data_folder), std::move(name)
|
|
||||||
}
|
asset_loader_t::asset_loader_t(std::string name):
|
||||||
|
db{name + ".assets"}, name{std::move(name)}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
blt::expected<assets_data_t, load_failure_t> asset_loader_t::load_assets()
|
std::optional<load_failure_t> asset_loader_t::load_assets(const std::string& asset_folder, const std::optional<std::string>& data_folder)
|
||||||
{
|
{
|
||||||
if (!contains)
|
if (!std::filesystem::exists(asset_folder))
|
||||||
return blt::unexpected(load_failure_t::ASSETS_ALREADY_LOADED);
|
return load_failure_t::ASSET_FOLDER_NOT_FOUND;
|
||||||
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<std::string>("name").primary_key();
|
|
||||||
texture_table.with_column<blt::u32>("width").not_null();
|
|
||||||
texture_table.with_column<blt::u32>("height").not_null();
|
|
||||||
texture_table.with_column<std::byte*>("data").not_null();
|
|
||||||
texture_table.build().execute();
|
|
||||||
|
|
||||||
std::optional<std::filesystem::path> model_folder;
|
std::optional<std::filesystem::path> model_folder;
|
||||||
std::optional<std::filesystem::path> texture_folder;
|
std::optional<std::filesystem::path> texture_folder;
|
||||||
std::optional<std::filesystem::path> tags_folder;
|
std::optional<std::filesystem::path> 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())
|
if (!entry.is_directory())
|
||||||
continue;
|
continue;
|
||||||
|
@ -67,22 +58,22 @@ blt::expected<assets_data_t, load_failure_t> asset_loader_t::load_assets()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!model_folder)
|
if (!model_folder)
|
||||||
return blt::unexpected(load_failure_t::MODEL_FOLDER_NOT_FOUND);
|
return load_failure_t::MODEL_FOLDER_NOT_FOUND;
|
||||||
|
|
||||||
if (!texture_folder)
|
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"))
|
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"))
|
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();
|
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())
|
if (!entry.is_directory())
|
||||||
continue;
|
continue;
|
||||||
|
@ -94,19 +85,25 @@ blt::expected<assets_data_t, load_failure_t> asset_loader_t::load_assets()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.data_folder && !tags_folder)
|
if (data_folder && !tags_folder)
|
||||||
return blt::unexpected(load_failure_t::TAGS_FOLDER_NOT_FOUND);
|
return load_failure_t::TAGS_FOLDER_NOT_FOUND;
|
||||||
|
|
||||||
if (data.data_folder && !exists(*tags_folder / "block"))
|
if (data_folder && !exists(*tags_folder / "block"))
|
||||||
return blt::unexpected(load_failure_t::TAGS_FOLDER_NOT_FOUND);
|
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)
|
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<std::string, namespace_data_t> namespaced_models;
|
blt::hashmap_t<std::string, namespace_data_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())
|
if (!entry.path().has_extension())
|
||||||
continue;
|
continue;
|
||||||
|
@ -162,10 +159,77 @@ blt::expected<assets_data_t, load_failure_t> asset_loader_t::load_assets()
|
||||||
if (!namespaced_models.contains(namespace_name.string()))
|
if (!namespaced_models.contains(namespace_name.string()))
|
||||||
namespaced_models[namespace_name.string()] = {};
|
namespaced_models[namespace_name.string()] = {};
|
||||||
namespaced_models[namespace_name.string()].models.insert({
|
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::vector<namespaced_object>>{} : std::optional{std::move(textures)}}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
contains = false;
|
auto& map = data.json_data[namespace_name.string()];
|
||||||
return std::move(data);
|
|
||||||
|
std::vector<namespaced_object> 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<std::string>("namespace").primary_key();
|
||||||
|
texture_table.with_column<std::string>("name").primary_key();
|
||||||
|
texture_table.with_column<blt::u32>("width").not_null();
|
||||||
|
texture_table.with_column<blt::u32>("height").not_null();
|
||||||
|
texture_table.with_column<std::byte*>("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<namespaced_object> asset_data_t::resolve_parents(const namespaced_object& model) const
|
||||||
|
{
|
||||||
|
std::vector<namespaced_object> 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,16 +60,15 @@ int main()
|
||||||
{
|
{
|
||||||
// blt::gfx::init(blt::gfx::window_data{"Minecraft Color Picker", init, update, destroy}.setSyncInterval(1));
|
// 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"};
|
asset_loader_t loader{"1.21.5"};
|
||||||
auto result = loader.load_assets();
|
|
||||||
|
|
||||||
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto asset_data = loader.load_textures();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue