/* This file is part of RetroFE.
*
* RetroFE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RetroFE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RetroFE. If not, see .
*/
#include "Tween.h"
#include
#define _USE_MATH_DEFINES
#include
#include
std::map Tween::TweenTypeMap;
std::map Tween::TweenPropertyMap;
Tween::Tween(TweenProperty property, TweenAlgorithm type, double start, double end, double duration)
: Property(property)
, Type(type)
, Start(start)
, End(end)
, Duration(duration)
{
}
TweenProperty Tween::GetProperty() const
{
return Property;
}
bool Tween::GetTweenProperty(std::string name, TweenProperty &property)
{
bool retVal = false;
if(TweenPropertyMap.size() == 0)
{
TweenPropertyMap["x"] = TWEEN_PROPERTY_X;
TweenPropertyMap["y"] = TWEEN_PROPERTY_Y;
TweenPropertyMap["angle"] = TWEEN_PROPERTY_ANGLE;
TweenPropertyMap["alpha"] = TWEEN_PROPERTY_ALPHA;
TweenPropertyMap["width"] = TWEEN_PROPERTY_WIDTH;
TweenPropertyMap["height"] = TWEEN_PROPERTY_HEIGHT;
TweenPropertyMap["xorigin"] = TWEEN_PROPERTY_X_ORIGIN;
TweenPropertyMap["yorigin"] = TWEEN_PROPERTY_Y_ORIGIN;
TweenPropertyMap["xoffset"] = TWEEN_PROPERTY_X_OFFSET;
TweenPropertyMap["yoffset"] = TWEEN_PROPERTY_Y_OFFSET;
TweenPropertyMap["fontSize"] = TWEEN_PROPERTY_FONT_SIZE;
}
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
if(TweenPropertyMap.find(name) != TweenPropertyMap.end())
{
property = TweenPropertyMap[name];
retVal = true;
}
return retVal;
}
TweenAlgorithm Tween::GetTweenType(std::string name)
{
if(TweenTypeMap.size() == 0)
{
TweenTypeMap["easeinquadratic"] = EASE_IN_QUADRATIC;
TweenTypeMap["easeoutquadratic"] = EASE_OUT_QUADRATIC;
TweenTypeMap["easeinoutquadratic"] = EASE_INOUT_QUADRATIC;
TweenTypeMap["easeincubic"] = EASE_IN_CUBIC;
TweenTypeMap["easeoutcubic"] = EASE_OUT_CUBIC;
TweenTypeMap["easeinoutcubic"] = EASE_INOUT_CUBIC;
TweenTypeMap["easeinquartic"] = EASE_IN_QUARTIC;
TweenTypeMap["easeoutquartic"] = EASE_OUT_QUARTIC;
TweenTypeMap["easeinoutquartic"] = EASE_INOUT_QUARTIC;
TweenTypeMap["easeinquintic"] = EASE_IN_QUINTIC;
TweenTypeMap["easeoutquintic"] = EASE_OUT_QUINTIC;
TweenTypeMap["easeinoutquintic"] = EASE_INOUT_QUINTIC;
TweenTypeMap["easeinsine"] = EASE_IN_SINE;
TweenTypeMap["easeoutsine"] = EASE_OUT_SINE;
TweenTypeMap["easeinoutsine"] = EASE_INOUT_SINE;
TweenTypeMap["easeinexponential"] = EASE_IN_EXPONENTIAL;
TweenTypeMap["easeoutexponential"] = EASE_OUT_EXPONENTIAL;
TweenTypeMap["easeinoutexponential"] = EASE_INOUT_EXPONENTIAL;
TweenTypeMap["easeincircular"] = EASE_IN_CIRCULAR;
TweenTypeMap["easeoutcircular"] = EASE_OUT_CIRCULAR;
TweenTypeMap["easeinoutcircular"] = EASE_INOUT_CIRCULAR;
TweenTypeMap["linear"] = LINEAR;
}
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
if(TweenTypeMap.find(name) != TweenTypeMap.end())
{
return TweenTypeMap[name];
}
else
{
return TweenTypeMap["linear"];
}
}
float Tween::Animate(double elapsedTime)
{
return AnimateSingle(Type, Start, End, Duration, elapsedTime);
}
//todo: SDL likes floats, consider having casting being performed elsewhere
float Tween::AnimateSingle(TweenAlgorithm type, double start, double end, double duration, double elapsedTime)
{
double a = start;
double b = end - start;
double result = 0;
switch(type)
{
case EASE_IN_QUADRATIC:
result = EaseInQuadratic(elapsedTime, duration, a, b);
break;
case EASE_OUT_QUADRATIC:
result = EaseOutQuadratic(elapsedTime, duration, a, b);
break;
case EASE_INOUT_QUADRATIC:
result = EaseInOutQuadratic(elapsedTime, duration, a, b);
break;
case EASE_IN_CUBIC:
result = EaseInCubic(elapsedTime, duration, a, b);
break;
case EASE_OUT_CUBIC:
result = EaseOutCubic(elapsedTime, duration, a, b);
break;
case EASE_INOUT_CUBIC:
result = EaseInOutCubic(elapsedTime, duration, a, b);
break;
case EASE_IN_QUARTIC:
result = EaseInQuartic(elapsedTime, duration, a, b);
break;
case EASE_OUT_QUARTIC:
result = EaseOutQuartic(elapsedTime, duration, a, b);
break;
case EASE_INOUT_QUARTIC:
result = EaseInOutQuartic(elapsedTime, duration, a, b);
break;
case EASE_IN_QUINTIC:
result = EaseInQuintic(elapsedTime, duration, a, b);
break;
case EASE_OUT_QUINTIC:
result = EaseOutQuintic(elapsedTime, duration, a, b);
break;
case EASE_INOUT_QUINTIC:
result = EaseInOutQuintic(elapsedTime, duration, a, b);
break;
case EASE_IN_SINE:
result = EaseInSine(elapsedTime, duration, a, b);
break;
case EASE_OUT_SINE:
result = EaseOutSine(elapsedTime, duration, a, b);
break;
case EASE_INOUT_SINE:
result = EaseInOutSine(elapsedTime, duration, a, b);
break;
case EASE_IN_EXPONENTIAL:
result = EaseInExponential(elapsedTime, duration, a, b);
break;
case EASE_OUT_EXPONENTIAL:
result = EaseOutExponential(elapsedTime, duration, a, b);
break;
case EASE_INOUT_EXPONENTIAL:
result = EaseInOutExponential(elapsedTime, duration, a, b);
break;
case EASE_IN_CIRCULAR:
result = EaseInCircular(elapsedTime, duration, a, b);
break;
case EASE_OUT_CIRCULAR:
result = EaseOutCircular(elapsedTime, duration, a, b);
break;
case EASE_INOUT_CIRCULAR:
result = EaseInOutCircular(elapsedTime, duration, a, b);
break;
case LINEAR:
default:
result = Linear(elapsedTime, duration, a, b);
break;
}
return static_cast(result);
}
double Tween::Linear(double t, double d, double b, double c)
{
if(d == 0) return b;
return c*t/d + b;
};
double Tween::EaseInQuadratic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return c*t*t + b;
};
double Tween::EaseOutQuadratic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return -c * t*(t-2) + b;
};
double Tween::EaseInOutQuadratic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};
double Tween::EaseInCubic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return c*t*t*t + b;
};
double Tween::EaseOutCubic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
t--;
return c*(t*t*t + 1) + b;
};
double Tween::EaseInOutCubic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d/2;
if (t < 1) return c/2*t*t*t + b;
t -= 2;
return c/2*(t*t*t + 2) + b;
};
double Tween::EaseInQuartic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return c*t*t*t*t + b;
};
double Tween::EaseOutQuartic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
t--;
return -c * (t*t*t*t - 1) + b;
};
double Tween::EaseInOutQuartic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d/2;
if (t < 1) return c/2*t*t*t*t + b;
t -= 2;
return -c/2 * (t*t*t*t - 2) + b;
};
double Tween::EaseInQuintic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
return c*t*t*t*t*t + b;
};
double Tween::EaseOutQuintic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d;
t--;
return c*(t*t*t*t*t + 1) + b;
};
double Tween::EaseInOutQuintic(double t, double d, double b, double c)
{
if(d == 0) return b;
t /= d/2;
if (t < 1) return c/2*t*t*t*t*t + b;
t -= 2;
return c/2*(t*t*t*t*t + 2) + b;
};
double Tween::EaseInSine(double t, double d, double b, double c)
{
return -c * cos(t/d * (M_PI/2)) + c + b;
};
double Tween::EaseOutSine(double t, double d, double b, double c)
{
return c * sin(t/d * (M_PI/2)) + b;
};
double Tween::EaseInOutSine(double t, double d, double b, double c)
{
return -c/2 * (cos( M_PI*t/d) - 1) + b;
};
double Tween::EaseInExponential(double t, double d, double b, double c)
{
return c * pow( 2, 10 * (t/d - 1) ) + b;
};
double Tween::EaseOutExponential(double t, double d, double b, double c)
{
return c * ( - pow( 2, -10 * t/d ) + 1 ) + b;
};
double Tween::EaseInOutExponential(double t, double d, double b, double c)
{
t /= d/2;
if (t < 1) return c/2 * pow( 2, 10 * (t - 1) ) + b;
t--;
return c/2 * ( -1* pow( 2, -10 * t) + 2 ) + b;
};
double Tween::EaseInCircular(double t, double d, double b, double c)
{
t /= d;
return -c * (sqrt(1 - t*t) - 1) + b;
};
double Tween::EaseOutCircular(double t, double d, double b, double c)
{
t /= d;
t--;
return c * sqrt(1 - t*t) + b;
};
double Tween::EaseInOutCircular(double t, double d, double b, double c)
{
t /= d/2;
if (t < 1) return -c/2 * (sqrt(1 - t*t) - 1) + b;
t -= 2;
return c/2 * (sqrt(1 - t*t) + 1) + b;
}
;
//todo: sdl requires floats, should the casting be done at this layer?
float Tween::GetDuration() const
{
return static_cast(Duration);
}