Extra2D/include/animation/animation_controller.h

109 lines
3.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <animation/animation_clip.h>
#include <animation/interpolation_engine.h>
#include <core/types.h>
#include <functional>
#include <string>
namespace extra2d {
// ============================================================================
// 动画播放状态
// ============================================================================
enum class AnimPlayState : uint8 { Stopped, Playing, Paused };
// ============================================================================
// AnimationController - 动画播放控制器
// 借鉴 Cocos Creator 的 AnimationState纯播放逻辑不持有渲染资源
// ============================================================================
class AnimationController {
public:
// 回调类型定义
using FrameChangeCallback = std::function<void(size_t oldIdx, size_t newIdx,
const AnimationFrame &frame)>;
using KeyframeCallback = std::function<void(int flagIndex)>;
using SoundTriggerCallback = std::function<void(const std::string &path)>;
using CompletionCallback = std::function<void()>;
AnimationController() = default;
// ------ 绑定动画数据 ------
void setClip(Ptr<AnimationClip> clip);
Ptr<AnimationClip> getClip() const { return clip_; }
// ------ 播放控制 ------
void play();
void pause();
void resume();
void stop();
void reset();
// ------ 帧控制 ------
void setFrameIndex(size_t index);
void nextFrame();
void prevFrame();
// ------ 核心更新(每帧调用)------
void update(float dt);
// ------ 状态查询 ------
AnimPlayState getState() const { return state_; }
bool isPlaying() const { return state_ == AnimPlayState::Playing; }
bool isPaused() const { return state_ == AnimPlayState::Paused; }
bool isStopped() const { return state_ == AnimPlayState::Stopped; }
size_t getCurrentFrameIndex() const { return currentFrameIndex_; }
size_t getTotalFrames() const;
const AnimationFrame &getCurrentFrame() const;
float getPlaybackSpeed() const { return playbackSpeed_; }
void setPlaybackSpeed(float speed) { playbackSpeed_ = speed; }
bool isLooping() const;
void setLooping(bool loop);
// ------ 插值状态 ------
float getInterpolationFactor() const { return interpolationFactor_; }
bool isInterpolating() const { return interpolating_; }
// ------ 回调注册 ------
void setFrameChangeCallback(FrameChangeCallback cb) {
onFrameChange_ = std::move(cb);
}
void setKeyframeCallback(KeyframeCallback cb) { onKeyframe_ = std::move(cb); }
void setSoundTriggerCallback(SoundTriggerCallback cb) {
onSoundTrigger_ = std::move(cb);
}
void setCompletionCallback(CompletionCallback cb) {
onComplete_ = std::move(cb);
}
private:
Ptr<AnimationClip> clip_;
AnimPlayState state_ = AnimPlayState::Stopped;
size_t currentFrameIndex_ = 0;
float accumulatedTime_ = 0.0f; // 当前帧已累积时间 (ms)
float playbackSpeed_ = 1.0f;
bool loopOverride_ = false; // 外部循环覆盖值
bool hasLoopOverride_ = false; // 是否使用外部循环覆盖
// 插值状态
bool interpolating_ = false;
float interpolationFactor_ = 0.0f;
// 回调
FrameChangeCallback onFrameChange_;
KeyframeCallback onKeyframe_;
SoundTriggerCallback onSoundTrigger_;
CompletionCallback onComplete_;
// 内部方法
void advanceFrame(size_t newIndex);
void processFrameProperties(const AnimationFrame &frame);
void updateInterpolation();
};
} // namespace extra2d