mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Support for EvaluteBoth interpType and easing
This commit is contained in:
parent
ee4bb233b9
commit
ec08139a46
7 changed files with 230 additions and 11 deletions
|
@ -29,6 +29,7 @@
|
|||
#include "AnimTwoBoneIK.h"
|
||||
#include "AnimSplineIK.h"
|
||||
#include "AnimPoleVectorConstraint.h"
|
||||
#include "AnimUtil.h"
|
||||
|
||||
using NodeLoaderFunc = AnimNode::Pointer (*)(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||
using NodeProcessFunc = bool (*)(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||
|
@ -91,6 +92,8 @@ static AnimStateMachine::InterpType stringToInterpType(const QString& str) {
|
|||
return AnimStateMachine::InterpType::SnapshotBoth;
|
||||
} else if (str == "snapshotPrev") {
|
||||
return AnimStateMachine::InterpType::SnapshotPrev;
|
||||
} else if (str == "evaluateBoth") {
|
||||
return AnimStateMachine::InterpType::EvaluateBoth;
|
||||
} else {
|
||||
return AnimStateMachine::InterpType::NumTypes;
|
||||
}
|
||||
|
@ -101,11 +104,61 @@ static AnimRandomSwitch::InterpType stringToRandomInterpType(const QString& str)
|
|||
return AnimRandomSwitch::InterpType::SnapshotBoth;
|
||||
} else if (str == "snapshotPrev") {
|
||||
return AnimRandomSwitch::InterpType::SnapshotPrev;
|
||||
} else if (str == "evaluateBoth") {
|
||||
return AnimRandomSwitch::InterpType::EvaluateBoth;
|
||||
} else {
|
||||
return AnimRandomSwitch::InterpType::NumTypes;
|
||||
}
|
||||
}
|
||||
|
||||
static EasingType stringToEasingType(const QString& str) {
|
||||
if (str == "easeInSine") {
|
||||
return EasingType_EaseInSine;
|
||||
} else if (str == "easeOutSine") {
|
||||
return EasingType_EaseOutSine;
|
||||
} else if (str == "easeInOutSine") {
|
||||
return EasingType_EaseInOutSine;
|
||||
} else if (str == "easeInQuad") {
|
||||
return EasingType_EaseInQuad;
|
||||
} else if (str == "easeOutQuad") {
|
||||
return EasingType_EaseOutQuad;
|
||||
} else if (str == "easeInOutQuad") {
|
||||
return EasingType_EaseInOutQuad;
|
||||
} else if (str == "easeInCubic") {
|
||||
return EasingType_EaseInCubic;
|
||||
} else if (str == "easeOutCubic") {
|
||||
return EasingType_EaseOutCubic;
|
||||
} else if (str == "easeInOutCubic") {
|
||||
return EasingType_EaseInOutCubic;
|
||||
} else if (str == "easeInQuart") {
|
||||
return EasingType_EaseInQuart;
|
||||
} else if (str == "easeOutQuart") {
|
||||
return EasingType_EaseOutQuart;
|
||||
} else if (str == "easeInOutQuart") {
|
||||
return EasingType_EaseInOutQuart;
|
||||
} else if (str == "easeInQuint") {
|
||||
return EasingType_EaseInQuint;
|
||||
} else if (str == "easeOutQuint") {
|
||||
return EasingType_EaseOutQuint;
|
||||
} else if (str == "easeInOutQuint") {
|
||||
return EasingType_EaseInOutQuint;
|
||||
} else if (str == "easeInExpo") {
|
||||
return EasingType_EaseInExpo;
|
||||
} else if (str == "easeOutExpo") {
|
||||
return EasingType_EaseOutExpo;
|
||||
} else if (str == "easeInOutExpo") {
|
||||
return EasingType_EaseInOutExpo;
|
||||
} else if (str == "easeInCirc") {
|
||||
return EasingType_EaseInCirc;
|
||||
} else if (str == "easeOutCirc") {
|
||||
return EasingType_EaseOutCirc;
|
||||
} else if (str == "easeInOutCirc") {
|
||||
return EasingType_EaseInOutCirc;
|
||||
} else {
|
||||
return EasingType_NumTypes;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* animManipulatorJointVarTypeToString(AnimManipulator::JointVar::Type type) {
|
||||
switch (type) {
|
||||
case AnimManipulator::JointVar::Type::Absolute: return "absolute";
|
||||
|
@ -723,6 +776,7 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj,
|
|||
READ_FLOAT(interpTarget, stateObj, nodeId, jsonUrl, false);
|
||||
READ_FLOAT(interpDuration, stateObj, nodeId, jsonUrl, false);
|
||||
READ_OPTIONAL_STRING(interpType, stateObj);
|
||||
READ_OPTIONAL_STRING(easingType, stateObj);
|
||||
|
||||
READ_OPTIONAL_STRING(interpTargetVar, stateObj);
|
||||
READ_OPTIONAL_STRING(interpDurationVar, stateObj);
|
||||
|
@ -743,7 +797,16 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj,
|
|||
}
|
||||
}
|
||||
|
||||
auto statePtr = std::make_shared<AnimStateMachine::State>(id, iter->second, interpTarget, interpDuration, interpTypeEnum);
|
||||
EasingType easingTypeEnum = EasingType_Linear; // default value
|
||||
if (!easingType.isEmpty()) {
|
||||
easingTypeEnum = stringToEasingType(easingType);
|
||||
if (easingTypeEnum == EasingType_NumTypes) {
|
||||
qCCritical(animation) << "AnimNodeLoader, bad easingType on stateMachine state, nodeId = " << nodeId << "stateId =" << id;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto statePtr = std::make_shared<AnimStateMachine::State>(id, iter->second, interpTarget, interpDuration, interpTypeEnum, easingTypeEnum);
|
||||
assert(statePtr);
|
||||
|
||||
if (!interpTargetVar.isEmpty()) {
|
||||
|
@ -845,6 +908,7 @@ bool processRandomSwitchStateMachineNode(AnimNode::Pointer node, const QJsonObje
|
|||
READ_FLOAT(interpTarget, stateObj, nodeId, jsonUrl, false);
|
||||
READ_FLOAT(interpDuration, stateObj, nodeId, jsonUrl, false);
|
||||
READ_OPTIONAL_STRING(interpType, stateObj);
|
||||
READ_OPTIONAL_STRING(easingType, stateObj);
|
||||
READ_FLOAT(priority, stateObj, nodeId, jsonUrl, false);
|
||||
READ_BOOL(resume, stateObj, nodeId, jsonUrl, false);
|
||||
|
||||
|
@ -867,7 +931,16 @@ bool processRandomSwitchStateMachineNode(AnimNode::Pointer node, const QJsonObje
|
|||
}
|
||||
}
|
||||
|
||||
auto randomStatePtr = std::make_shared<AnimRandomSwitch::RandomSwitchState>(id, iter->second, interpTarget, interpDuration, interpTypeEnum, priority, resume);
|
||||
EasingType easingTypeEnum = EasingType_Linear; // default value
|
||||
if (!easingType.isEmpty()) {
|
||||
easingTypeEnum = stringToEasingType(easingType);
|
||||
if (easingTypeEnum == EasingType_NumTypes) {
|
||||
qCCritical(animation) << "AnimNodeLoader, bad easingType on randomSwitch state, nodeId = " << nodeId << "stateId =" << id;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto randomStatePtr = std::make_shared<AnimRandomSwitch::RandomSwitchState>(id, iter->second, interpTarget, interpDuration, interpTypeEnum, easingTypeEnum, priority, resume);
|
||||
if (priority > 0.0f) {
|
||||
smNode->addToPrioritySum(priority);
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
|||
|
||||
assert(_currentState);
|
||||
auto currentStateNode = _children[_currentState->getChildIndex()];
|
||||
auto previousStateNode = _children[_previousState->getChildIndex()];
|
||||
assert(currentStateNode);
|
||||
|
||||
if (_duringInterp) {
|
||||
|
@ -97,6 +98,7 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
|||
AnimPoseVec* nextPoses = nullptr;
|
||||
AnimPoseVec* prevPoses = nullptr;
|
||||
AnimPoseVec localNextPoses;
|
||||
AnimPoseVec localPrevPoses;
|
||||
if (_interpType == InterpType::SnapshotBoth) {
|
||||
// interp between both snapshots
|
||||
prevPoses = &_prevPoses;
|
||||
|
@ -107,13 +109,18 @@ const AnimPoseVec& AnimRandomSwitch::evaluate(const AnimVariantMap& animVars, co
|
|||
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||
prevPoses = &_prevPoses;
|
||||
nextPoses = &localNextPoses;
|
||||
} else if (_interpType == InterpType::EvaluateBoth) {
|
||||
localPrevPoses = previousStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||
prevPoses = &localPrevPoses;
|
||||
nextPoses = &localNextPoses;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
if (_poses.size() > 0 && nextPoses && prevPoses && nextPoses->size() > 0 && prevPoses->size() > 0) {
|
||||
::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), _alpha, &_poses[0]);
|
||||
::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), easingFunc(_alpha, _easingType), &_poses[0]);
|
||||
}
|
||||
context.setDebugAlpha(_currentState->getID(), _alpha * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType());
|
||||
context.setDebugAlpha(_currentState->getID(), easingFunc(_alpha, _easingType) * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType());
|
||||
} else {
|
||||
_duringInterp = false;
|
||||
_prevPoses.clear();
|
||||
|
@ -160,6 +167,7 @@ void AnimRandomSwitch::switchRandomState(const AnimVariantMap& animVars, const A
|
|||
float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration));
|
||||
_alphaVel = FRAMES_PER_SECOND / duration;
|
||||
_interpType = (InterpType)animVars.lookup(desiredState->_interpTypeVar, (int)desiredState->_interpType);
|
||||
_easingType = desiredState->_easingType;
|
||||
|
||||
// because dt is 0, we should not encounter any triggers
|
||||
const float dt = 0.0f;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include "AnimNode.h"
|
||||
#include "AnimUtil.h"
|
||||
|
||||
// Random Switch State Machine for random transitioning between children AnimNodes
|
||||
//
|
||||
|
@ -51,6 +52,7 @@ public:
|
|||
enum class InterpType {
|
||||
SnapshotBoth = 0,
|
||||
SnapshotPrev,
|
||||
EvaluateBoth,
|
||||
NumTypes
|
||||
};
|
||||
|
||||
|
@ -73,12 +75,13 @@ protected:
|
|||
RandomSwitchState::Pointer _randomSwitchState;
|
||||
};
|
||||
|
||||
RandomSwitchState(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType, float priority, bool resume) :
|
||||
RandomSwitchState(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType, EasingType easingType, float priority, bool resume) :
|
||||
_id(id),
|
||||
_childIndex(childIndex),
|
||||
_interpTarget(interpTarget),
|
||||
_interpDuration(interpDuration),
|
||||
_interpType(interpType),
|
||||
_easingType(easingType),
|
||||
_priority(priority),
|
||||
_resume(resume){
|
||||
}
|
||||
|
@ -106,6 +109,7 @@ protected:
|
|||
float _interpTarget; // frames
|
||||
float _interpDuration; // frames
|
||||
InterpType _interpType;
|
||||
EasingType _easingType;
|
||||
float _priority {0.0f};
|
||||
bool _resume {false};
|
||||
|
||||
|
@ -154,7 +158,8 @@ protected:
|
|||
int _randomSwitchEvaluationCount { 0 };
|
||||
// interpolation state
|
||||
bool _duringInterp = false;
|
||||
InterpType _interpType{ InterpType::SnapshotPrev };
|
||||
InterpType _interpType { InterpType::SnapshotPrev };
|
||||
EasingType _easingType { EasingType_Linear };
|
||||
float _alphaVel = 0.0f;
|
||||
float _alpha = 0.0f;
|
||||
AnimPoseVec _prevPoses;
|
||||
|
|
|
@ -48,6 +48,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co
|
|||
|
||||
assert(_currentState);
|
||||
auto currentStateNode = _children[_currentState->getChildIndex()];
|
||||
auto previousStateNode = _children[_previousState->getChildIndex()];
|
||||
assert(currentStateNode);
|
||||
|
||||
if (_duringInterp) {
|
||||
|
@ -56,6 +57,8 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co
|
|||
AnimPoseVec* nextPoses = nullptr;
|
||||
AnimPoseVec* prevPoses = nullptr;
|
||||
AnimPoseVec localNextPoses;
|
||||
AnimPoseVec localPrevPoses;
|
||||
|
||||
if (_interpType == InterpType::SnapshotBoth) {
|
||||
// interp between both snapshots
|
||||
prevPoses = &_prevPoses;
|
||||
|
@ -66,13 +69,18 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co
|
|||
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||
prevPoses = &_prevPoses;
|
||||
nextPoses = &localNextPoses;
|
||||
} else if (_interpType == InterpType::EvaluateBoth) {
|
||||
localPrevPoses = previousStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||
localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
|
||||
prevPoses = &localPrevPoses;
|
||||
nextPoses = &localNextPoses;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
if (_poses.size() > 0 && nextPoses && prevPoses && nextPoses->size() > 0 && prevPoses->size() > 0) {
|
||||
::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), _alpha, &_poses[0]);
|
||||
::blend(_poses.size(), &(prevPoses->at(0)), &(nextPoses->at(0)), easingFunc(_alpha, _easingType), &_poses[0]);
|
||||
}
|
||||
context.setDebugAlpha(_currentState->getID(), _alpha * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType());
|
||||
context.setDebugAlpha(_currentState->getID(), easingFunc(_alpha, _easingType) * parentDebugAlpha, _children[_currentState->getChildIndex()]->getType());
|
||||
} else {
|
||||
_duringInterp = false;
|
||||
_prevPoses.clear();
|
||||
|
@ -125,6 +133,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimCon
|
|||
float duration = std::max(0.001f, animVars.lookup(desiredState->_interpDurationVar, desiredState->_interpDuration));
|
||||
_alphaVel = FRAMES_PER_SECOND / duration;
|
||||
_interpType = (InterpType)animVars.lookup(desiredState->_interpTypeVar, (int)desiredState->_interpType);
|
||||
_easingType = desiredState->_easingType;
|
||||
|
||||
// because dt is 0, we should not encounter any triggers
|
||||
const float dt = 0.0f;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include "AnimNode.h"
|
||||
#include "AnimUtil.h"
|
||||
|
||||
// State Machine for transitioning between children AnimNodes
|
||||
//
|
||||
|
@ -47,6 +48,7 @@ public:
|
|||
enum class InterpType {
|
||||
SnapshotBoth = 0,
|
||||
SnapshotPrev,
|
||||
EvaluateBoth,
|
||||
NumTypes
|
||||
};
|
||||
|
||||
|
@ -69,12 +71,13 @@ protected:
|
|||
State::Pointer _state;
|
||||
};
|
||||
|
||||
State(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType) :
|
||||
State(const QString& id, int childIndex, float interpTarget, float interpDuration, InterpType interpType, EasingType easingType) :
|
||||
_id(id),
|
||||
_childIndex(childIndex),
|
||||
_interpTarget(interpTarget),
|
||||
_interpDuration(interpDuration),
|
||||
_interpType(interpType) {}
|
||||
_interpType(interpType),
|
||||
_easingType(easingType) {}
|
||||
|
||||
void setInterpTargetVar(const QString& interpTargetVar) { _interpTargetVar = interpTargetVar; }
|
||||
void setInterpDurationVar(const QString& interpDurationVar) { _interpDurationVar = interpDurationVar; }
|
||||
|
@ -95,6 +98,7 @@ protected:
|
|||
float _interpTarget; // frames
|
||||
float _interpDuration; // frames
|
||||
InterpType _interpType;
|
||||
EasingType _easingType;
|
||||
|
||||
QString _interpTargetVar;
|
||||
QString _interpDurationVar;
|
||||
|
@ -135,6 +139,7 @@ protected:
|
|||
// interpolation state
|
||||
bool _duringInterp = false;
|
||||
InterpType _interpType { InterpType::SnapshotPrev };
|
||||
EasingType _easingType { EasingType_Linear };
|
||||
float _alphaVel = 0.0f;
|
||||
float _alpha = 0.0f;
|
||||
AnimPoseVec _prevPoses;
|
||||
|
|
|
@ -211,3 +211,95 @@ bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// See https://easings.net/en# for a graphical visualiztion of easing types.
|
||||
float easingFunc(float alpha, EasingType type) {
|
||||
switch (type) {
|
||||
case EasingType_Linear:
|
||||
return alpha;
|
||||
case EasingType_EaseInSine:
|
||||
return sinf((alpha - 1.0f) * PI_OVER_TWO) + 1.0f;
|
||||
case EasingType_EaseOutSine:
|
||||
return sinf(alpha * PI_OVER_TWO);
|
||||
case EasingType_EaseInOutSine:
|
||||
return 0.5f * (1.0f - cos(alpha * PI));
|
||||
case EasingType_EaseInQuad:
|
||||
return alpha * alpha;
|
||||
case EasingType_EaseOutQuad:
|
||||
return -(alpha * (alpha - 2.0f));
|
||||
case EasingType_EaseInOutQuad:
|
||||
return (alpha < 0.5f) ? (2.0f * alpha * alpha) : ((-2.0f * alpha * alpha) + (4.0f * alpha) - 1.0f);
|
||||
case EasingType_EaseInCubic:
|
||||
return alpha * alpha * alpha;
|
||||
case EasingType_EaseOutCubic:
|
||||
{
|
||||
float temp = alpha - 1.0f;
|
||||
return temp * temp * temp + 1.0f;
|
||||
}
|
||||
case EasingType_EaseInOutCubic:
|
||||
if (alpha < 0.5f) {
|
||||
return 4.0f * alpha * alpha * alpha;
|
||||
} else {
|
||||
float temp = ((2.0f * alpha) - 2.0f);
|
||||
return 0.5f * temp * temp * temp + 1.0f;
|
||||
}
|
||||
break;
|
||||
case EasingType_EaseInQuart:
|
||||
return alpha * alpha * alpha * alpha;
|
||||
case EasingType_EaseOutQuart:
|
||||
{
|
||||
float temp = alpha - 1.0f;
|
||||
return temp * temp * temp * (1.0f - alpha) + 1.0f;
|
||||
}
|
||||
break;
|
||||
case EasingType_EaseInOutQuart:
|
||||
if (alpha < 0.5f) {
|
||||
return 8.0f * alpha * alpha * alpha * alpha;
|
||||
} else {
|
||||
float temp = alpha - 1.0f;
|
||||
return -8.0f * temp * temp * temp * temp + 1.0f;
|
||||
}
|
||||
break;
|
||||
case EasingType_EaseInQuint:
|
||||
return alpha * alpha * alpha * alpha * alpha;
|
||||
case EasingType_EaseOutQuint:
|
||||
{
|
||||
float temp = (alpha - 1.0f);
|
||||
return temp * temp * temp * temp * temp + 1.0f;
|
||||
}
|
||||
case EasingType_EaseInOutQuint:
|
||||
if (alpha < 0.5f) {
|
||||
return 16.0f * alpha * alpha * alpha * alpha * alpha;
|
||||
} else {
|
||||
float temp = ((2.0f * alpha) - 2.0f);
|
||||
return 0.5f * temp * temp * temp * temp * temp + 1.0f;
|
||||
}
|
||||
break;
|
||||
case EasingType_EaseInExpo:
|
||||
return (alpha == 0.0f) ? alpha : powf(2.0f, 10.0f * (alpha - 1.0f));
|
||||
case EasingType_EaseOutExpo:
|
||||
return (alpha == 1.0f) ? alpha : 1.0f - powf(2.0f, -10.0f * alpha);
|
||||
case EasingType_EaseInOutExpo:
|
||||
if (alpha == 0.0f || alpha == 1.0f)
|
||||
return alpha;
|
||||
else if (alpha < 0.5) {
|
||||
return 0.5f * powf(2.0f, (20.0f * alpha) - 10.0f);
|
||||
} else {
|
||||
return -0.5f * powf(2.0f, (-20.0f * alpha) + 10.0f) + 1.0f;
|
||||
}
|
||||
break;
|
||||
case EasingType_EaseInCirc:
|
||||
return 1.0f - sqrtf(1.0f - (alpha * alpha));
|
||||
case EasingType_EaseOutCirc:
|
||||
return sqrtf((2.0f - alpha) * alpha);
|
||||
case EasingType_EaseInOutCirc:
|
||||
if (alpha < 0.5f) {
|
||||
return 0.5f * (1.0f - sqrtf(1.0f - 4.0f * (alpha * alpha)));
|
||||
} else {
|
||||
return 0.5f * (sqrtf(-((2.0f * alpha) - 3.0f) * ((2.0f * alpha) - 1.0f)) + 1.0f);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return alpha;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,10 +128,37 @@ protected:
|
|||
bool _snapshotValid { false };
|
||||
};
|
||||
|
||||
|
||||
// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose.
|
||||
// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward
|
||||
// such that it lies on the surface of the kdop.
|
||||
bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut);
|
||||
|
||||
enum EasingType {
|
||||
EasingType_Linear,
|
||||
EasingType_EaseInSine,
|
||||
EasingType_EaseOutSine,
|
||||
EasingType_EaseInOutSine,
|
||||
EasingType_EaseInQuad,
|
||||
EasingType_EaseOutQuad,
|
||||
EasingType_EaseInOutQuad,
|
||||
EasingType_EaseInCubic,
|
||||
EasingType_EaseOutCubic,
|
||||
EasingType_EaseInOutCubic,
|
||||
EasingType_EaseInQuart,
|
||||
EasingType_EaseOutQuart,
|
||||
EasingType_EaseInOutQuart,
|
||||
EasingType_EaseInQuint,
|
||||
EasingType_EaseOutQuint,
|
||||
EasingType_EaseInOutQuint,
|
||||
EasingType_EaseInExpo,
|
||||
EasingType_EaseOutExpo,
|
||||
EasingType_EaseInOutExpo,
|
||||
EasingType_EaseInCirc,
|
||||
EasingType_EaseOutCirc,
|
||||
EasingType_EaseInOutCirc,
|
||||
EasingType_NumTypes
|
||||
};
|
||||
|
||||
float easingFunc(float alpha, EasingType type);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue