Block animation

This commit is contained in:
@clasher113
2024-01-21 15:23:03 +02:00
parent fa6eb6ae22
commit 5fb34daf52
9 changed files with 264 additions and 24 deletions
+11
View File
@@ -54,6 +54,14 @@ void Assets::store(Atlas* atlas, std::string name){
atlases[name].reset(atlas);
}
const std::vector<TextureAnimation>& Assets::getAnimations() {
return animations;
}
void Assets::store(const TextureAnimation& animation) {
animations.emplace_back(animation);
}
void Assets::extend(const Assets& assets) {
for (auto entry : assets.textures) {
textures[entry.first] = entry.second;
@@ -67,4 +75,7 @@ void Assets::extend(const Assets& assets) {
for (auto entry : assets.atlases) {
atlases[entry.first] = entry.second;
}
for (auto entry : assets.animations) {
animations.emplace_back(entry);
}
}
+7
View File
@@ -1,9 +1,12 @@
#ifndef ASSETS_ASSETS_H_
#define ASSETS_ASSETS_H_
#include "../graphics/TextureAnimation.h"
#include <string>
#include <memory>
#include <unordered_map>
#include <vector>
class Texture;
class Shader;
@@ -15,6 +18,7 @@ class Assets {
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::vector<TextureAnimation> animations;
public:
~Assets();
Texture* getTexture(std::string name) const;
@@ -29,6 +33,9 @@ public:
Atlas* getAtlas(std::string name) const;
void store(Atlas* atlas, std::string name);
const std::vector<TextureAnimation>& getAnimations();
void store(const TextureAnimation& animation);
void extend(const Assets& assets);
};
+127 -23
View File
@@ -6,16 +6,17 @@
#include "../files/files.h"
#include "../files/engine_paths.h"
#include "../coders/png.h"
#include "../coders/json.h"
#include "../graphics/Shader.h"
#include "../graphics/Texture.h"
#include "../graphics/ImageData.h"
#include "../graphics/Atlas.h"
#include "../graphics/Font.h"
#include "../graphics/TextureAnimation.h"
namespace fs = std::filesystem;
bool assetload::texture(Assets* assets,
bool assetload::texture(Assets* assets,
const ResPaths* paths,
const std::string filename,
const std::string name) {
@@ -28,21 +29,21 @@ bool assetload::texture(Assets* assets,
return true;
}
bool assetload::shader(Assets* assets,
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");
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(),
vertexFile.string(),
fragmentFile.string(),
vertexSource, fragmentSource);
if (shader == nullptr) {
std::cerr << "failed to load shader '" << name << "'" << std::endl;
return false;
@@ -51,30 +52,39 @@ bool assetload::shader(Assets* assets,
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());
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)) {
// png is only supported format
if (file.extension() != ".png")
continue;
std::string name = file.stem().string();
// skip duplicates
if (builder.has(name)) {
continue;
}
std::unique_ptr<ImageData> image (png::load_image(file.string()));
if (image == nullptr) {
std::cerr << "could not to load " << file.string() << std::endl;
continue;
}
image->fixAlphaColor();
builder.add(name, image.release());
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;
}
@@ -99,3 +109,97 @@ bool assetload::font(Assets* assets,
assets->store(font, 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";
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::vector<std::pair<std::string, float>> frameList;
if (fs::exists(animFile)) {
auto root = files::read_json(animFile);
auto frameArr = root->list("frames");
Frame temp;
float frameDuration = DEFAULT_FRAME_DURATION;
std::string frameName;
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;
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;
}
Atlas* srcAtlas = builder.build(2);
Texture* srcTex = srcAtlas->getTexture();
Texture* dstTex = dstAtlas->getTexture();
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;
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, name + "_animation");
assets->store(animation);
return true;
}
return true;
}
+6
View File
@@ -5,6 +5,7 @@
class ResPaths;
class Assets;
class Atlas;
namespace assetload {
bool texture(Assets* assets,
@@ -23,6 +24,11 @@ namespace assetload {
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);
}
#endif // ASSETS_ASSET_LOADERS_H_