Fix bad assumptions about state machine animation instances.
diff --git a/include/rive/animation/animation_state.hpp b/include/rive/animation/animation_state.hpp index 5cb0282..2a2c580 100644 --- a/include/rive/animation/animation_state.hpp +++ b/include/rive/animation/animation_state.hpp
@@ -15,6 +15,7 @@ public: const LinearAnimation* animation() const { return m_Animation; } + const LinearAnimation* animationOrEmpty() const; std::unique_ptr<StateInstance> makeInstance(ArtboardInstance*) const override; }; } // namespace rive
diff --git a/src/animation/animation_state.cpp b/src/animation/animation_state.cpp index 3d25d42..cc1d37c 100644 --- a/src/animation/animation_state.cpp +++ b/src/animation/animation_state.cpp
@@ -1,16 +1,17 @@ #include "rive/animation/animation_state.hpp" #include "rive/animation/linear_animation.hpp" #include "rive/animation/animation_state_instance.hpp" -#include "rive/animation/system_state_instance.hpp" #include "rive/core_context.hpp" #include "rive/artboard.hpp" using namespace rive; std::unique_ptr<StateInstance> AnimationState::makeInstance(ArtboardInstance* instance) const { - if (animation() == nullptr) { - // Failed to load at runtime/some new type we don't understand. - return std::make_unique<SystemStateInstance>(this, instance); - } return std::make_unique<AnimationStateInstance>(this, instance); +} + +static LinearAnimation emptyAnimation; + +const LinearAnimation* AnimationState::animationOrEmpty() const { + return m_Animation == nullptr ? &emptyAnimation : m_Animation; } \ No newline at end of file
diff --git a/src/animation/animation_state_instance.cpp b/src/animation/animation_state_instance.cpp index 3cd7b15..7efd51d 100644 --- a/src/animation/animation_state_instance.cpp +++ b/src/animation/animation_state_instance.cpp
@@ -6,16 +6,20 @@ AnimationStateInstance::AnimationStateInstance(const AnimationState* state, ArtboardInstance* instance) : StateInstance(state), - m_AnimationInstance(state->animation(), instance), - m_KeepGoing(true) -{} + // We're careful to always instance a valid animation here as the + // StateMachine makes assumptions about AnimationState's producing valid + // AnimationStateInstances with backing animations. This was discovered when + // using Clang address sanitizer. We previously returned a + // SystemStateInstance (basically a no-op StateMachine state) which would + // cause bad casts in parts of the code where we assumed AnimationStates + // would have create AnimationStateInstances. + m_AnimationInstance(state->animationOrEmpty(), instance), + m_KeepGoing(true) {} void AnimationStateInstance::advance(float seconds, Span<SMIInput*>) { m_KeepGoing = m_AnimationInstance.advance(seconds); } -void AnimationStateInstance::apply(float mix) { - m_AnimationInstance.apply(mix); -} +void AnimationStateInstance::apply(float mix) { m_AnimationInstance.apply(mix); } bool AnimationStateInstance::keepGoing() const { return m_KeepGoing; } \ No newline at end of file