migrant .ani a .yaml

This commit is contained in:
2025-11-17 12:47:07 +01:00
parent 21a495e40a
commit 10911990dd
66 changed files with 1012 additions and 78 deletions

View File

@@ -7,6 +7,7 @@
#include <stdexcept> // Para runtime_error
#include <utility>
#include "external/fkyaml_node.hpp" // Para fkyaml::node
#include "core/rendering/surface.hpp" // Para Surface
#include "core/resources/resource_cache.hpp" // Para Resource
#include "core/resources/resource_helper.hpp" // Para ResourceHelper
@@ -42,12 +43,136 @@ auto SurfaceAnimatedSprite::loadAnimationsFromFile(const std::string& file_path)
return buffer;
}
// Helper: Convierte un nodo YAML de frames (array) a vector de SDL_FRect
auto convertYAMLFramesToRects(const fkyaml::node& frames_node, float frame_width, float frame_height, int frames_per_row, int max_tiles) -> std::vector<SDL_FRect> {
std::vector<SDL_FRect> frames;
SDL_FRect rect = {0.0F, 0.0F, frame_width, frame_height};
for (const auto& frame_index_node : frames_node) {
const int NUM_TILE = frame_index_node.get_value<int>();
if (NUM_TILE <= max_tiles) {
rect.x = (NUM_TILE % frames_per_row) * frame_width;
rect.y = (NUM_TILE / frames_per_row) * frame_height;
frames.emplace_back(rect);
}
}
return frames;
}
// Carga las animaciones desde un fichero YAML
auto SurfaceAnimatedSprite::loadAnimationsFromYAML(const std::string& file_path, std::shared_ptr<Surface>& surface, float& frame_width, float& frame_height) -> std::vector<AnimationData> {
std::vector<AnimationData> animations;
// Extract filename for logging
const std::string FILE_NAME = file_path.substr(file_path.find_last_of("\\/") + 1);
try {
// Load YAML file using ResourceHelper (supports both filesystem and pack)
auto file_data = Resource::Helper::loadFile(file_path);
if (file_data.empty()) {
std::cerr << "Error: Unable to load animation file " << FILE_NAME << '\n';
throw std::runtime_error("Animation file not found: " + file_path);
}
printWithDots("Animation : ", FILE_NAME, "[ LOADED ]");
// Parse YAML from string
std::string yaml_content(file_data.begin(), file_data.end());
auto yaml = fkyaml::node::deserialize(yaml_content);
// --- Parse global configuration ---
if (yaml.contains("tileSetFile")) {
std::string tile_set_file = yaml["tileSetFile"].get_value<std::string>();
surface = Resource::Cache::get()->getSurface(tile_set_file);
}
if (yaml.contains("frameWidth")) {
frame_width = static_cast<float>(yaml["frameWidth"].get_value<int>());
}
if (yaml.contains("frameHeight")) {
frame_height = static_cast<float>(yaml["frameHeight"].get_value<int>());
}
// Calculate sprite sheet parameters
int frames_per_row = 1;
int max_tiles = 1;
if (surface) {
frames_per_row = surface->getWidth() / static_cast<int>(frame_width);
const int W = surface->getWidth() / static_cast<int>(frame_width);
const int H = surface->getHeight() / static_cast<int>(frame_height);
max_tiles = W * H;
}
// --- Parse animations array ---
if (yaml.contains("animations") && yaml["animations"].is_sequence()) {
const auto& animations_node = yaml["animations"];
for (const auto& anim_node : animations_node) {
AnimationData animation;
// Parse animation name
if (anim_node.contains("name")) {
animation.name = anim_node["name"].get_value<std::string>();
}
// Parse speed (seconds per frame)
if (anim_node.contains("speed")) {
animation.speed = anim_node["speed"].get_value<float>();
}
// Parse loop frame index
if (anim_node.contains("loop")) {
animation.loop = anim_node["loop"].get_value<int>();
}
// Parse frames array
if (anim_node.contains("frames") && anim_node["frames"].is_sequence()) {
animation.frames = convertYAMLFramesToRects(
anim_node["frames"],
frame_width,
frame_height,
frames_per_row,
max_tiles
);
}
animations.push_back(animation);
}
}
} catch (const fkyaml::exception& e) {
std::cerr << "YAML parsing error in " << FILE_NAME << ": " << e.what() << '\n';
throw;
} catch (const std::exception& e) {
std::cerr << "Error loading animation " << FILE_NAME << ": " << e.what() << '\n';
throw;
}
return animations;
}
// Constructor
SurfaceAnimatedSprite::SurfaceAnimatedSprite(const std::string& file_path) {
// Carga las animaciones
if (!file_path.empty()) {
Animations v = SurfaceAnimatedSprite::loadAnimationsFromFile(file_path);
setAnimations(v);
// Detectar extensión del archivo
const bool IS_YAML = file_path.substr(file_path.find_last_of('.') + 1) == "yaml";
if (IS_YAML) {
// Cargar desde YAML (formato nuevo)
float frame_width = 1.0F;
float frame_height = 1.0F;
animations_ = loadAnimationsFromYAML(file_path, surface_, frame_width, frame_height);
setWidth(frame_width);
setHeight(frame_height);
} else {
// Cargar desde .ani (formato legacy)
Animations v = SurfaceAnimatedSprite::loadAnimationsFromFile(file_path);
setAnimations(v);
}
}
}
@@ -63,8 +188,21 @@ SurfaceAnimatedSprite::SurfaceAnimatedSprite(std::shared_ptr<Surface> surface, c
: SurfaceMovingSprite(std::move(surface)) {
// Carga las animaciones
if (!file_path.empty()) {
Animations v = SurfaceAnimatedSprite::loadAnimationsFromFile(file_path);
setAnimations(v);
// Detectar extensión del archivo
const bool IS_YAML = file_path.substr(file_path.find_last_of('.') + 1) == "yaml";
if (IS_YAML) {
// Cargar desde YAML (formato nuevo)
float frame_width = 1.0F;
float frame_height = 1.0F;
animations_ = loadAnimationsFromYAML(file_path, surface_, frame_width, frame_height);
setWidth(frame_width);
setHeight(frame_height);
} else {
// Cargar desde .ani (formato legacy)
Animations v = SurfaceAnimatedSprite::loadAnimationsFromFile(file_path);
setAnimations(v);
}
}
}

View File

@@ -15,8 +15,20 @@ class SurfaceAnimatedSprite : public SurfaceMovingSprite {
public:
using Animations = std::vector<std::string>; // Tipo para lista de animaciones
// Estructura pública de datos de animación
struct AnimationData {
std::string name{}; // Nombre de la animacion
std::vector<SDL_FRect> frames; // Cada uno de los frames que componen la animación
float speed{0.083F}; // Velocidad de la animación (segundos por frame)
int loop{0}; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed{false}; // Indica si ha finalizado la animación
int current_frame{0}; // Frame actual
float accumulated_time{0.0F}; // Tiempo acumulado para las animaciones (time-based)
};
// Métodos estáticos
static auto loadAnimationsFromFile(const std::string& file_path) -> Animations; // Carga las animaciones desde fichero
static auto loadAnimationsFromFile(const std::string& file_path) -> Animations; // Carga las animaciones desde fichero .ani
static auto loadAnimationsFromYAML(const std::string& file_path, std::shared_ptr<Surface>& surface, float& frame_width, float& frame_height) -> std::vector<AnimationData>; // Carga las animaciones desde fichero .yaml
// Constructores
explicit SurfaceAnimatedSprite(const std::string& file_path);
@@ -47,17 +59,6 @@ class SurfaceAnimatedSprite : public SurfaceMovingSprite {
void setAnimations(const Animations& animations); // Carga la animación desde un vector de cadenas
private:
// Estructura interna de datos de animación
struct AnimationData {
std::string name{}; // Nombre de la animacion
std::vector<SDL_FRect> frames; // Cada uno de los frames que componen la animación
float speed{0.083F}; // Velocidad de la animación (segundos por frame)
int loop{0}; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed{false}; // Indica si ha finalizado la animación
int current_frame{0}; // Frame actual
float accumulated_time{0.0F}; // Tiempo acumulado para las animaciones (time-based)
};
// Funciones amigas (helper functions del .cpp)
friend void parseAnimationFrames(const std::string& value, AnimationData& animation, float frame_width, float frame_height, int frames_per_row, int max_tiles);
friend auto parseAnimationParameter(const std::string& key, const std::string& value, AnimationData& animation, float frame_width, float frame_height, int frames_per_row, int max_tiles) -> bool;