diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 6828ed1c7e..d43351fff9 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -943,9 +943,6 @@ bool processRandomSwitchStateMachineNode(AnimNode::Pointer node, const QJsonObje } auto randomStatePtr = std::make_shared(id, iter->second, interpTarget, interpDuration, interpTypeEnum, easingTypeEnum, priority, resume); - if (priority > 0.0f) { - smNode->addToPrioritySum(priority); - } assert(randomStatePtr); if (!interpTargetVar.isEmpty()) { diff --git a/libraries/animation/src/AnimRandomSwitch.cpp b/libraries/animation/src/AnimRandomSwitch.cpp index edc8c8dd96..3cf402cc14 100644 --- a/libraries/animation/src/AnimRandomSwitch.cpp +++ b/libraries/animation/src/AnimRandomSwitch.cpp @@ -27,22 +27,35 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co AnimRandomSwitch::RandomSwitchState::Pointer desiredState = _currentState; if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1 || animVars.lookup(_triggerRandomSwitchVar, false)) { - // get a random number and decide which motion to choose. + // filter states different to the last random state and with priorities. bool currentStateHasPriority = false; - float dice = randFloatInRange(0.0f, 1.0f); - float lowerBound = 0.0f; - for (const RandomSwitchState::Pointer& randState : _randomStates) { + std::vector randomStatesToConsider; + randomStatesToConsider.reserve(_randomStates.size()); + float totalPriorities = 0.0f; + for (size_t i = 0; i < _randomStates.size(); i++) { + auto randState = _randomStates[i]; if (randState->getPriority() > 0.0f) { - float upperBound = lowerBound + (randState->getPriority() / _totalPriorities); - if ((dice > lowerBound) && (dice < upperBound)) { - desiredState = randState; + bool isRepeatingClip = _children[randState->getChildIndex()]->getID() == _lastPlayedState; + if (!isRepeatingClip) { + randomStatesToConsider.push_back(randState); + totalPriorities += randState->getPriority(); } - lowerBound = upperBound; - // this indicates if the curent state is one that can be selected randomly, or is one that was transitioned to by the random duration timer. currentStateHasPriority = currentStateHasPriority || (_currentState == randState); } } + // get a random number and decide which motion to choose. + float dice = randFloatInRange(0.0f, 1.0f); + float lowerBound = 0.0f; + for (size_t i = 0; i < randomStatesToConsider.size(); i++) { + auto randState = randomStatesToConsider[i]; + float upperBound = lowerBound + (randState->getPriority() / totalPriorities); + if ((dice > lowerBound) && (dice < upperBound)) { + desiredState = randState; + break; + } + lowerBound = upperBound; + } if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1) { _duringInterp = false; switchRandomState(animVars, context, desiredState, _duringInterp); @@ -155,8 +168,8 @@ void AnimRandomSwitch::addState(RandomSwitchState::Pointer randomState) { } void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const AnimContext& context, RandomSwitchState::Pointer desiredState, bool shouldInterp) { - auto nextStateNode = _children[desiredState->getChildIndex()]; + _lastPlayedState = nextStateNode->getID(); if (shouldInterp) { const float FRAMES_PER_SECOND = 30.0f; diff --git a/libraries/animation/src/AnimRandomSwitch.h b/libraries/animation/src/AnimRandomSwitch.h index 7c185dd7cb..888ed1f6b5 100644 --- a/libraries/animation/src/AnimRandomSwitch.h +++ b/libraries/animation/src/AnimRandomSwitch.h @@ -143,7 +143,6 @@ protected: void setTransitionVar(const QString& transitionVar) { _transitionVar = transitionVar; } void setTriggerTimeMin(float triggerTimeMin) { _triggerTimeMin = triggerTimeMin; } void setTriggerTimeMax(float triggerTimeMax) { _triggerTimeMax = triggerTimeMax; } - void addToPrioritySum(float priority) { _totalPriorities += priority; } void addState(RandomSwitchState::Pointer randomState); @@ -164,7 +163,6 @@ protected: float _alpha = 0.0f; AnimPoseVec _prevPoses; AnimPoseVec _nextPoses; - float _totalPriorities { 0.0f }; RandomSwitchState::Pointer _currentState; RandomSwitchState::Pointer _previousState; @@ -179,6 +177,7 @@ protected: float _randomSwitchTimeMin { 10.0f }; float _randomSwitchTimeMax { 20.0f }; float _randomSwitchTime { 0.0f }; + QString _lastPlayedState; private: // no copies