| #include "rive/animation/blend_state_1d_instance.hpp" | |
| #include "rive/animation/state_machine_input_instance.hpp" | |
| using namespace rive; | |
| BlendState1DInstance::BlendState1DInstance(const BlendState1D* blendState, | |
| ArtboardInstance* instance) : | |
| BlendStateInstance<BlendState1D, BlendAnimation1D>(blendState, instance) | |
| {} | |
| int BlendState1DInstance::animationIndex(float value) | |
| { | |
| int idx = 0; | |
| int mid = 0; | |
| float closestValue = 0; | |
| int start = 0; | |
| int end = static_cast<int>(m_AnimationInstances.size()) - 1; | |
| while (start <= end) | |
| { | |
| mid = (start + end) >> 1; | |
| closestValue = m_AnimationInstances[mid].blendAnimation()->value(); | |
| if (closestValue < value) | |
| { | |
| start = mid + 1; | |
| } | |
| else if (closestValue > value) | |
| { | |
| end = mid - 1; | |
| } | |
| else | |
| { | |
| idx = start = mid; | |
| break; | |
| } | |
| idx = start; | |
| } | |
| return idx; | |
| } | |
| void BlendState1DInstance::advance(float seconds, Span<SMIInput*> inputs) | |
| { | |
| BlendStateInstance<BlendState1D, BlendAnimation1D>::advance(seconds, inputs); | |
| auto blendState = state()->as<BlendState1D>(); | |
| float value = 0.0f; | |
| if (blendState->hasValidInputId()) | |
| { | |
| // TODO: https://github.com/rive-app/rive-cpp/issues/229 | |
| auto inputInstance = inputs[blendState->inputId()]; | |
| auto numberInput = static_cast<const SMINumber*>(inputInstance); | |
| value = numberInput->value(); | |
| } | |
| int index = animationIndex(value); | |
| auto animationsCount = static_cast<int>(m_AnimationInstances.size()); | |
| m_To = index >= 0 && index < animationsCount ? &m_AnimationInstances[index] : nullptr; | |
| m_From = | |
| index - 1 >= 0 && index - 1 < animationsCount ? &m_AnimationInstances[index - 1] : nullptr; | |
| float mix, mixFrom; | |
| auto toValue = m_To == nullptr ? 0.0f : m_To->blendAnimation()->value(); | |
| auto fromValue = m_From == nullptr ? 0.0f : m_From->blendAnimation()->value(); | |
| if (m_To == nullptr || m_From == nullptr || toValue == fromValue) | |
| { | |
| mix = mixFrom = 1.0f; | |
| } | |
| else | |
| { | |
| mix = (value - fromValue) / (toValue - fromValue); | |
| mixFrom = 1.0f - mix; | |
| } | |
| for (auto& animation : m_AnimationInstances) | |
| { | |
| auto animationValue = animation.blendAnimation()->value(); | |
| if (m_To != nullptr && animationValue == toValue) | |
| { | |
| animation.mix(mix); | |
| } | |
| else if (m_From != nullptr && animationValue == fromValue) | |
| { | |
| animation.mix(mixFrom); | |
| } | |
| else | |
| { | |
| animation.mix(0.0f); | |
| } | |
| } | |
| } |