Merge pull request #16042 from luiscuenca/randomAnimDif

DEV-327: Prevent AnimRandomSwitch from repeating same animation twice in a row
This commit is contained in:
Anthony Thibault 2019-08-08 09:38:22 -07:00 committed by GitHub
commit ab63aecf29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 15 deletions

View file

@ -943,9 +943,6 @@ bool processRandomSwitchStateMachineNode(AnimNode::Pointer node, const QJsonObje
} }
auto randomStatePtr = std::make_shared<AnimRandomSwitch::RandomSwitchState>(id, iter->second, interpTarget, interpDuration, interpTypeEnum, easingTypeEnum, priority, resume); auto randomStatePtr = std::make_shared<AnimRandomSwitch::RandomSwitchState>(id, iter->second, interpTarget, interpDuration, interpTypeEnum, easingTypeEnum, priority, resume);
if (priority > 0.0f) {
smNode->addToPrioritySum(priority);
}
assert(randomStatePtr); assert(randomStatePtr);
if (!interpTargetVar.isEmpty()) { if (!interpTargetVar.isEmpty()) {

View file

@ -27,22 +27,35 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
AnimRandomSwitch::RandomSwitchState::Pointer desiredState = _currentState; AnimRandomSwitch::RandomSwitchState::Pointer desiredState = _currentState;
if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1 || animVars.lookup(_triggerRandomSwitchVar, false)) { 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; bool currentStateHasPriority = false;
float dice = randFloatInRange(0.0f, 1.0f); std::vector<RandomSwitchState::Pointer> randomStatesToConsider;
float lowerBound = 0.0f; randomStatesToConsider.reserve(_randomStates.size());
for (const RandomSwitchState::Pointer& randState : _randomStates) { float totalPriorities = 0.0f;
for (size_t i = 0; i < _randomStates.size(); i++) {
auto randState = _randomStates[i];
if (randState->getPriority() > 0.0f) { if (randState->getPriority() > 0.0f) {
float upperBound = lowerBound + (randState->getPriority() / _totalPriorities); bool isRepeatingClip = _children[randState->getChildIndex()]->getID() == _lastPlayedState;
if ((dice > lowerBound) && (dice < upperBound)) { if (!isRepeatingClip) {
desiredState = randState; 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. // 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); 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) { if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1) {
_duringInterp = false; _duringInterp = false;
switchRandomState(animVars, context, desiredState, _duringInterp); 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) { void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const AnimContext& context, RandomSwitchState::Pointer desiredState, bool shouldInterp) {
auto nextStateNode = _children[desiredState->getChildIndex()]; auto nextStateNode = _children[desiredState->getChildIndex()];
_lastPlayedState = nextStateNode->getID();
if (shouldInterp) { if (shouldInterp) {
const float FRAMES_PER_SECOND = 30.0f; const float FRAMES_PER_SECOND = 30.0f;

View file

@ -143,7 +143,6 @@ protected:
void setTransitionVar(const QString& transitionVar) { _transitionVar = transitionVar; } void setTransitionVar(const QString& transitionVar) { _transitionVar = transitionVar; }
void setTriggerTimeMin(float triggerTimeMin) { _triggerTimeMin = triggerTimeMin; } void setTriggerTimeMin(float triggerTimeMin) { _triggerTimeMin = triggerTimeMin; }
void setTriggerTimeMax(float triggerTimeMax) { _triggerTimeMax = triggerTimeMax; } void setTriggerTimeMax(float triggerTimeMax) { _triggerTimeMax = triggerTimeMax; }
void addToPrioritySum(float priority) { _totalPriorities += priority; }
void addState(RandomSwitchState::Pointer randomState); void addState(RandomSwitchState::Pointer randomState);
@ -164,7 +163,6 @@ protected:
float _alpha = 0.0f; float _alpha = 0.0f;
AnimPoseVec _prevPoses; AnimPoseVec _prevPoses;
AnimPoseVec _nextPoses; AnimPoseVec _nextPoses;
float _totalPriorities { 0.0f };
RandomSwitchState::Pointer _currentState; RandomSwitchState::Pointer _currentState;
RandomSwitchState::Pointer _previousState; RandomSwitchState::Pointer _previousState;
@ -179,6 +177,7 @@ protected:
float _randomSwitchTimeMin { 10.0f }; float _randomSwitchTimeMin { 10.0f };
float _randomSwitchTimeMax { 20.0f }; float _randomSwitchTimeMax { 20.0f };
float _randomSwitchTime { 0.0f }; float _randomSwitchTime { 0.0f };
QString _lastPlayedState;
private: private:
// no copies // no copies