blob: 9b1a1206c19f75d54f8948dc74fb668a04c6f4f1 [file] [log] [blame]
#ifndef _RIVE_BLEND_STATE_INSTANCE_HPP_
#define _RIVE_BLEND_STATE_INSTANCE_HPP_
#include <string>
#include <vector>
#include "rive/animation/state_instance.hpp"
#include "rive/animation/blend_state.hpp"
#include "rive/animation/linear_animation_instance.hpp"
namespace rive {
class AnimationState;
template <class K, class T> class BlendStateInstance;
template <class T> class BlendStateAnimationInstance {
template <class A, class B> friend class BlendStateInstance;
private:
const T* m_BlendAnimation;
LinearAnimationInstance m_AnimationInstance;
float m_Mix = 0.0f;
public:
const T* blendAnimation() const { return m_BlendAnimation; }
const LinearAnimationInstance* animationInstance() const { return &m_AnimationInstance; }
BlendStateAnimationInstance(const T* blendAnimation, Artboard* instance) :
m_BlendAnimation(blendAnimation),
m_AnimationInstance(blendAnimation->animation(), instance)
{}
void mix(float value) { m_Mix = value; }
};
template <class K, class T> class BlendStateInstance : public StateInstance {
protected:
std::vector<BlendStateAnimationInstance<T>> m_AnimationInstances;
bool m_KeepGoing = true;
public:
BlendStateInstance(const K* blendState, ArtboardInstance* instance) : StateInstance(blendState) {
for (auto blendAnimation : blendState->animations()) {
m_AnimationInstances.emplace_back(
BlendStateAnimationInstance<T>(static_cast<T*>(blendAnimation), instance));
}
}
bool keepGoing() const override { return m_KeepGoing; }
void advance(float seconds, Span<SMIInput*>) override {
m_KeepGoing = false;
for (auto& animation : m_AnimationInstances) {
if (animation.m_AnimationInstance.advance(seconds)) {
m_KeepGoing = true;
}
}
}
void apply(float mix) override {
for (auto& animation : m_AnimationInstances) {
float m = mix * animation.m_Mix;
animation.m_AnimationInstance.apply(m);
}
}
// Find the animationInstance that corresponds to the blendAnimation.
const LinearAnimationInstance*
animationInstance(const BlendAnimation* blendAnimation) const {
for (auto& animation : m_AnimationInstances) {
if (animation.m_BlendAnimation == blendAnimation) {
return animation.animationInstance();
}
}
return nullptr;
}
};
} // namespace rive
#endif