Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed accuracy in some cases #42

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 45 additions & 15 deletions include/tween.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ namespace tweeny {
* @param suppressCallbacks (Optional) Suppress callbacks registered with tween::onStep()
* @returns std::tuple<Ts...> with the current tween values.
*/
const typename detail::tweentraits<T, Ts...>::valuesType & step(float dp, bool suppressCallbacks = false);
const typename detail::tweentraits<T, Ts...>::valuesType &step(
float dp, bool suppressCallbacks = false);

/**
* @brief Seeks to a specified point in time based on the currentProgress.
Expand All @@ -261,7 +262,8 @@ namespace tweeny {
* @param suppressCallbacks (Optional) Suppress callbacks registered with tween::onSeek()
* @returns std::tuple<Ts...> with the current tween values.
*/
const typename detail::tweentraits<T, Ts...>::valuesType & seek(float p, bool suppressCallbacks = false);
const typename detail::tweentraits<T, Ts...>::valuesType &seek(
float p, bool suppressCallbacks = false);

/**
* @brief Seeks to a specified point in time.
Expand All @@ -285,7 +287,8 @@ namespace tweeny {
* @returns std::tuple<Ts...> with the current tween values.
* @see duration
*/
const typename detail::tweentraits<T, Ts...>::valuesType & seek(uint32_t d, bool suppressCallbacks = false);
const typename detail::tweentraits<T, Ts...>::valuesType &seek(
uint32_t d, bool suppressCallbacks = false);

/**
* @brief Adds a callback that will be called when stepping occurs, accepting both the tween and
Expand Down Expand Up @@ -506,6 +509,13 @@ namespace tweeny {
*/
const typename detail::tweentraits<T, Ts...>::valuesType peek(uint32_t time) const;

/**
* @brief Returns the current time point of the interpolation.
*
* @returns the current timr point between 0 and total time point (inclusive)
*/
uint32_t currentTimePoint() const; ///< @sa tween::currenttimepoint

/**
* @brief Returns the current currentProgress of the interpolation.
*
Expand All @@ -514,6 +524,13 @@ namespace tweeny {
*/
float progress() const;

/**
* @brief Returns true if tween reach to end of interpolation progress.
*
* @returns True means its finished, false means its in progress.
*/
bool isFinished() const;

/**
* @brief Sets the direction of this tween forward.
*
Expand Down Expand Up @@ -564,7 +581,7 @@ namespace tweeny {
private /* member variables */:
uint32_t total = 0; // total runtime
uint16_t currentPoint = 0; // current point
float currentProgress = 0; // current progress
uint32_t currentProgress = 0; // current progress
std::vector<detail::tweenpoint<T, Ts...>> points;
typename traits::valuesType current;
std::vector<typename traits::callbackType> onStepCallbacks;
Expand All @@ -574,11 +591,18 @@ namespace tweeny {
private:
/* member functions */
tween(T t, Ts... vs);
template<size_t I> void interpolate(float prog, unsigned point, typename traits::valuesType & values, detail::int2type<I>) const;
void interpolate(float prog, unsigned point, typename traits::valuesType & values, detail::int2type<0>) const;
void render(float p);
template<size_t I>
void interpolate(uint32_t prog,
unsigned point,
typename traits::valuesType &values,
detail::int2type<I>) const;
void interpolate(uint32_t prog,
unsigned point,
typename traits::valuesType &values,
detail::int2type<0>) const;
void render(uint32_t p);
void dispatch(std::vector<typename traits::callbackType> & cbVector);
uint16_t pointAt(float progress) const;
uint16_t pointAt(uint32_t progress) const;
};

/**
Expand Down Expand Up @@ -607,8 +631,12 @@ namespace tweeny {
template<typename... Ds> tween<T> & during(Ds... ds); ///< @sa tween::during
const T & step(int32_t dt, bool suppressCallbacks = false); ///< @sa tween::step(int32_t dt, bool suppressCallbacks)
const T & step(uint32_t dt, bool suppressCallbacks = false); ///< @sa tween::step(uint32_t dt, bool suppressCallbacks)
const T & step(float dp, bool suppressCallbacks = false); ///< @sa tween::step(float dp, bool suppressCallbacks)
const T & seek(float p, bool suppressCallbacks = false); ///< @sa tween::seek(float p, bool suppressCallbacks)
const T &step(float dp,
bool suppressCallbacks
= false); ///< @sa tween::step(float dp, bool suppressCallbacks)
const T &seek(float p,
bool suppressCallbacks
= false); ///< @sa tween::seek(float p, bool suppressCallbacks)
const T & seek(int32_t d, bool suppressCallbacks = false); ///< @sa tween::seek(int32_t d, bool suppressCallbacks)
const T & seek(uint32_t d, bool suppressCallbacks = false); ///< @sa tween::seek(uint32_t d, bool suppressCallbacks)
tween<T> & onStep(typename detail::tweentraits<T>::callbackType callback); ///< @sa tween::onStep
Expand All @@ -621,7 +649,9 @@ namespace tweeny {
T peek(float progress) const; ///< @sa tween::peek
T peek(uint32_t time) const; ///< @sa tween::peek
uint32_t duration() const; ///< @sa tween::duration
float progress() const; ///< @sa tween::progress
uint32_t currentTimePoint() const; ///< @sa tween::currenttimepoint
float progress() const; ///< @sa tween::progress
bool isFinished() const; ///< @sa tween::isFinished
tween<T> & forward(); ///< @sa tween::forward
tween<T> & backward(); ///< @sa tween::backward
int direction() const; ///< @sa tween::direction
Expand All @@ -634,7 +664,7 @@ namespace tweeny {
private /* member variables */:
uint32_t total = 0; // total runtime
uint16_t currentPoint = 0; // current point
float currentProgress = 0; // current progress
uint32_t currentProgress = 0; // current progress
std::vector<detail::tweenpoint<T>> points;
T current;
std::vector<typename traits::callbackType> onStepCallbacks;
Expand All @@ -644,10 +674,10 @@ namespace tweeny {
private:
/* member functions */
tween(T t);
void interpolate(float prog, unsigned point, T & value) const;
void render(float p);
void interpolate(uint32_t prog, unsigned point, T &value) const;
void render(uint32_t p);
void dispatch(std::vector<typename traits::callbackType> & cbVector);
uint16_t pointAt(float progress) const;
uint16_t pointAt(uint32_t progress) const;
};
}

