💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
5.0 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_TWEEN_HPP
  20. #define ANTKEEPER_TWEEN_HPP
  21. #include <algorithm>
  22. #include <functional>
  23. #include <stdexcept>
  24. #include <type_traits>
  25. /**
  26. * Container which stores two states along with an interpolator, for quick and easy tween<T, S>ing.
  27. *
  28. * @tparam T Value type.
  29. * @tparam S Scalar type.
  30. */
  31. template <class T, class S = float>
  32. class tween
  33. {
  34. public:
  35. static_assert(std::is_scalar<S>::value);
  36. typedef T value_type;
  37. typedef S scalar_type;
  38. typedef typename std::decay<std::function<value_type(const value_type&, const value_type&, scalar_type)>>::type interpolator_type;
  39. private:
  40. /// Throws an error if no interpolator is set.
  41. static value_type interpolator_error(const value_type&, const value_type&, scalar_type);
  42. public:
  43. /**
  44. * Creates a tween.
  45. *
  46. * @param state0 Initial value of state 0.
  47. * @param state1 Initial value of state 1.
  48. * @param interpolator Function used to interpolate between states 0 and 1.
  49. */
  50. tween(const value_type& state0, const value_type& state1, interpolator_type interpolator = tween<T, S>::interpolator_error);
  51. /**
  52. * Creates a tween.
  53. *
  54. * @param value Initial value of states 0 and 1.
  55. * @param interpolator Function used to interpolate between states 0 and 1.
  56. */
  57. explicit tween(const value_type& value, interpolator_type interpolator = tween<T, S>::interpolator_error);
  58. /**
  59. * Creates a tween.
  60. */
  61. tween();
  62. /**
  63. * Returns a reference to the specified tween state.
  64. *
  65. * @param i Index of a tween state. Should be either `0` or `1`.
  66. * @return Reference to the specified tween state.
  67. */
  68. const value_type& operator[](int i) const;
  69. /// @copydoc tween<T, S>::operator[](int) const
  70. value_type& operator[](int i);
  71. /// @copydoc tween<T, S>::interpolate(scalar_type) const
  72. value_type operator[](scalar_type a) const;
  73. /**
  74. * Returns an interpolated state between state 0 and state 1. If no interpolator is set, state 1 will be returned.
  75. *
  76. * @param a Interpolation factor on `[0.0, 1.0]`.
  77. * @return Interpolated state, or state 1 if no interpolator is set.
  78. */
  79. value_type interpolate(scalar_type a) const;
  80. /**
  81. * Sets the function used to interpolate between states 0 and 1.
  82. *
  83. * @param interpolator Interpolator function.
  84. */
  85. void set_interpolator(const interpolator_type& interpolator);
  86. /**
  87. * Returns the function used to interpolate between states 0 and 1.
  88. */
  89. const interpolator_type& get_interpolator() const;
  90. /**
  91. * Sets state 0 = state 1.
  92. */
  93. void update();
  94. /**
  95. * Swaps state 0 and state 1.
  96. */
  97. void swap();
  98. private:
  99. value_type states[2];
  100. interpolator_type interpolator;
  101. };
  102. template <class T, class S>
  103. typename tween<T, S>::value_type tween<T, S>::interpolator_error(const value_type&, const value_type&, scalar_type)
  104. {
  105. throw std::runtime_error("tween interpolator not set");
  106. }
  107. template <class T, class S>
  108. tween<T, S>::tween(const value_type& value, interpolator_type interpolator):
  109. states{value, value},
  110. interpolator(interpolator)
  111. {}
  112. template <class T, class S>
  113. tween<T, S>::tween(const value_type& state0, const value_type& state1, interpolator_type interpolator):
  114. states{state0, state1},
  115. interpolator(interpolator)
  116. {}
  117. template <class T, class S>
  118. tween<T, S>::tween():
  119. interpolator(nullptr)
  120. {}
  121. template <class T, class S>
  122. inline const typename tween<T, S>::value_type& tween<T, S>::operator[](int i) const
  123. {
  124. return states[i];
  125. }
  126. template <class T, class S>
  127. inline typename tween<T, S>::value_type& tween<T, S>::operator[](int i)
  128. {
  129. return states[i];
  130. }
  131. template <class T, class S>
  132. inline typename tween<T, S>::value_type tween<T, S>::operator[](scalar_type a) const
  133. {
  134. return interpolate(a);
  135. }
  136. template <class T, class S>
  137. inline typename tween<T, S>::value_type tween<T, S>::interpolate(scalar_type a) const
  138. {
  139. return interpolator(states[0], states[1], a);
  140. }
  141. template <class T, class S>
  142. inline void tween<T, S>::set_interpolator(const interpolator_type& interpolator)
  143. {
  144. this->interpolator = interpolator;
  145. }
  146. template <class T, class S>
  147. inline const typename tween<T, S>::interpolator_type& tween<T, S>::get_interpolator() const
  148. {
  149. return interpolator;
  150. }
  151. template <class T, class S>
  152. inline void tween<T, S>::update()
  153. {
  154. states[0] = states[1];
  155. }
  156. template <class T, class S>
  157. inline void tween<T, S>::swap()
  158. {
  159. std::swap(states[0], states[1]);
  160. }
  161. #endif // ANTKEEPER_TWEEN_HPP