Xxxx randomization updates part 2 Diffs= 99d28e1ac Xxxx randomization updates part 2 (#7097) Co-authored-by: Alex Gibson <agibson.uk@gmail.com> Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index 64395e4..efc3ff2 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -a0004fa72b5b3c4f040b7807b186560703334dc4 +99d28e1ac65672076b08f3a044218ec60268c4ae
diff --git a/include/rive/animation/state_machine_instance.hpp b/include/rive/animation/state_machine_instance.hpp index 1232b11..4618a82 100644 --- a/include/rive/animation/state_machine_instance.hpp +++ b/include/rive/animation/state_machine_instance.hpp
@@ -5,6 +5,8 @@ #include <stddef.h> #include <vector> #include "rive/animation/linear_animation_instance.hpp" +#include "rive/animation/state_instance.hpp" +#include "rive/animation/state_transition.hpp" #include "rive/core/field_types/core_callback_type.hpp" #include "rive/hit_result.hpp" #include "rive/listener_type.hpp" @@ -55,6 +57,8 @@ void notifyEventListeners(const std::vector<EventReport>& events, NestedArtboard* source); void sortHitComponents(); double randomValue(); + StateTransition* findRandomTransition(StateInstance* stateFromInstance, bool ignoreTriggers); + StateTransition* findAllowedTransition(StateInstance* stateFromInstance, bool ignoreTriggers); public: StateMachineInstance(const StateMachine* machine, ArtboardInstance* instance);
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index 3617c64..9434dd4 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp
@@ -172,15 +172,11 @@ return true; } - bool tryChangeState(StateInstance* stateFromInstance, bool ignoreTriggers) + StateTransition* findRandomTransition(StateInstance* stateFromInstance, bool ignoreTriggers) { - if (stateFromInstance == nullptr) - { - return false; - } - auto stateFrom = stateFromInstance->state(); - auto outState = m_currentState; uint32_t totalWeight = 0; + auto stateFrom = stateFromInstance->state(); + // printf("stateFrom->transitionCount(): %zu\n", stateFrom->transitionCount()); for (size_t i = 0, length = stateFrom->transitionCount(); i < length; i++) { auto transition = stateFrom->transition(i); @@ -190,11 +186,6 @@ { transition->evaluatedRandomWeight(transition->randomWeight()); totalWeight += transition->randomWeight(); - if ((static_cast<LayerStateFlags>(stateFromInstance->state()->flags()) & - LayerStateFlags::Random) != LayerStateFlags::Random) - { - break; - } } else { @@ -207,7 +198,6 @@ } if (totalWeight > 0) { - double randomWeight = randomValue() * totalWeight * 1.0; float currentWeight = 0; size_t index = 0; @@ -218,11 +208,57 @@ auto transitionWeight = transition->evaluatedRandomWeight(); if (currentWeight + transitionWeight > randomWeight) { - break; + return transition; } currentWeight += transitionWeight; index++; } + } + return nullptr; + } + + StateTransition* findAllowedTransition(StateInstance* stateFromInstance, bool ignoreTriggers) + { + auto stateFrom = stateFromInstance->state(); + // If it should randomize + if ((static_cast<LayerStateFlags>(stateFrom->flags()) & LayerStateFlags::Random) == + LayerStateFlags::Random) + { + return findRandomTransition(stateFromInstance, ignoreTriggers); + } + // Else search the first valid transition + for (size_t i = 0, length = stateFrom->transitionCount(); i < length; i++) + { + auto transition = stateFrom->transition(i); + auto allowed = + transition->allowed(stateFromInstance, m_stateMachineInstance, ignoreTriggers); + if (allowed == AllowTransition::yes && canChangeState(transition->stateTo())) + { + transition->evaluatedRandomWeight(transition->randomWeight()); + return transition; + } + else + { + transition->evaluatedRandomWeight(0); + if (allowed == AllowTransition::waitingForExit) + { + m_waitingForExit = true; + } + } + } + return nullptr; + } + + bool tryChangeState(StateInstance* stateFromInstance, bool ignoreTriggers) + { + if (stateFromInstance == nullptr) + { + return false; + } + auto outState = m_currentState; + auto transition = findAllowedTransition(stateFromInstance, ignoreTriggers); + if (transition != nullptr) + { changeState(transition->stateTo()); m_stateMachineChangedOnAdvance = true; // state actually has changed