Expand Down
97 changes: 71 additions & 26 deletions include/tween.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
#ifndef TWEENY_TWEEN_TCC
#define TWEENY_TWEEN_TCC

#include "tween.h"
#include "dispatcher.h"
#include "tween.h"
#include <cstdlib>

namespace tweeny {

Expand Down Expand Up @@ -165,7 +166,11 @@ namespace tweeny {

template<typename T, typename... Ts>
inline const typename detail::tweentraits<T, Ts...>::valuesType & tween<T, Ts...>::step(int32_t dt, bool suppress) {
return step(static_cast<float>(dt)/static_cast<float>(total), suppress);
dt *= currentDirection;
seek(currentProgress + dt, true);
if (!suppress)
dispatch(onStepCallbacks);
return current;
}

template<typename T, typename... Ts>
Expand All @@ -174,25 +179,34 @@ namespace tweeny {
}

template<typename T, typename... Ts>
inline const typename detail::tweentraits<T, Ts...>::valuesType & tween<T, Ts...>::step(float dp, bool suppress) {
dp *= currentDirection;
seek(currentProgress + dp, true);
if (!suppress) dispatch(onStepCallbacks);
return current;
inline const typename detail::tweentraits<T, Ts...>::valuesType &tween<T, Ts...>::step(
float dp, bool suppress)
{
return step(static_cast<int32_t>(dp * total), suppress);
}

template<typename T, typename... Ts>
inline const typename detail::tweentraits<T, Ts...>::valuesType & tween<T, Ts...>::seek(float p, bool suppress) {
p = detail::clip(p, 0.0f, 1.0f);
inline const typename detail::tweentraits<T, Ts...>::valuesType &tween<T, Ts...>::seek(
uint32_t p, bool suppress)
{
p = detail::clip(p, 0u, total);
currentProgress = p;
render(p);
if (!suppress) dispatch(onSeekCallbacks);
if (!suppress)
dispatch(onSeekCallbacks);
return current;
}

template<typename T, typename... Ts>
inline const typename detail::tweentraits<T, Ts...>::valuesType & tween<T, Ts...>::seek(int32_t t, bool suppress) {
return seek(static_cast<float>(t) / static_cast<float>(total), suppress);
return seek(static_cast<uint32_t>(std::abs(t)), suppress);
}

template<typename T, typename... Ts>
inline const typename detail::tweentraits<T, Ts...>::valuesType &tween<T, Ts...>::seek(
float p, bool suppress)
{
return seek(static_cast<int32_t>(p * total), suppress);
}

template<typename T, typename... Ts>
Expand All @@ -202,9 +216,13 @@ namespace tweeny {

template<typename T, typename... Ts>
template<size_t I>
inline void tween<T, Ts...>::interpolate(float prog, unsigned point, typename traits::valuesType & values, detail::int2type<I>) const {
inline void tween<T, Ts...>::interpolate(uint32_t prog,
unsigned point,
typename traits::valuesType &values,
detail::int2type<I>) const
{
auto & p = points.at(point);
auto pointDuration = uint32_t(p.duration() - (p.stacked - (prog * static_cast<float>(total))));
auto pointDuration = uint32_t(p.duration() - (p.stacked - prog));
float pointTotal = static_cast<float>(pointDuration) / static_cast<float>(p.duration(I));
if (pointTotal > 1.0f) pointTotal = 1.0f;
auto easing = std::get<I>(p.easings);
Expand All @@ -213,17 +231,22 @@ namespace tweeny {
}

template<typename T, typename... Ts>
inline void tween<T, Ts...>::interpolate(float prog, unsigned point, typename traits::valuesType & values, detail::int2type<0>) const {
inline void tween<T, Ts...>::interpolate(uint32_t prog,
unsigned point,
typename traits::valuesType &values,
detail::int2type<0>) const
{
auto & p = points.at(point);
auto pointDuration = uint32_t(p.duration() - (p.stacked - (prog * static_cast<float>(total))));
auto pointDuration = uint32_t(p.duration() - (p.stacked - prog));
float pointTotal = static_cast<float>(pointDuration) / static_cast<float>(p.duration(0));
if (pointTotal > 1.0f) pointTotal = 1.0f;
auto easing = std::get<0>(p.easings);
std::get<0>(values) = easing(pointTotal, std::get<0>(p.values), std::get<0>(points.at(point+1).values));
}

template<typename T, typename... Ts>
inline void tween<T, Ts...>::render(float p) {
inline void tween<T, Ts...>::render(uint32_t p)
{
currentPoint = pointAt(p);
interpolate(p, currentPoint, current, detail::int2type<sizeof...(Ts) - 1 + 1 /* +1 for the T */>{ });
}
Expand Down Expand Up @@ -290,23 +313,42 @@ namespace tweeny {
template<typename T, typename... Ts>
const typename detail::tweentraits<T, Ts...>::valuesType tween<T, Ts...>::peek(float progress) const {
typename detail::tweentraits<T, Ts...>::valuesType values;
interpolate(progress, pointAt(progress), values, detail::int2type<sizeof...(Ts) - 1 + 1 /* +1 for the T */>{ });
uint32_t time = progress * total;
interpolate(time,
pointAt(time),
values,
detail::int2type<sizeof...(Ts) - 1 + 1 /* +1 for the T */>{});
return values;
}

template<typename T, typename... Ts>
const typename detail::tweentraits<T, Ts...>::valuesType tween<T, Ts...>::peek(uint32_t time) const {
typename detail::tweentraits<T, Ts...>::valuesType values;
float progress = static_cast<float>(time) / static_cast<float>(total);
interpolate(progress, pointAt(progress), values, detail::int2type<sizeof...(Ts) - 1 + 1 /* +1 for the T */>{ });
interpolate(time,
pointAt(time),
values,
detail::int2type<sizeof...(Ts) - 1 + 1 /* +1 for the T */>{});
return values;
}

template<typename T, typename... Ts>
float tween<T, Ts...>::progress() const {
template<typename T, typename... Ts>
uint32_t tween<T, Ts...>::currentTimePoint() const
{
return currentProgress;
}

template<typename T, typename... Ts>
float tween<T, Ts...>::progress() const
{
return static_cast<float>(currentProgress) / static_cast<float>(total);
}

template<typename T, typename... Ts>
bool tween<T, Ts...>::isFinished() const
{
return currentProgress == total;
}

template<typename T, typename... Ts>
tween<T, Ts...> & tween<T, Ts...>::forward() {
currentDirection = 1;
Expand Down Expand Up @@ -334,12 +376,15 @@ namespace tweeny {
return currentPoint;
}

template<typename T, typename... Ts> inline uint16_t tween<T, Ts...>::pointAt(float progress) const {
progress = detail::clip(progress, 0.0f, 1.0f);
uint32_t t = static_cast<uint32_t>(progress * total);
template<typename T, typename... Ts>
inline uint16_t tween<T, Ts...>::pointAt(uint32_t progress) const
{
progress = detail::clip(progress, 0u, total);
uint16_t point = 0;
while (t > points.at(point).stacked) point++;
if (point > 0 && t <= points.at(point - 1u).stacked) point--;
while (progress > points.at(point).stacked)
point++;
if (point > 0 && progress <= points.at(point - 1u).stacked)
point--;
return point;
}
}
Expand Down
Loading