Merge pull request #16104 from luiscuenca/fixRandomAnim

DEV-327: Prevent AnimRandomSwitch from repeating same animation twice in a row.
This commit is contained in:
Shannon Romano 2019-08-27 13:00:39 -07:00 committed by GitHub
commit 55238200f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 6 deletions

View file

@ -60,6 +60,13 @@ void AnimNode::setCurrentFrame(float frame) {
}
}
void AnimNode::setActive(bool active) {
setActiveInternal(active);
for (auto&& child : _children) {
child->setActiveInternal(active);
}
}
void AnimNode::processOutputJoints(AnimVariantMap& triggersOut) const {
if (!_skeleton) {
return;

View file

@ -73,6 +73,7 @@ public:
}
void setCurrentFrame(float frame);
void setActive(bool active);
template <typename F>
bool traverse(F func) {
@ -104,6 +105,7 @@ protected:
virtual void setCurrentFrameInternal(float frame) {}
virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) { _skeleton = skeleton; }
virtual void setActiveInternal(bool active) {}
// for AnimDebugDraw rendering
virtual const AnimPoseVec& getPosesInternal() const = 0;
@ -116,6 +118,7 @@ protected:
AnimSkeleton::ConstPointer _skeleton;
std::weak_ptr<AnimNode> _parent;
std::vector<QString> _outputJointNames;
bool _active { false };
// no copies
AnimNode(const AnimNode&) = delete;

View file

@ -21,12 +21,16 @@ AnimRandomSwitch::~AnimRandomSwitch() {
}
void AnimRandomSwitch::setActiveInternal(bool active) {
_active = active;
_triggerNewRandomState = active;
}
const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) {
float parentDebugAlpha = context.getDebugAlpha(_id);
AnimRandomSwitch::RandomSwitchState::Pointer desiredState = _currentState;
if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1 || animVars.lookup(_triggerRandomSwitchVar, false)) {
if (_triggerNewRandomState || animVars.lookup(_triggerRandomSwitchVar, false)) {
// filter states different to the last random state and with priorities.
bool currentStateHasPriority = false;
std::vector<RandomSwitchState::Pointer> randomStatesToConsider;
@ -56,8 +60,9 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
}
lowerBound = upperBound;
}
if (abs(_randomSwitchEvaluationCount - context.getEvaluationCount()) > 1) {
if (_triggerNewRandomState) {
switchRandomState(animVars, context, desiredState, false);
_triggerNewRandomState = false;
} else {
// firing a random switch, be sure that we aren't completing a previously triggered transition
if (currentStateHasPriority) {
@ -70,7 +75,6 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
}
_triggerTime = randFloatInRange(_triggerTimeMin, _triggerTimeMax);
_randomSwitchTime = randFloatInRange(_randomSwitchTimeMin, _randomSwitchTimeMax);
} else {
// here we are checking to see if we want a temporary movement
@ -143,7 +147,6 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
_poses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
}
_randomSwitchEvaluationCount = context.getEvaluationCount();
processOutputJoints(triggersOut);
context.addStateMachineInfo(_id, _currentState->getID(), _previousState->getID(), _duringInterp, _alpha);
@ -165,8 +168,16 @@ void AnimRandomSwitch::addState(RandomSwitchState::Pointer randomState) {
}
void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const AnimContext& context, RandomSwitchState::Pointer desiredState, bool shouldInterp) {
auto prevStateNode = _children[_currentState->getChildIndex()];
auto nextStateNode = _children[desiredState->getChildIndex()];
// activate/deactivate states
prevStateNode->setActive(false);
nextStateNode->setActive(true);
_lastPlayedState = nextStateNode->getID();
if (shouldInterp) {
bool interpActive = _duringInterp;

View file

@ -151,10 +151,11 @@ protected:
// for AnimDebugDraw rendering
virtual const AnimPoseVec& getPosesInternal() const override;
virtual void setActiveInternal(bool active) override;
AnimPoseVec _poses;
int _randomSwitchEvaluationCount { 0 };
bool _triggerNewRandomState = false;
// interpolation state
bool _duringInterp = false;
InterpType _interpType { InterpType::SnapshotPrev };

View file

@ -128,6 +128,10 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon
auto prevStateNode = _children[_currentState->getChildIndex()];
auto nextStateNode = _children[desiredState->getChildIndex()];
// activate/deactivate states
prevStateNode->setActive(false);
nextStateNode->setActive(true);
bool interpActive = _duringInterp;
_duringInterp = true;
_alpha = 0.0f;