UiDocument is an asset now

This commit is contained in:
MihailRis
2024-02-09 09:59:36 +03:00
parent 241d15e349
commit 07adbd04ea
21 changed files with 402 additions and 304 deletions
+12
View File
@@ -4,6 +4,7 @@
#include "../graphics/Shader.h"
#include "../graphics/Atlas.h"
#include "../graphics/Font.h"
#include "../frontend/UiDocument.h"
Assets::~Assets() {
}
@@ -62,6 +63,17 @@ void Assets::store(const TextureAnimation& animation) {
animations.emplace_back(animation);
}
UiDocument* Assets::getLayout(std::string name) const {
auto found = layouts.find(name);
if (found == layouts.end())
return nullptr;
return found->second.get();
}
void Assets::store(UiDocument* layout, std::string name) {
layouts[name].reset(layout);
}
void Assets::extend(const Assets& assets) {
for (auto entry : assets.textures) {
textures[entry.first] = entry.second;
+5
View File
@@ -12,12 +12,14 @@ class Texture;
class Shader;
class Font;
class Atlas;
class UiDocument;
class Assets {
std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
std::unordered_map<std::string, std::shared_ptr<Shader>> shaders;
std::unordered_map<std::string, std::shared_ptr<Font>> fonts;
std::unordered_map<std::string, std::shared_ptr<Atlas>> atlases;
std::unordered_map<std::string, std::shared_ptr<UiDocument>> layouts;
std::vector<TextureAnimation> animations;
public:
~Assets();
@@ -36,6 +38,9 @@ public:
const std::vector<TextureAnimation>& getAnimations();
void store(const TextureAnimation& animation);
UiDocument* getLayout(std::string name) const;
void store(UiDocument* layout, std::string name);
void extend(const Assets& assets);
};
+10 -1
View File
@@ -48,6 +48,7 @@ void AssetsLoader::createDefaults(AssetsLoader& loader) {
loader.addLoader(ASSET_TEXTURE, assetload::texture);
loader.addLoader(ASSET_FONT, assetload::font);
loader.addLoader(ASSET_ATLAS, assetload::atlas);
loader.addLoader(ASSET_LAYOUT, assetload::layout);
}
void AssetsLoader::addDefaults(AssetsLoader& loader, bool world) {
@@ -66,6 +67,14 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, bool world) {
loader.add(ASSET_SHADER, SHADERS_FOLDER"/skybox_gen", "skybox_gen");
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/moon.png", "misc/moon");
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/sun.png", "misc/sun");
for (fs::path& file : loader.getPaths()->listdir(LAYOUTS_FOLDER)) {
std::string packName = file.parent_path().parent_path().filename();
if (packName == "res") {
packName = "core";
}
loader.add(ASSET_LAYOUT, file.u8string(), packName+":"+file.stem().u8string());
}
}
loader.add(ASSET_ATLAS, TEXTURES_FOLDER"/blocks", "blocks");
loader.add(ASSET_ATLAS, TEXTURES_FOLDER"/items", "items");
@@ -73,4 +82,4 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, bool world) {
const ResPaths* AssetsLoader::getPaths() const {
return paths;
}
}
+1
View File
@@ -10,6 +10,7 @@ const short ASSET_TEXTURE = 1;
const short ASSET_SHADER = 2;
const short ASSET_FONT = 3;
const short ASSET_ATLAS = 4;
const short ASSET_LAYOUT = 5;
class ResPaths;
class Assets;
+151 -132
View File
@@ -13,6 +13,7 @@
#include "../graphics/Atlas.h"
#include "../graphics/Font.h"
#include "../graphics/TextureAnimation.h"
#include "../frontend/UiDocument.h"
namespace fs = std::filesystem;
@@ -20,187 +21,205 @@ bool assetload::texture(Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name) {
std::unique_ptr<Texture> texture(
png::load_texture(paths->find(filename).string())
std::unique_ptr<Texture> texture(
png::load_texture(paths->find(filename).u8string())
);
if (texture == nullptr) {
std::cerr << "failed to load texture '" << name << "'" << std::endl;
return false;
}
assets->store(texture.release(), name);
return true;
if (texture == nullptr) {
std::cerr << "failed to load texture '" << name << "'" << std::endl;
return false;
}
assets->store(texture.release(), name);
return true;
}
bool assetload::shader(Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name) {
fs::path vertexFile = paths->find(filename+".glslv");
fs::path fragmentFile = paths->find(filename+".glslf");
fs::path vertexFile = paths->find(filename+".glslv");
fs::path fragmentFile = paths->find(filename+".glslf");
std::string vertexSource = files::read_string(vertexFile);
std::string fragmentSource = files::read_string(fragmentFile);
std::string vertexSource = files::read_string(vertexFile);
std::string fragmentSource = files::read_string(fragmentFile);
Shader* shader = Shader::loadShader(
vertexFile.string(),
fragmentFile.string(),
vertexSource, fragmentSource);
Shader* shader = Shader::loadShader(
vertexFile.string(),
fragmentFile.string(),
vertexSource, fragmentSource);
if (shader == nullptr) {
std::cerr << "failed to load shader '" << name << "'" << std::endl;
return false;
}
assets->store(shader, name);
return true;
if (shader == nullptr) {
std::cerr << "failed to load shader '" << name << "'" << std::endl;
return false;
}
assets->store(shader, name);
return true;
}
static bool appendAtlas(AtlasBuilder& atlas, const fs::path& file) {
// png is only supported format
if (file.extension() != ".png")
return false;
std::string name = file.stem().string();
// skip duplicates
if (atlas.has(name)) {
return false;
}
std::unique_ptr<ImageData> image(png::load_image(file.string()));
if (image == nullptr) {
std::cerr << "could not to load " << file.string() << std::endl;
return false;
}
image->fixAlphaColor();
atlas.add(name, image.release());
// png is only supported format
if (file.extension() != ".png")
return false;
std::string name = file.stem().string();
// skip duplicates
if (atlas.has(name)) {
return false;
}
std::unique_ptr<ImageData> image(png::load_image(file.string()));
if (image == nullptr) {
std::cerr << "could not to load " << file.string() << std::endl;
return false;
}
image->fixAlphaColor();
atlas.add(name, image.release());
return true;
return true;
}
bool assetload::atlas(Assets* assets,
const ResPaths* paths,
const std::string directory,
const std::string name) {
AtlasBuilder builder;
for (const auto& file : paths->listdir(directory)) {
if (!appendAtlas(builder, file)) continue;
}
Atlas* atlas = builder.build(2);
assets->store(atlas, name);
for (const auto& file : builder.getNames()) {
assetload::animation(assets, paths, "textures", file, atlas);
}
return true;
AtlasBuilder builder;
for (const auto& file : paths->listdir(directory)) {
if (!appendAtlas(builder, file)) continue;
}
Atlas* atlas = builder.build(2);
assets->store(atlas, name);
for (const auto& file : builder.getNames()) {
assetload::animation(assets, paths, "textures", file, atlas);
}
return true;
}
bool assetload::font(Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name) {
std::vector<std::unique_ptr<Texture>> pages;
for (size_t i = 0; i <= 4; i++) {
std::vector<std::unique_ptr<Texture>> pages;
for (size_t i = 0; i <= 4; i++) {
std::string name = filename + "_" + std::to_string(i) + ".png";
name = paths->find(name).string();
std::unique_ptr<Texture> texture (png::load_texture(name));
if (texture == nullptr) {
std::cerr << "failed to load bitmap font '" << name;
std::unique_ptr<Texture> texture (png::load_texture(name));
if (texture == nullptr) {
std::cerr << "failed to load bitmap font '" << name;
std::cerr << "' (missing page " << std::to_string(i) << ")";
std::cerr << std::endl;
return false;
}
pages.push_back(std::move(texture));
}
return false;
}
pages.push_back(std::move(texture));
}
int res = pages[0]->height / 16;
assets->store(new Font(std::move(pages), res, 4), name);
return true;
assets->store(new Font(std::move(pages), res, 4), name);
return true;
}
bool assetload::animation(Assets* assets,
const ResPaths* paths,
const std::string directory,
const std::string name,
Atlas* dstAtlas) {
std::string animsDir = directory + "/animations";
std::string blocksDir = directory + "/blocks";
const ResPaths* paths,
const std::string directory,
const std::string name,
Atlas* dstAtlas) {
std::string animsDir = directory + "/animations";
std::string blocksDir = directory + "/blocks";
for (const auto& folder : paths->listdir(animsDir)) {
if (!fs::is_directory(folder)) continue;
if (folder.filename().string() != name) continue;
if (fs::is_empty(folder)) continue;
AtlasBuilder builder;
for (const auto& folder : paths->listdir(animsDir)) {
if (!fs::is_directory(folder)) continue;
if (folder.filename().string() != name) continue;
if (fs::is_empty(folder)) continue;
AtlasBuilder builder;
appendAtlas(builder, paths->find(blocksDir + "/" + name + ".png"));
std::string animFile = folder.string() + "/animation.json";
std::string animFile = folder.string() + "/animation.json";
std::vector<std::pair<std::string, float>> frameList;
std::vector<std::pair<std::string, float>> frameList;
if (fs::exists(animFile)) {
auto root = files::read_json(animFile);
if (fs::exists(animFile)) {
auto root = files::read_json(animFile);
auto frameArr = root->list("frames");
auto frameArr = root->list("frames");
float frameDuration = DEFAULT_FRAME_DURATION;
std::string frameName;
float frameDuration = DEFAULT_FRAME_DURATION;
std::string frameName;
if (frameArr) {
for (size_t i = 0; i < frameArr->size(); i++) {
auto currentFrame = frameArr->list(i);
if (frameArr) {
for (size_t i = 0; i < frameArr->size(); i++) {
auto currentFrame = frameArr->list(i);
frameName = currentFrame->str(0);
if (currentFrame->size() > 1) frameDuration = static_cast<float>(currentFrame->integer(1)) / 1000;
frameName = currentFrame->str(0);
if (currentFrame->size() > 1)
frameDuration = static_cast<float>(currentFrame->integer(1)) / 1000;
frameList.emplace_back(frameName, frameDuration);
}
}
}
for (const auto& file : paths->listdir(animsDir + "/" + name)) {
if (!frameList.empty()) {
bool contains = false;
for (const auto& elem : frameList) {
if (file.stem() == elem.first) {
contains = true;
break;
}
}
if (!contains) continue;
}
if (!appendAtlas(builder, file)) continue;
}
frameList.emplace_back(frameName, frameDuration);
}
}
}
for (const auto& file : paths->listdir(animsDir + "/" + name)) {
if (!frameList.empty()) {
bool contains = false;
for (const auto& elem : frameList) {
if (file.stem() == elem.first) {
contains = true;
break;
}
}
if (!contains) continue;
}
if (!appendAtlas(builder, file)) continue;
}
std::unique_ptr<Atlas> srcAtlas (builder.build(2));
std::unique_ptr<Atlas> srcAtlas (builder.build(2));
Texture* srcTex = srcAtlas->getTexture();
Texture* dstTex = dstAtlas->getTexture();
Texture* srcTex = srcAtlas->getTexture();
Texture* dstTex = dstAtlas->getTexture();
TextureAnimation animation(srcTex, dstTex);
Frame frame;
UVRegion region = dstAtlas->get(name);
TextureAnimation animation(srcTex, dstTex);
Frame frame;
UVRegion region = dstAtlas->get(name);
frame.dstPos = glm::ivec2(region.u1 * dstTex->width, region.v1 * dstTex->height);
frame.size = glm::ivec2(region.u2 * dstTex->width, region.v2 * dstTex->height) - frame.dstPos;
frame.dstPos = glm::ivec2(region.u1 * dstTex->width, region.v1 * dstTex->height);
frame.size = glm::ivec2(region.u2 * dstTex->width, region.v2 * dstTex->height) - frame.dstPos;
if (frameList.empty()) {
for (const auto& elem : builder.getNames()) {
region = srcAtlas->get(elem);
frame.srcPos = glm::ivec2(region.u1 * srcTex->width, srcTex->height - region.v2 * srcTex->height);
animation.addFrame(frame);
}
}
else {
for (const auto& elem : frameList) {
if (!srcAtlas->has(elem.first)) {
std::cerr << "Unknown frame name: " << elem.first << std::endl;
continue;
}
region = srcAtlas->get(elem.first);
frame.duration = elem.second;
frame.srcPos = glm::ivec2(region.u1 * srcTex->width, srcTex->height - region.v2 * srcTex->height);
animation.addFrame(frame);
}
}
if (frameList.empty()) {
for (const auto& elem : builder.getNames()) {
region = srcAtlas->get(elem);
frame.srcPos = glm::ivec2(region.u1 * srcTex->width, srcTex->height - region.v2 * srcTex->height);
animation.addFrame(frame);
}
}
else {
for (const auto& elem : frameList) {
if (!srcAtlas->has(elem.first)) {
std::cerr << "Unknown frame name: " << elem.first << std::endl;
continue;
}
region = srcAtlas->get(elem.first);
frame.duration = elem.second;
frame.srcPos = glm::ivec2(region.u1 * srcTex->width, srcTex->height - region.v2 * srcTex->height);
animation.addFrame(frame);
}
}
assets->store(srcAtlas.release(), name + "_animation");
assets->store(animation);
assets->store(srcAtlas.release(), name + "_animation");
assets->store(animation);
return true;
}
return true;
return true;
}
return true;
}
bool assetload::layout(
Assets* assets,
const ResPaths* paths,
const std::string file,
const std::string name
) {
try {
auto document = UiDocument::read(name, file);
assets->store(document.release(), name);
return true;
} catch (const parsing_error& err) {
std::cerr << "failed to parse layout XML '" << file << "'" << std::endl;
std::cerr << err.errorLog() << std::endl;
return false;
}
}
+37 -21
View File
@@ -8,27 +8,43 @@ class Assets;
class Atlas;
namespace assetload {
bool texture(Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name);
bool shader(Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name);
bool atlas(Assets* assets,
const ResPaths* paths,
const std::string directory,
const std::string name);
bool font(Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name);
bool animation(Assets* assets,
const ResPaths* paths,
const std::string directory,
const std::string name,
Atlas* dstAtlas);
bool texture(
Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name
);
bool shader(
Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name
);
bool atlas(
Assets* assets,
const ResPaths* paths,
const std::string directory,
const std::string name
);
bool font(
Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name
);
bool animation(
Assets* assets,
const ResPaths* paths,
const std::string directory,
const std::string name,
Atlas* dstAtlas
);
bool layout(
Assets* assets,
const ResPaths* paths,
const std::string file,
const std::string name
);
}
#endif // ASSETS_ASSET_LOADERS_H_