namespace tweeny {
/**
 @page manual Tweeny Manual

 This document is the manual for Tweeny. It walks you through all the important steps when creating and controlling tweens.

 @section creating Creating a tween

 Tweeny can interpolate a single value, a set of values and a set of values with different types. For each of these cases, you create a tween using the same method: tweeny::from. The argument types you pass to it defines the tween itself which in turn defines argument number and types for tween::to, tween::during and tween::via, as well as the callback argument types.

 Here is how you create a tween:

 @code
 // Creates a single-valued tween
 auto tween = tweeny::from(0);

 // Creates a multi-valued tween
 auto tween2 = tweeny::from(0, 1, 2);

 // Creates a multi-value heterogeneous tween
 auto tween3 = tweeny::from(0, 'a', 1.0f);
 @endcode

 @section points Adding tween points

 A tween without a target value does nothing. To add a point to a tween, use the method tween::to. Since tweeny::from returns the tween instance itself, you can chain both calls, forming the following:

 @code
 // For a single value
 auto tween = tweeny::from(0).to(100);

 // For multiple values
 auto tween = tweeny::from(0, 'a').to(10, 'z');
 @endcode

 Notice how arguments to tween::to were of the same type of the arguments to tweeny::from.

 @section durations Specifying durations

 A tween needs a duration between each point. This duration unit is a unsigned integer that can represent anything you want. Usually I use it as milliseconds (this is relevant when stepping a tween). To specify the duration, call tween::during **after** tween::to:

 @code
 auto tween = tweeny::from(0).to(100).during(100);
 @endcode

 When you have a multivalued tween, you can either pass one single duration for all the values or specify a value for each point:

 @code
 auto tween = tweeny::from(0, 1, 2).to(3, 4, 5).during(50, 100, 200);
 @endcode

 The total duration from the starting point `(0, 1, 2)` to the next point `(3, 4, 5)` is 200, but each value will reach their target at different times.

 To specify the same time for each value, pass a single value for tween::during:

 @code
 auto tween = tweeny::from(0, 1, 2).to(3, 4, 5).during(200);
 @endcode

 @section easings Changing easing functions

 Easing functions control the interpolation values between each point. Given a percentage `p`, initial value `a` and final value `b`, a easing function will return a value between `a` and `b` corresponding to that `p`. For instance, the common implementation of a linear easing function is the following:

 @code
 int linear(float p, int a, int b) {
    return (b-a)*p + a;
 }
 @endcode

 By default, tweens use a linear easing function to interpolate their values. You can change that, though: Tweeny has 30 easing functions that you can specify using tween::via function.

 @code
 auto tween = tweeny::from(0).to(10).during(100).via(tweeny::easing::circularInOut);
 @endcode

 The same rules of tween::during applies here: if you have multi-valued tweens, you can specify a different easing for each one or use the same for all of them:

 @code
 using tweeny::easing;
 auto tween = tweeny::from(0, 1, 2).to(3, 4, 5).during(200).via(easing::exponentialIn, easing::exponentialInOut, easing::backOut);
 @endcode

 For a list of all available easings, consult the <a href="modules.html">modules</a> page.
 http://easings.net has a nice visualization of those easing curves.

 You can specify custom easing functions if a different behavior is needed, by passing any callable type to tween::via conforming to the <code>T ease(float p, T begin, T end)</code>
 prototype and returning the corresponding value.

 @code
 auto tween = tweeny::from(0).to(100).during(100).via([](float p, int a, int b) { return (b-a)*p + a; } );
 @endcode

 To a multi type tween, you need to make sure that easing arguments conform to their type:

 @code
 auto tween = tweeny::from(0, 1.0f).to(100, 200.0f).during(100)
              .via([](float p, int a, int b) { return (b-a)*p + a; }, [](float p, float a, float b) { return (b-a)*p + a; });
 @endcode

 Beware that when using integral types most easing functions will not round but truncate their results. This leads to strange behaviors such as
 the tween reaching its final value only when it its 100% but staying in its initial value for a long percentage portion. You can use floating point values
 and round them to obtain smoother results. easing::linear does this by default for integral types, but other easings don't.

 @section multipoint Multi point tweens

 Tweens can have multiple points: a sequence of values that will be reached in order. For instance, you might want to start from 0, reach
 100 during 500ms through a easing::linear easing, then reach 200 during 100ms through a easing::circularOut easing.

 To allow for that, each call to tween::to adds a new tweening point. Calls to tween::during and tween::via always refer to the last added
 point:

 @code
 auto tween = tweeny::from(0)
               .to(100).during(500) // 0 to 100 during 500
               .to(200).during(100).via(easing::circularOut); // 100 to 200 during 100 via circularOut
 @endcode

 Stepping and seeking works transparently for the user, regardless of how many tween points there are. This means that Tweeny will
 automatically manage switching from one point to another when using tween::step and tween::seek.

 @section interpolating Stepping, seeking and jumping.

 After setting up points, durations and easings, a tween is ready to interpolate. There are three main ways to do that and we are going
 to cover them in this section.

 The first one is **stepping**. It is used to move the tween forward by a delta amount, which can be either specified in duration units
 or percentage. Stepping is particularly useful when you are in a event/rendering loop and has access to the delta time between frames:

 @code
 auto tween = tweeny::from(0).to(100).during(1000);
 while (!done) {
    tween.step(dt);
  }
 @endcode

 Passing a integral quantity (integers) to tween::step will step it in duration units. Passing a float value will step it by
 a percentage (ranging from 0.0f to 1.0f).

 You can set a tween to go backwards, so that it steps in reverse. To to that, use tween::backward: each tween::step call will decrease
 a tween time until it reaches 0. To make it go forward again, use tween::forward. Tween direction makes no difference when seeking or jumping.

 The second one is **seeking**. Seeking is useful if you need the tween to move to a specific point in time or percentage.

 @code
 auto tween = tweeny::from(0).to(100).during(1000);
 tween.seek(0.5f);
 @endcode

 The same value type rules of tween::step applies: a float value means a percentage and an integral value means duration.

 The third one is **jumping**. Jumping is useful to seek to a specific tween point, when you have @ref multipoint .

 @code
 auto tween = tweeny::from(0).to(100).during(100).to(200).during(100);
 tween.jump(1);
 @endcode

 tween::step, tween::seek and tween::jump both returns the result of their action. The return type varies according to the
 tween type according to these rules:

 - If the tween has a single value, it will yield that value directly:
   @code
   auto tween = tweeny::from(0).to(100).during(100);
   int value = tween.step(10);
   @endcode

 - If the tween has multiple values of the same type, it will yield an array with those values:
   @code
   auto tween = tweeny::from(0, 1).to(2, 3).during(100);
   std::array<int, 2> v = tween.step(10);
   @endcode

 - If the tween has multiple types, it will return a tuple:
   @code
   auto tween = tweeny::from(0, 1.0f).to(2, 3.0f).during(100);
   std::tuple<int, float> v = tween.step(10);
   @endcode

 @section callbacks Callbacks

 Tweeny lets you specify seeking and stepping callbacks so that actions can executed in specific points
 (e.g, playing a sound when a tween reaches a frame). tween::onStep add a function that will be called whenever a tween
 steps whereas tween::onSeek will add a function to be called when it seeks. Although stepping is resolved
 in terms of seeking, tween::step it will not trigger seek callbacks.

 Callbacks can be of three different types:

 - Accept the tween and its current values. Useful if you want access to tween values and need to control the tween instance:
   @code
   bool stepped(tween<int, int> & t, int x, int y);
   auto tween = tweeny::from(0, 0).to(100, 200).during(100).onStep(stepped);
   @endcode

 - Accept only a tween, useful if the values itself are not interesting but you need to control tween behavior:
   @code
   bool stepped(tween<int, int> & t);
   auto tween = tweeny::from(0, 0).to(100, 200).during(100).onStep(stepped);
   @endcode

 - Accept only tween values, if you just want tween values:
   @code
   bool stepped(int x, int y);
   auto tween = tweeny::from(0, 0).to(100, 200).during(100).onStep(stepped);
   @endcode

 The return type of a callback is always boolean. If it returns true, it will be *dismissed* and
 removed from the callback list. Returning false keeps the callback in the queue:

 @code
 bool stepped(int x, int y) {
   printf("x: %d, y: %d\n", x, y);
   if (x == y) return true;
   return false;
 }
 auto tween = tweeny::from(0, 0).to(100, 200).during(100).onStep(stepped);
 @endcode

 All callable types can be used as a callback, as long as they conform to the interface.

 @code
 struct ftor {
    bool operator()(int x, int y) { return false; }
 };
 auto tween = tweeny::from(0, 0).to(100, 200).during(100);
 tween.onStep([](int, int) { return false; }); // lambdas
 tween.onStep(ftor()); // functors
 @endcode

 The @ref loop has some nice ways of using callbacks.

 <hr>

 This covers all the basics steps of using Tweeny. There is more to learn though, take a look at the <a href="http://github.com/mobius3/tweey-demos">demo repository</a> to see
 more. Consult the API of the @ref tween class to see all its methods and more examples within.

 I hope you have fun using Tweeny.
*/
}
