Files
hot-step-cpp-ROCm/engine/vendor/vst3sdk/vstgui4/vstgui/lib/animation/timingfunctions.cpp
T
2026-08-16 18:24:52 +07:00

220 lines
7.1 KiB
C++

// This file is part of VSTGUI. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
#include "timingfunctions.h"
#include "../vstguibase.h"
#include <cmath>
namespace VSTGUI {
namespace Animation {
//------------------------------------------------------------------------
/*! @defgroup AnimationTimingFunctions Animation Timing Functions
* @ingroup animation
*/
//------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
LinearTimingFunction::LinearTimingFunction (uint32_t length)
: TimingFunctionBase (length)
{
}
//-----------------------------------------------------------------------------
float LinearTimingFunction::getPosition (uint32_t milliseconds)
{
float pos = ((float)milliseconds) / ((float)length);
if (pos > 1.f)
pos = 1.f;
else if (pos < 0.f)
pos = 0.f;
return pos;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
PowerTimingFunction::PowerTimingFunction (uint32_t length, float factor)
: TimingFunctionBase (length)
, factor (factor)
{
}
//-----------------------------------------------------------------------------
float PowerTimingFunction::getPosition (uint32_t milliseconds)
{
float pos = ((float)milliseconds) / ((float)length);
pos = std::pow (pos, factor);
if (pos > 1.f)
pos = 1.f;
else if (pos < 0.f)
pos = 0.f;
return pos;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
InterpolationTimingFunction::InterpolationTimingFunction (uint32_t length, float startPos, float endPos)
: TimingFunctionBase (length)
{
addPoint (0.f, startPos);
addPoint (1.f, endPos);
}
//-----------------------------------------------------------------------------
void InterpolationTimingFunction::addPoint (float time, float pos)
{
points.emplace ((uint32_t)((float)getLength () * time), pos);
}
//-----------------------------------------------------------------------------
float InterpolationTimingFunction::getPosition (uint32_t milliseconds)
{
uint32_t prevTime = getLength ();
float prevPos = points[prevTime];
PointMap::reverse_iterator it = points.rbegin ();
while (it != points.rend ())
{
uint32_t time = it->first;
float pos = it->second;
if (time == milliseconds)
return pos;
else if (time <= milliseconds && prevTime > milliseconds)
{
double timePos = (double)(milliseconds - time) / (double)(prevTime - time);
return static_cast<float> (static_cast<double> (pos) + ((static_cast<double> (prevPos) - static_cast<double> (pos)) * timePos));
}
prevTime = time;
prevPos = pos;
++it;
}
return 1.f;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CubicBezierTimingFunction::CubicBezierTimingFunction (uint32_t milliseconds, CPoint p1, CPoint p2)
: TimingFunctionBase (milliseconds), p1 (p1), p2 (p2)
{
}
//-----------------------------------------------------------------------------
CPoint CubicBezierTimingFunction::lerp (CPoint p1, CPoint p2, float pos)
{
return p1 * (1.f - pos) + p2 * pos;
}
//-----------------------------------------------------------------------------
float CubicBezierTimingFunction::getPosition (uint32_t milliseconds)
{
constexpr CPoint p0 (0, 0);
constexpr CPoint p3 (1, 1);
auto t = static_cast<float> (milliseconds) / static_cast<float> (length);
auto a = lerp (p0, p1, t);
auto b = lerp (p1, p2, t);
auto c = lerp (p2, p3, t);
auto d = lerp (a, b, t);
auto e = lerp (b, c, t);
auto result = lerp (d, e, t).y;
return static_cast<float> (result);
}
//-----------------------------------------------------------------------------
CubicBezierTimingFunction CubicBezierTimingFunction::easy (uint32_t time)
{
return CubicBezierTimingFunction (time, CPoint (0.25, 0.1), CPoint (0.25, 1.));
}
//-----------------------------------------------------------------------------
CubicBezierTimingFunction CubicBezierTimingFunction::easyIn (uint32_t time)
{
return CubicBezierTimingFunction (time, CPoint (0.42, 0.), CPoint (1., 1.));
}
//-----------------------------------------------------------------------------
CubicBezierTimingFunction CubicBezierTimingFunction::easyOut (uint32_t time)
{
return CubicBezierTimingFunction (time, CPoint (0., 0.), CPoint (0.58, 1.));
}
//-----------------------------------------------------------------------------
CubicBezierTimingFunction CubicBezierTimingFunction::easyInOut (uint32_t time)
{
return CubicBezierTimingFunction (time, CPoint (0.42, 0.), CPoint (0.58, 1.));
}
//------------------------------------------------------------------------
CubicBezierTimingFunction* CubicBezierTimingFunction::make (Style style, uint32_t time)
{
using Func = CubicBezierTimingFunction;
switch (style)
{
case Easy:
return new CubicBezierTimingFunction (Func::easy (time));
case EasyIn:
return new CubicBezierTimingFunction (Func::easyIn (time));
case EasyOut:
return new CubicBezierTimingFunction (Func::easyOut (time));
case EasyInOut:
return new CubicBezierTimingFunction (Func::easyInOut (time));
}
return nullptr;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
RepeatTimingFunction::RepeatTimingFunction (TimingFunctionBase* tf, int32_t repeatCount, bool autoReverse)
: tf (tf)
, repeatCount (repeatCount)
, runCounter (0)
, autoReverse (autoReverse)
, isReverse (false)
{
}
//-----------------------------------------------------------------------------
RepeatTimingFunction::~RepeatTimingFunction () noexcept
{
auto obj = dynamic_cast<IReference*> (tf);
if (obj)
obj->forget ();
else
delete tf;
}
//-----------------------------------------------------------------------------
float RepeatTimingFunction::getPosition (uint32_t milliseconds)
{
if (runCounter > 0)
milliseconds -= tf->getLength () * runCounter;
float pos = tf->getPosition (milliseconds);
return isReverse ? 1.f - pos : pos;
}
//-----------------------------------------------------------------------------
bool RepeatTimingFunction::isDone (uint32_t milliseconds)
{
if (runCounter > 0)
milliseconds -= tf->getLength () * runCounter;
if (tf->isDone (milliseconds))
{
runCounter++;
if (autoReverse)
isReverse = !isReverse;
if ((uint64_t)runCounter >= (uint64_t)repeatCount)
return true;
}
return false;
}
}} // namespaces