315 lines
8.8 KiB
C++
315 lines
8.8 KiB
C++
#include "Animation.h"
|
|
#include "Asset/AssetManager.h"
|
|
#include "Tool/Math.h"
|
|
#include "EngineFrame/Actor/Actor.h"
|
|
|
|
Animation::Animation()
|
|
{
|
|
}
|
|
|
|
Animation::Animation(std::string AniPath)
|
|
{
|
|
Init(AniPath);
|
|
}
|
|
|
|
Animation::Animation(std::string AniPath, std::function<std::string(std::string)> AdditionalOptions)
|
|
{
|
|
this->AdditionalOptions = AdditionalOptions;
|
|
Init(AniPath);
|
|
}
|
|
|
|
Animation::~Animation()
|
|
{
|
|
}
|
|
|
|
void Animation::Init(std::string AniPath)
|
|
{
|
|
// 标记该组件需要渲染和更新
|
|
addTag(Tag::RENDER);
|
|
addTag(Tag::UPDATE);
|
|
addTag(Tag::TRANSFORM);
|
|
|
|
AniScriptParser::AniInfo Info = AssetManager::GetInstance().StructAniInfo(AniPath);
|
|
this->AniPath = AniPath;
|
|
this->AnimationFlag = Info.Flag;
|
|
this->FrameArr = Info.Frame;
|
|
|
|
for (size_t i = 0; i < this->FrameArr.size(); i++)
|
|
{
|
|
AniScriptParser::AniFrame FrameObj = this->FrameArr[i];
|
|
RefPtr<Sprite> SpriteObj = nullptr;
|
|
if (!FrameObj.Img_Path.empty())
|
|
{
|
|
if (AdditionalOptions)
|
|
{
|
|
FrameObj.Img_Path = AdditionalOptions(FrameObj.Img_Path);
|
|
}
|
|
SpriteObj = new Sprite(FrameObj.Img_Path, FrameObj.Img_Index);
|
|
SpriteObj->SetPos(FrameObj.Img_Pos);
|
|
}
|
|
else
|
|
SpriteObj = new Sprite();
|
|
SpriteArr.push_back(SpriteObj);
|
|
}
|
|
|
|
// 初始化完毕 如果是第一次初始化 而非重新构造 设置大小为第0帧大小否则天空 地板等依靠大小的初始化会有问题
|
|
if (CurrentIndexT == 0)
|
|
SetSize(SpriteArr[0]->GetSize());
|
|
// 记录总帧数
|
|
TotalFrameIndex = FrameArr.size();
|
|
// TODO 染色
|
|
}
|
|
|
|
void Animation::HandleEvents(SDL_Event *e)
|
|
{
|
|
}
|
|
|
|
void Animation::Update(float deltaTime)
|
|
{
|
|
Component::Update(deltaTime);
|
|
// 可用性检查
|
|
if (IsUsability)
|
|
{
|
|
int dt = (int)(deltaTime * 1000);
|
|
// 累加当前帧时间
|
|
CurrentIndexT += dt;
|
|
// 插值模式判断
|
|
InterpolationLogic();
|
|
// 当前帧时间 超过 当前帧延迟就需要切换帧了
|
|
if (CurrentIndexT >= NextFrameDelay)
|
|
{
|
|
CurrentIndexT = 0;
|
|
// 如果当前帧小于总帧数就切换
|
|
if (CurrentFrameIndex < (TotalFrameIndex - 1))
|
|
{
|
|
FlushFrame(CurrentFrameIndex + 1);
|
|
}
|
|
// 说明播放完毕了
|
|
else
|
|
{
|
|
// 如果有循环
|
|
if (AnimationFlag.count("LOOP"))
|
|
{
|
|
FlushFrame(0);
|
|
}
|
|
// 没有循环触发状态机回调
|
|
else
|
|
{
|
|
// 将不再可用
|
|
IsUsability = false;
|
|
if (EndCallback)
|
|
EndCallback();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Animation::Render(float deltaTime)
|
|
{
|
|
if (IsUsability)
|
|
{
|
|
if (CurrentFrame)
|
|
{
|
|
CurrentFrame->Render(deltaTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Animation::OnAdded(Actor *actor)
|
|
{
|
|
Component::OnAdded(actor);
|
|
FlushFrame(0);
|
|
}
|
|
|
|
void Animation::Clear()
|
|
{
|
|
}
|
|
|
|
void Animation::SetIterationPos(VecPos pos)
|
|
{
|
|
Component::SetIterationPos(pos);
|
|
if (CurrentFrame)
|
|
CurrentFrame->SetIterationPos(this->Pos + this->IterationPos);
|
|
}
|
|
|
|
void Animation::FlushFrame(int Index)
|
|
{
|
|
// 同步当前帧
|
|
CurrentFrameIndex = Index;
|
|
// 当前帧更换为本帧
|
|
CurrentFrame = SpriteArr[CurrentFrameIndex];
|
|
// 设置精灵帧的迭代坐标为自己的坐标和自己的迭代坐标
|
|
CurrentFrame->SetIterationPos(this->Pos + this->IterationPos);
|
|
// 如果是整体染色 则直接使用染色帧
|
|
// if (DyeAllFlag) CurrentFrame = DyeFrameList[CurrentFrameIndex];
|
|
|
|
AniScriptParser::AniFrame FrameInfo = FrameArr[CurrentFrameIndex];
|
|
// 设置下帧延迟
|
|
NextFrameDelay = FrameInfo.Delay;
|
|
|
|
std::unordered_map<std::string, AniScriptParser::AniFlag> FlagBuf = FrameInfo.Flag;
|
|
// 关键帧
|
|
if (FlagBuf.count("SET_FLAG"))
|
|
{
|
|
if (ChangeFrameCallback)
|
|
ChangeFrameCallback(std::get<int>(FlagBuf["SET_FLAG"]));
|
|
}
|
|
// 播放音效
|
|
if (FlagBuf.count("PLAY_SOUND"))
|
|
{
|
|
// TODO 还没有做音效的播放
|
|
}
|
|
// 缩放
|
|
if (FlagBuf.count("IMAGE_RATE"))
|
|
{
|
|
VecFPos Rate = std::get<VecFPos>(FlagBuf["IMAGE_RATE"]);
|
|
VecSize Size = CurrentFrame->GetSize();
|
|
CurrentFrame->SetSize(VecSize{int(Size.width * Rate.x), (int)(Size.width * Rate.y)});
|
|
}
|
|
// 线性减淡
|
|
if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE"))
|
|
{
|
|
CurrentFrame->SetBlendMode(SDL_BLENDMODE_ADD);
|
|
}
|
|
// 旋转
|
|
if (FlagBuf.count("IMAGE_ROTATE"))
|
|
{
|
|
CurrentFrame->SetAnchor(VecFPos{0.5, 0.5});
|
|
CurrentFrame->SetAngle(std::get<float>(FlagBuf["IMAGE_ROTATE"]));
|
|
}
|
|
// 染色
|
|
// if (!DyeAllFlag)
|
|
// 插值模式
|
|
if (FlagBuf.count("INTERPOLATION"))
|
|
{
|
|
// 初始化插值数据
|
|
if (InterpolationFlag.size() == 0)
|
|
{
|
|
// 旧插值数据
|
|
InterpolationFlag.push_back(FrameArr[CurrentFrameIndex]);
|
|
// 新插值数据
|
|
InterpolationFlag.push_back(FrameArr[CurrentFrameIndex + 1]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (InterpolationFlag.size() > 0)
|
|
{
|
|
InterpolationFlag.clear();
|
|
}
|
|
}
|
|
// 如果有描边
|
|
if (IsOutline)
|
|
{
|
|
}
|
|
// Ani的大小同步为精灵帧对象的大小
|
|
SetSize(CurrentFrame->GetSize());
|
|
// 裁切 //TODO
|
|
}
|
|
|
|
void Animation::Reset()
|
|
{
|
|
IsUsability = true;
|
|
CurrentIndexT = 0;
|
|
FlushFrame(0);
|
|
}
|
|
|
|
AniScriptParser::AniFrame Animation::GetCurrentFrameInfo()
|
|
{
|
|
return FrameArr[CurrentFrameIndex];
|
|
}
|
|
|
|
void Animation::SetFrameIndex(int Index)
|
|
{
|
|
FlushFrame(Index);
|
|
CurrentIndexT = 0;
|
|
}
|
|
|
|
void Animation::InterpolationLogic()
|
|
{
|
|
if (InterpolationFlag.size() == 0)
|
|
return;
|
|
// 插值倍率
|
|
float InterRate = Math::getUniformVelocity(0, 100, CurrentIndexT, NextFrameDelay) / 100.0f;
|
|
AniScriptParser::AniFrame OldData = InterpolationFlag[0];
|
|
AniScriptParser::AniFrame NewData = InterpolationFlag[1];
|
|
// RGBA插值
|
|
{
|
|
std::vector<int> OldRgbaData = {255, 255, 255, 250};
|
|
std::vector<int> NewRgbaData = {255, 255, 255, 250};
|
|
if (OldData.Flag.count("RGBA"))
|
|
OldRgbaData = std::get<std::vector<int>>(OldData.Flag["RGBA"]);
|
|
if (NewData.Flag.count("RGBA"))
|
|
NewRgbaData = std::get<std::vector<int>>(NewData.Flag["RGBA"]);
|
|
std::vector<int> RgbaData = {
|
|
(int)(OldRgbaData[0] + (NewRgbaData[0] - OldRgbaData[0]) * InterRate),
|
|
(int)(OldRgbaData[1] + (NewRgbaData[1] - OldRgbaData[1]) * InterRate),
|
|
(int)(OldRgbaData[2] + (NewRgbaData[2] - OldRgbaData[2]) * InterRate),
|
|
(int)(OldRgbaData[3] + (NewRgbaData[3] - OldRgbaData[3]) * InterRate)};
|
|
// TODO 染色 和 透明度还没弄
|
|
}
|
|
// 坐标
|
|
{
|
|
VecPos PosData = {
|
|
(int)(OldData.Img_Pos.x + (NewData.Img_Pos.x - OldData.Img_Pos.x) * InterRate),
|
|
(int)(OldData.Img_Pos.y + (NewData.Img_Pos.y - OldData.Img_Pos.y) * InterRate)};
|
|
SetPos(PosData);
|
|
CurrentFrame->SetIterationPos(this->Pos + this->IterationPos);
|
|
}
|
|
// 缩放
|
|
{
|
|
VecFPos OldRateData = {1.0, 1.0};
|
|
VecFPos NewRateData = {1.0, 1.0};
|
|
if (OldData.Flag.count("IMAGE_RATE"))
|
|
{
|
|
OldRateData = std::get<VecFPos>(OldData.Flag["IMAGE_RATE"]);
|
|
}
|
|
if (NewData.Flag.count("IMAGE_RATE"))
|
|
{
|
|
NewRateData = std::get<VecFPos>(NewData.Flag["IMAGE_RATE"]);
|
|
}
|
|
VecSize ScaleData = {
|
|
(int)(CurrentFrame->GetSize().width * (OldRateData.x + (NewRateData.x - OldRateData.x) * InterRate)),
|
|
(int)(CurrentFrame->GetSize().height * (OldRateData.y + (NewRateData.y - OldRateData.y) * InterRate))};
|
|
VecSize Size = CurrentFrame->GetSize();
|
|
CurrentFrame->SetSize(VecSize{int(Size.width * ScaleData.width), (int)(Size.height * ScaleData.height)});
|
|
}
|
|
// 旋转
|
|
{
|
|
float OldAngleData = 0.0;
|
|
float NewAngleData = 0.0;
|
|
if (OldData.Flag.count("IMAGE_ROTATE"))
|
|
{
|
|
OldAngleData = std::get<float>(OldData.Flag["IMAGE_ROTATE"]);
|
|
}
|
|
if (NewData.Flag.count("IMAGE_ROTATE"))
|
|
{
|
|
NewAngleData = std::get<float>(NewData.Flag["IMAGE_ROTATE"]);
|
|
}
|
|
CurrentFrame->SetAngle(OldAngleData + (NewAngleData - OldAngleData) * InterRate);
|
|
}
|
|
}
|
|
|
|
void Animation::SetSize(VecSize size)
|
|
{
|
|
this->Size = size;
|
|
}
|
|
|
|
void Animation::SetPos(VecPos pos)
|
|
{
|
|
this->Pos = pos;
|
|
if (CurrentFrame)
|
|
CurrentFrame->SetIterationPos(this->Pos + this->IterationPos);
|
|
}
|
|
|
|
VecPos Animation::GetPos()
|
|
{
|
|
return this->Pos;
|
|
}
|
|
|
|
VecSize Animation::GetSize()
|
|
{
|
|
return this->Size;
|
|
}
|