Create-Engine/src/src/Components/AnimationComponent.cpp
2025-04-24 16:52:36 -05:00

153 lines
5.1 KiB
C++

#include "AnimationComponent.h"
AnimationComponent::AnimationComponent(Object *owner)
: Component(owner) {}
void AnimationComponent::SetTextureAtlasPath(const std::string &path, int texelWidth, int texelHeight, float duration, int start, int end)
{
AssetManager::LoadAssetAsync(path, AssetType::Image);
const auto *asset = AssetManager::GetAssetByPath(path);
if (asset)
SetTextureAtlas(asset->uaid, texelWidth, texelHeight, duration, start, end);
}
void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texelHeight, float duration, int start, int end)
{
textureUAID = uaid;
const auto *asset = AssetManager::GetAssetByID(uaid);
if (!asset || !asset->loaded)
{
Logger::LogError("SetTextureAtlas: Asset not found or not loaded (UAID: %llu)", uaid);
return;
}
int texWidth = static_cast<int>(asset->size.x);
int texHeight = static_cast<int>(asset->size.y);
if (texelWidth <= 0 || texelHeight <= 0 || texWidth < texelWidth || texHeight < texelHeight)
{
Logger::LogError("SetTextureAtlas: Invalid texel size %dx%d for image size %dx%d (UAID: %llu)",
texelWidth, texelHeight, texWidth, texHeight, uaid);
return;
}
if (texWidth % texelWidth != 0 || texHeight % texelHeight != 0)
{
Logger::LogWarning("SetTextureAtlas: Texture size is not cleanly divisible by texel size (UAID: %llu)", uaid);
}
texture = std::make_shared<Texture>(asset->uaid);
atlas.texture = texture;
atlas.SetTexelSize(texelWidth, texelHeight);
columns = texWidth / texelWidth;
rows = texHeight / texelHeight;
totalFrames = columns * rows;
startFrame = 0;
endFrame = totalFrames > 0 ? totalFrames - 1 : 0;
if (start != 0)
{
startFrame = start;
}
if (end != 0)
{
endFrame = end;
}
frameDuration = duration;
currentFrame = startFrame;
renderType = RenderType::Unlit;
}
void AnimationComponent::Play() { playing = true; }
void AnimationComponent::Stop() { playing = false; }
void AnimationComponent::SetLooping(bool loop_) { loop = loop_; }
bool AnimationComponent::IsPlaying() const { return playing; }
void AnimationComponent::SetPlaying(bool play) { playing = play; }
uint64_t AnimationComponent::GetTextureUAID() const { return textureUAID; }
void AnimationComponent::SetTextureUAID(uint64_t uaid) { textureUAID = uaid; }
bool AnimationComponent::IsLooping() const { return loop; }
void AnimationComponent::SetSpeed(float speed_) { speed = speed_; }
float AnimationComponent::GetSpeed() const { return speed; }
void AnimationComponent::SetFrame(int frame)
{
currentFrame = std::clamp(frame, startFrame, endFrame);
time = 0.0f;
}
int AnimationComponent::GetCurrentFrame() const { return currentFrame; }
int AnimationComponent::GetStartFrame() const { return startFrame; }
void AnimationComponent::SetStartFrame(int start) { startFrame = std::clamp(start, 0, totalFrames - 1); }
int AnimationComponent::GetEndFrame() const { return endFrame; }
void AnimationComponent::SetEndFrame(int end) { endFrame = std::clamp(end, 0, totalFrames - 1); }
int AnimationComponent::GetTotalFrames() const { return totalFrames; }
float AnimationComponent::GetFrameDuration() const { return frameDuration; }
void AnimationComponent::SetFrameDuration(float duration) { frameDuration = duration; }
TextureAtlas *AnimationComponent::GetAtlas() { return &atlas; }
const TextureAtlas *AnimationComponent::GetAtlas() const { return &atlas; }
void AnimationComponent::Update(float dt)
{
if (!playing || totalFrames <= 1)
return;
time += dt * speed;
if (time >= frameDuration)
{
time -= frameDuration;
currentFrame++;
if (currentFrame > endFrame)
{
if (loop)
currentFrame = startFrame;
else
{
currentFrame = startFrame;
playing = false;
}
}
}
}
std::string AnimationComponent::GetName() const { return "AnimationComponent"; }
void AnimationComponent::Save(YAML::Emitter &out) const
{
out << YAML::BeginMap;
out << YAML::Key << "type" << YAML::Value << GetName();
out << YAML::Key << "TextureUAID" << YAML::Value << textureUAID;
out << YAML::Key << "TexelWidth" << YAML::Value << atlas.frameWidth;
out << YAML::Key << "TexelHeight" << YAML::Value << atlas.frameHeight;
out << YAML::Key << "FrameDuration" << YAML::Value << frameDuration;
out << YAML::Key << "StartFrame" << YAML::Value << startFrame;
out << YAML::Key << "EndFrame" << YAML::Value << endFrame;
out << YAML::EndMap;
}
void AnimationComponent::Load(const YAML::Node &node)
{
uint64_t uaid = node["TextureUAID"].as<uint64_t>();
int texelWidth = node["TexelWidth"].as<int>();
int texelHeight = node["TexelHeight"].as<int>();
float duration = node["FrameDuration"].as<float>();
int start = node["StartFrame"] ? node["StartFrame"].as<int>() : 0;
int end = node["EndFrame"] ? node["EndFrame"].as<int>() : 0;
SetTextureAtlas(uaid, texelWidth, texelHeight, duration, start, end);
}