//// AnimStateMachine.h//// Created by Anthony J. Thibault on 9/2/15.// Copyright (c) 2015 High Fidelity, Inc. All rights reserved.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//#ifndef hifi_AnimStateMachine_h#define hifi_AnimStateMachine_h#include <string>#include <vector>#include "AnimNode.h"#include "AnimUtil.h"// State Machine for transitioning between children AnimNodes//// This is mechinisim for playing animations and smoothly interpolating/fading// between them. A StateMachine has a set of States, which typically reference// child AnimNodes. Each State has a list of Transitions, which are evaluated// to determine when we should switch to a new State. Parameters for the smooth// interpolation/fading are read from the State that you are transitioning to.//// The currentState can be set directly via the setCurrentStateVar() and will override// any State transitions.//// Each State has two parameters that can be changed via AnimVars,// * interpTarget - (frames) The destination frame of the interpolation. i.e. the first frame of the animation that will// visible after interpolation is complete.// * interpDuration - (frames) The total length of time it will take to interp between the current pose and the// interpTarget frame.// * interpType - How the interpolation is performed.// * SnapshotBoth: Stores two snapshots, the previous animation before interpolation begins and the target state at the// interTarget frame. Then during the interpolation period the two snapshots are interpolated to produce smooth motion between them.// * SnapshotPrev: Stores a snapshot of the previous animation before interpolation begins. However the target state is// evaluated dynamically. During the interpolation period the previous snapshot is interpolated with the target pose// to produce smooth motion between them. This mode is useful for interping into a blended animation where the actual// blend factor is not known at the start of the interp or is might change dramatically during the interp.class AnimStateMachine : public AnimNode {public: friend class AnimNodeLoader; friend bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& nodeId, const QUrl& jsonUrl); enum class InterpType { SnapshotBoth = 0, SnapshotPrev, EvaluateBoth, NumTypes };protected: class State { public: friend AnimStateMachine; friend bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& nodeId, const QUrl& jsonUrl); using Pointer = std::shared_ptr<State>; using ConstPointer = std::shared_ptr<const State>; class Transition { public: friend AnimStateMachine; Transition(const QString& var, State::Pointer state) : _var(var), _state(state) {} protected: QString _var; State::Pointer _state; }; State(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType, EasingType easingType) : _id(id), _childIndex(childIndex), _interpTarget(interpTarget), _interpDuration(interpDuration), _interpType(interpType), _easingType(easingType) {} void setInterpTargetVar(const QString& interpTargetVar) { _interpTargetVar = interpTargetVar; } void setInterpDurationVar(const QString& interpDurationVar) { _interpDurationVar = interpDurationVar; } void setInterpTypeVar(const QString& interpTypeVar) { _interpTypeVar = interpTypeVar; } int getChildIndex() const { return _childIndex; } const QString& getID() const { return _id; } protected: void setInterpTarget(float interpTarget) { _interpTarget = interpTarget; } void setInterpDuration(float interpDuration) { _interpDuration = interpDuration; } void addTransition(const Transition& transition) { _transitions.push_back(transition); } QString _id; int _childIndex; float _interpTarget; // frames float _interpDuration; // frames InterpType _interpType; EasingType _easingType; QString _interpTargetVar; QString _interpDurationVar; QString _interpTypeVar; std::vector<Transition> _transitions; private: Q_DISABLE_COPY(State) };public: explicit AnimStateMachine(const QString& id); virtual ~AnimStateMachine() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override; void setCurrentStateVar(QString& currentStateVar) { _currentStateVar = currentStateVar; } const QString& getCurrentStateID() const;protected: void setCurrentState(State::Pointer state); void addState(State::Pointer state); void switchState(const AnimVariantMap& animVars, const AnimContext& context, State::Pointer desiredState); State::Pointer evaluateTransitions(const AnimVariantMap& animVars) const; // for AnimDebugDraw rendering virtual const AnimPoseVec& getPosesInternal() const override; AnimPoseVec _poses; // interpolation state bool _duringInterp = false; InterpType _interpType { InterpType::SnapshotPrev }; EasingType _easingType { EasingType_Linear }; float _alphaVel = 0.0f; float _alpha = 0.0f; AnimPoseVec _prevPoses; AnimPoseVec _nextPoses; State::Pointer _currentState; State::Pointer _previousState; std::vector<State::Pointer> _states; QString _currentStateVar;private: Q_DISABLE_COPY(AnimStateMachine)};#endif // hifi_AnimStateMachine_h
//
// AnimStateMachine.h
//
// Created by Anthony J. Thibault on 9/2/15.
// Copyright (c) 2015 High Fidelity, Inc. All rights reserved.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AnimStateMachine_h
#define hifi_AnimStateMachine_h
#include <string>
#include <vector>
#include "AnimNode.h"
#include "AnimUtil.h"
// State Machine for transitioning between children AnimNodes
//
// This is mechinisim for playing animations and smoothly interpolating/fading
// between them. A StateMachine has a set of States, which typically reference
// child AnimNodes. Each State has a list of Transitions, which are evaluated
// to determine when we should switch to a new State. Parameters for the smooth
// interpolation/fading are read from the State that you are transitioning to.
//
// The currentState can be set directly via the setCurrentStateVar() and will override
// any State transitions.
//
// Each State has two parameters that can be changed via AnimVars,
// * interpTarget - (frames) The destination frame of the interpolation. i.e. the first frame of the animation that will
// visible after interpolation is complete.
// * interpDuration - (frames) The total length of time it will take to interp between the current pose and the
// interpTarget frame.
// * interpType - How the interpolation is performed.
// * SnapshotBoth: Stores two snapshots, the previous animation before interpolation begins and the target state at the
// interTarget frame. Then during the interpolation period the two snapshots are interpolated to produce smooth motion between them.
// * SnapshotPrev: Stores a snapshot of the previous animation before interpolation begins. However the target state is
// evaluated dynamically. During the interpolation period the previous snapshot is interpolated with the target pose
// to produce smooth motion between them. This mode is useful for interping into a blended animation where the actual
// blend factor is not known at the start of the interp or is might change dramatically during the interp.
class AnimStateMachine : public AnimNode {
public:
friend class AnimNodeLoader;
friend bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& nodeId, const QUrl& jsonUrl);
enum class InterpType {
SnapshotBoth = 0,
SnapshotPrev,
EvaluateBoth,
NumTypes
};
protected:
class State {
public:
friend AnimStateMachine;
friend bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& nodeId, const QUrl& jsonUrl);
using Pointer = std::shared_ptr<State>;
using ConstPointer = std::shared_ptr<const State>;
class Transition {
public:
friend AnimStateMachine;
Transition(const QString& var, State::Pointer state) : _var(var), _state(state) {}
protected:
QString _var;
State::Pointer _state;
};
State(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType, EasingType easingType) :
_id(id),
_childIndex(childIndex),
_interpTarget(interpTarget),
_interpDuration(interpDuration),
_interpType(interpType),
_easingType(easingType) {}
void setInterpTargetVar(const QString& interpTargetVar) { _interpTargetVar = interpTargetVar; }
void setInterpDurationVar(const QString& interpDurationVar) { _interpDurationVar = interpDurationVar; }
void setInterpTypeVar(const QString& interpTypeVar) { _interpTypeVar = interpTypeVar; }
int getChildIndex() const { return _childIndex; }
const QString& getID() const { return _id; }
protected:
void setInterpTarget(float interpTarget) { _interpTarget = interpTarget; }
void setInterpDuration(float interpDuration) { _interpDuration = interpDuration; }
void addTransition(const Transition& transition) { _transitions.push_back(transition); }
QString _id;
int _childIndex;
float _interpTarget; // frames
float _interpDuration; // frames
InterpType _interpType;
EasingType _easingType;
QString _interpTargetVar;
QString _interpDurationVar;
QString _interpTypeVar;
std::vector<Transition> _transitions;
private:
Q_DISABLE_COPY(State)
};
public:
explicit AnimStateMachine(const QString& id);
virtual ~AnimStateMachine() override;
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override;
void setCurrentStateVar(QString& currentStateVar) { _currentStateVar = currentStateVar; }
const QString& getCurrentStateID() const;
protected:
void setCurrentState(State::Pointer state);
void addState(State::Pointer state);
void switchState(const AnimVariantMap& animVars, const AnimContext& context, State::Pointer desiredState);
State::Pointer evaluateTransitions(const AnimVariantMap& animVars) const;
// for AnimDebugDraw rendering
virtual const AnimPoseVec& getPosesInternal() const override;
AnimPoseVec _poses;
// interpolation state
bool _duringInterp = false;
InterpType _interpType { InterpType::SnapshotPrev };
EasingType _easingType { EasingType_Linear };
float _alphaVel = 0.0f;
float _alpha = 0.0f;
AnimPoseVec _prevPoses;
AnimPoseVec _nextPoses;
State::Pointer _currentState;
State::Pointer _previousState;
std::vector<State::Pointer> _states;
QString _currentStateVar;
private:
Q_DISABLE_COPY(AnimStateMachine)
};
#endif // hifi_AnimStateMachine_h