#include "Animation.h"
#include <cmath>
#include <unordered_map>
#include <string>
typedef std::unordered_map<std::string, CurveFunction> CurveFunctionMap;
CurveFunctionMap g_curveFunctionMap;
struct CurveMapIniter {
void map(const char* str, CurveFunction func) {
g_curveFunctionMap.insert(std::make_pair(str, func));
}
CurveMapIniter() {
printf("creating curve function mapper\n");
map("square", &squareCurve);
map("linear", &linearCurve);
map("easeIn", &easeInCurve);
map("easeOut", &easeOutCurve);
map("easeInOut", &easeInOutCurve);
map("easeOutIn", &easeOutInCurve);
map("easeInBack", &easeInBackCurve);
map("easeOutBack", &easeOutBackCurve);
map("easeInOutBack", &easeInOutBackCurve);
map("easeOutInBack", &easeOutInBackCurve);
map("easeInBounce", &easeInBounceCurve);
map("easeOutBounce", &easeOutBounceCurve);
map("easeInOutBounce", &easeInOutBounceCurve);
map("easeOutInBounce", &easeOutInBounceCurve);
map("easeInElastic;", &easeInElasticCurve);
map("easeOutElastic", &easeOutElasticCurve);
map("easeInOutElastic", &easeInOutElasticCurve);
map("easeOutInElastic", &easeOutInElasticCurve);
} } g_initCurveMapper;
bool LookupCurveFunction(const char* curveName, CurveFunction& curveFunction)
{
if (g_curveFunctionMap.count(curveName)) {
curveFunction = g_curveFunctionMap[curveName];
return true;
}
return false;
}
float EvaluateCurve(const char* curveName, float ratio)
{
if (g_curveFunctionMap.count(curveName))
return g_curveFunctionMap[curveName](ratio);
return 1.0f;
}
inline float square(float ratio)
{
//return powf(ratio, 2.0f);
return ratio * ratio;
}
inline float inOutHelper(float ratio, CurveFunction inCurve, CurveFunction outCurve)
{
if (ratio < 0.5f)
return 0.5f * inCurve(ratio*2.0f);
return 0.5f * outCurve((ratio-0.5f)*2.0f) + 0.5f;
}
float squareCurve(float ratio)
{
if (ratio < 0.5f)
return 0.0f;
return 1.0f;
}
float linearCurve(float ratio)
{
return ratio;
}
float easeInCurve(float ratio)
{
return ratio * ratio * ratio;
}
float easeOutCurve(float ratio)
{
float invRatio = ratio - 1.0f;
return invRatio * invRatio * invRatio + 1.0f;
}
float easeInOutCurve(float ratio)
{
return inOutHelper(ratio, easeInCurve, easeOutCurve);
}
float easeOutInCurve(float ratio)
{
return inOutHelper(ratio, easeOutCurve, easeInCurve);
}
float easeInBackCurve(float ratio)
{
float s = 1.70158f;
return square(ratio) * ((s + 1.0f)*ratio - s);
}
float easeOutBackCurve(float ratio)
{
float invRatio = ratio - 1.0f;
float s = 1.70158f;
return square(invRatio) * ((s + 1.0f)*invRatio + s) + 1.0f;
}
float easeInOutBackCurve(float ratio)
{
return inOutHelper(ratio, easeInBackCurve, easeOutBackCurve);
}
float easeOutInBackCurve(float ratio)
{
return inOutHelper(ratio, easeOutBackCurve, easeInBackCurve);
}
float easeInBounceCurve(float ratio)
{
return 1.0f - easeOutBounceCurve(1.0f - ratio);
}
float easeOutBounceCurve(float ratio)
{
const float s = 7.5625f;
const float p = 2.75f;
if (ratio < (1.0f/p))
return s * square(ratio);
if (ratio < (2.0f/p))
return s * square(ratio - 1.5f/p) + 0.75f;
if (ratio < 2.5f/p)
return s * square(ratio - 2.25f/p) + 0.9375f;
return s * square(ratio - 2.625f/p) + 0.984375f;
}
float easeInOutBounceCurve(float ratio)
{
return inOutHelper(ratio, easeInBounceCurve, easeOutBounceCurve);
}
float easeOutInBounceCurve(float ratio)
{
return inOutHelper(ratio, easeOutBounceCurve, easeInBounceCurve);
}
float easeInElasticCurve(float ratio)
{
if (ratio == 0.0f || ratio == 1.0f)
return ratio;
float p = 0.3f;
float s = p / 4.0f;
float invRatio = ratio - 1.0f;
return -1.0f * powf(2.0f, 10.0f*invRatio) * sinf((invRatio-s)*2.0f*M_PI/p);
}
float easeOutElasticCurve(float ratio)
{
if (ratio == 0.0f || ratio == 1.0f)
return ratio;
float p = 0.3f;
float s = p / 4.0f;
return powf(2.0f, -10.0f*ratio) * sinf((ratio-s)*2.0f*M_PI/p) + 1.0f;
}
float easeInOutElasticCurve(float ratio)
{
return inOutHelper(ratio, easeInElasticCurve, easeOutElasticCurve);
}
float easeOutInElasticCurve(float ratio)
{
return inOutHelper(ratio, easeOutElasticCurve, easeInElasticCurve);
}