/*
|
|
* Copyright (C) 2021 Christopher J. Howard
|
|
*
|
|
* This file is part of Antkeeper source code.
|
|
*
|
|
* Antkeeper source code 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.
|
|
*
|
|
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef ANTKEEPER_TWEEN_HPP
|
|
#define ANTKEEPER_TWEEN_HPP
|
|
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <type_traits>
|
|
|
|
/**
|
|
* Container which stores two states along with an interpolator, for quick and easy tween<T, S>ing.
|
|
*
|
|
* @tparam T Value type.
|
|
* @tparam S Scalar type.
|
|
*/
|
|
template <class T, class S = float>
|
|
class tween
|
|
{
|
|
public:
|
|
static_assert(std::is_scalar<S>::value);
|
|
|
|
typedef T value_type;
|
|
typedef S scalar_type;
|
|
typedef typename std::decay<std::function<value_type(const value_type&, const value_type&, scalar_type)>>::type interpolator_type;
|
|
|
|
private:
|
|
/// Throws an error if no interpolator is set.
|
|
static value_type interpolator_error(const value_type&, const value_type&, scalar_type);
|
|
|
|
public:
|
|
|
|
/**
|
|
* Creates a tween.
|
|
*
|
|
* @param state0 Initial value of state 0.
|
|
* @param state1 Initial value of state 1.
|
|
* @param interpolator Function used to interpolate between states 0 and 1.
|
|
*/
|
|
tween(const value_type& state0, const value_type& state1, interpolator_type interpolator = tween<T, S>::interpolator_error);
|
|
|
|
/**
|
|
* Creates a tween.
|
|
*
|
|
* @param value Initial value of states 0 and 1.
|
|
* @param interpolator Function used to interpolate between states 0 and 1.
|
|
*/
|
|
explicit tween(const value_type& value, interpolator_type interpolator = tween<T, S>::interpolator_error);
|
|
|
|
/**
|
|
* Creates a tween.
|
|
*/
|
|
tween();
|
|
|
|
/**
|
|
* Returns a reference to the specified tween state.
|
|
*
|
|
* @param i Index of a tween state. Should be either `0` or `1`.
|
|
* @return Reference to the specified tween state.
|
|
*/
|
|
const value_type& operator[](int i) const;
|
|
|
|
/// @copydoc tween<T, S>::operator[](int) const
|
|
value_type& operator[](int i);
|
|
|
|
/// @copydoc tween<T, S>::interpolate(scalar_type) const
|
|
value_type operator[](scalar_type a) const;
|
|
|
|
/**
|
|
* Returns an interpolated state between state 0 and state 1. If no interpolator is set, state 1 will be returned.
|
|
*
|
|
* @param a Interpolation factor on `[0.0, 1.0]`.
|
|
* @return Interpolated state, or state 1 if no interpolator is set.
|
|
*/
|
|
value_type interpolate(scalar_type a) const;
|
|
|
|
/**
|
|
* Sets the function used to interpolate between states 0 and 1.
|
|
*
|
|
* @param interpolator Interpolator function.
|
|
*/
|
|
void set_interpolator(const interpolator_type& interpolator);
|
|
|
|
/**
|
|
* Returns the function used to interpolate between states 0 and 1.
|
|
*/
|
|
const interpolator_type& get_interpolator() const;
|
|
|
|
/**
|
|
* Sets state 0 = state 1.
|
|
*/
|
|
void update();
|
|
|
|
/**
|
|
* Swaps state 0 and state 1.
|
|
*/
|
|
void swap();
|
|
|
|
private:
|
|
value_type states[2];
|
|
interpolator_type interpolator;
|
|
};
|
|
|
|
template <class T, class S>
|
|
typename tween<T, S>::value_type tween<T, S>::interpolator_error(const value_type&, const value_type&, scalar_type)
|
|
{
|
|
throw std::runtime_error("tween interpolator not set");
|
|
}
|
|
|
|
template <class T, class S>
|
|
tween<T, S>::tween(const value_type& value, interpolator_type interpolator):
|
|
states{value, value},
|
|
interpolator(interpolator)
|
|
{}
|
|
|
|
template <class T, class S>
|
|
tween<T, S>::tween(const value_type& state0, const value_type& state1, interpolator_type interpolator):
|
|
states{state0, state1},
|
|
interpolator(interpolator)
|
|
{}
|
|
|
|
template <class T, class S>
|
|
tween<T, S>::tween():
|
|
interpolator(nullptr)
|
|
{}
|
|
|
|
template <class T, class S>
|
|
inline const typename tween<T, S>::value_type& tween<T, S>::operator[](int i) const
|
|
{
|
|
return states[i];
|
|
}
|
|
|
|
template <class T, class S>
|
|
inline typename tween<T, S>::value_type& tween<T, S>::operator[](int i)
|
|
{
|
|
return states[i];
|
|
}
|
|
|
|
template <class T, class S>
|
|
inline typename tween<T, S>::value_type tween<T, S>::operator[](scalar_type a) const
|
|
{
|
|
return interpolate(a);
|
|
}
|
|
|
|
template <class T, class S>
|
|
inline typename tween<T, S>::value_type tween<T, S>::interpolate(scalar_type a) const
|
|
{
|
|
return interpolator(states[0], states[1], a);
|
|
}
|
|
|
|
template <class T, class S>
|
|
inline void tween<T, S>::set_interpolator(const interpolator_type& interpolator)
|
|
{
|
|
this->interpolator = interpolator;
|
|
}
|
|
|
|
template <class T, class S>
|
|
inline const typename tween<T, S>::interpolator_type& tween<T, S>::get_interpolator() const
|
|
{
|
|
return interpolator;
|
|
}
|
|
|
|
template <class T, class S>
|
|
inline void tween<T, S>::update()
|
|
{
|
|
states[0] = states[1];
|
|
}
|
|
|
|
template <class T, class S>
|
|
inline void tween<T, S>::swap()
|
|
{
|
|
std::swap(states[0], states[1]);
|
|
}
|
|
|
|
#endif // ANTKEEPER_TWEEN_HPP
|