# ifndef Magnum_Animation_Track_h
# define Magnum_Animation_Track_h
/*
This file is part of Magnum .
Copyright © 2010 , 2011 , 2012 , 2013 , 2014 , 2015 , 2016 , 2017 , 2018 , 2019 ,
2020 , 2021 , 2022 , 2023 , 2024
Vladimír Vondruš < mosra @ centrum . cz >
Permission is hereby granted , free of charge , to any person obtaining a
copy of this software and associated documentation files ( the " Software " ) ,
to deal in the Software without restriction , including without limitation
the rights to use , copy , modify , merge , publish , distribute , sublicense ,
and / or sell copies of the Software , and to permit persons to whom the
Software is furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE .
*/
/** @file
* @ brief Class @ ref Magnum : : Animation : : Track , @ ref Magnum : : Animation : : TrackViewStorage , @ ref Magnum : : Animation : : TrackView
*/
# include <Corrade/Containers/Array.h>
# include "Magnum/Animation/Animation.h"
# include "Magnum/Animation/Interpolation.h"
# include "Magnum/Math/Range.h"
namespace Magnum { namespace Animation {
/**
@ brief Animation track
@ tparam K Key type
@ tparam V Value type
@ tparam R Result type
Immutable storage of keyframe + value pairs . Usually used in combination with
the @ ref Player class , but it ' s possible to use it separately as well .
@ section Animation - Track - usage Basic usage
Animation track is defined by a list of keyframes ( time + value pairs ) ,
interpolator function and extrapolation behavior .
@ snippet Animation . cpp Track - usage
@ section Animation - Track - interpolators Types and interpolators
The track supports arbitrary types for keys , values and interpolators . See
@ ref transformations - interpolation for an overview of builtin interpolation
functions .
Besides directly specifying an interpolator function as shown in the above
snippet , it ' s also possible to supply a generic interpolation behavior by
passing the @ ref Interpolation enum to the constructor . In case the
interpolator function is not passed in as well , it ' s autodetected using
@ ref interpolatorFor ( ) . See its documentation for more information . The
@ ref Interpolation enum is then stored in @ ref interpolation ( ) and acts as a
hint for desired interpolation behavior for users who might want to use their
own interpolator .
@ section Animation - Track - performance Performance tuning
The snippet shown above is convenience - oriented at a cost of sacrificing some
performance . You have the following options :
@ subsection Animation - Track - performance - hint Keyframe hinting
The @ ref Track and @ ref TrackView classes are fully stateless and the
@ ref at ( K ) const function performs a linear search for matching keyframe from
the beginning every time . You can use @ ref at ( K , std : : size_t & ) const to
remember last used keyframe index and pass it in the next iteration as a hint :
@ snippet Animation . cpp Track - performance - hint
@ subsection Animation - Track - performance - strict Strict interpolation
While it ' s possible to have different @ ref Extrapolation modes for frames
outside of the track range with graceful handling of single - or zero - frame
animations , the additional checks have some impact . The @ ref atStrict ( ) has
implicit @ ref Extrapolation : : Extrapolated behavior and assumes there are always
at least two keyframes , resulting in more compact interpolation code . If your
animation data satisfy the prerequisites , simply use it in place of @ ref at ( ) :
@ snippet Animation . cpp Track - performance - strict
@ subsection Animation - Track - performance - cache Cache - efficient data layout
Usually multiple tracks ( translation , rotation , scaling ) are combined together
to form a single animation . In order to achieve better data layout , consider
interleaving the data and passing them using
@ ref Corrade : : Containers : : StridedArrayView to multiple @ ref TrackView
instead of having data duplicated scattered across disjoint allocations of
@ ref Track instances :
@ snippet Animation . cpp Track - performance - cache
@ subsection Animation - Track - performance - interpolator Interpolator function choice
The interpolator function has a direct effect on animation performance . You can
choose a less complex interpolator ( constant instead of linear or linear
instead of spheric linear , for example ) either during construction or passing
it directly to @ ref at ( ) / @ ref atStrict ( ) . The @ ref interpolator ( ) can act as
a hint on what kind of function should be chosen . Depending on how the track
was constructed , passing the interpolator directly to @ ref at ( ) / @ ref atStrict ( )
usually also results in it being inlined by the compiler and thus faster than
an indirect function call .
Note that when constructing the track by just passing @ ref Interpolator to the
constructor , the function is chosen by @ ref interpolatorFor ( ) , which favors
correctness over performance . See its documentation for more information .
@ experimental
*/
template < class K , class V , class R
# ifdef DOXYGEN_GENERATING_OUTPUT
= ResultOf < V >
# endif
> class Track {
public :
/** @brief Key type */
typedef K KeyType ;
/** @brief Value type */
typedef V ValueType ;
/** @brief Animation result type */
typedef R ResultType ;
/** @brief Interpolation function */
typedef ResultType ( * Interpolator ) ( const ValueType & , const ValueType & , Float ) ;
/**
* @ brief Construct an empty track
*
* The @ ref data ( ) , @ ref keys ( ) , @ ref values ( ) and @ ref interpolator ( )
* functions return @ cpp nullptr @ ce , @ ref at ( ) always returns a
* default - constructed value .
*/
explicit Track ( ) noexcept : _data { } , _interpolator { } , _interpolation { } , _before { } , _after { } { }
/**
* @ brief Construct with custom interpolator
* @ param data Keyframe data
* @ param interpolator Interpolator function
* @ param before Extrapolation behavior
* @ param after Extrapolation behavior after
*
* The keyframe data are assumed to be stored in sorted order . It ' s not
* an error to have two successive keyframes with the same frame value .
* The @ ref interpolation ( ) field is set to @ ref Interpolation : : Custom .
* See @ ref Track ( Containers : : Array < std : : pair < K , V > > & & , Interpolation , Interpolator , Extrapolation , Extrapolation ) or
* @ ref Track ( Containers : : Array < std : : pair < K , V > > & & , Interpolation , Extrapolation , Extrapolation )
* for an alternative .
*/
explicit Track ( Containers : : Array < std : : pair < K , V > > & & data , Interpolator interpolator , Extrapolation before , Extrapolation after ) noexcept : _data { Utility : : move ( data ) } , _interpolator { interpolator } , _interpolation { Interpolation : : Custom } , _before { before } , _after { after } { }
/** @overload */
explicit Track ( std : : initializer_list < std : : pair < K , V > > data , Interpolator interpolator , Extrapolation before , Extrapolation after ) : Track < K , V , R > { Containers : : Array < std : : pair < K , V > > { InPlaceInit , data } , interpolator , before , after } { }
/** @overload
* Equivalent to calling @ ref Track ( Containers : : Array < std : : pair < K , V > > & & , Interpolator , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
explicit Track ( Containers : : Array < std : : pair < K , V > > & & data , Interpolator interpolator , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : Track < K , V , R > { Utility : : move ( data ) , interpolator , extrapolation , extrapolation } { }
/** @overload */
explicit Track ( std : : initializer_list < std : : pair < K , V > > data , Interpolator interpolator , Extrapolation extrapolation = Extrapolation : : Constant ) : Track < K , V , R > { Containers : : Array < std : : pair < K , V > > { InPlaceInit , data } , interpolator , extrapolation , extrapolation } { }
/**
* @ brief Construct with both generic and custom interpolator
* @ param data Keyframe data
* @ param interpolation Interpolation behavior
* @ param interpolator Interpolator function
* @ param before Extrapolation behavior
* @ param after Extrapolation behavior after
*
* The keyframe data are assumed to be stored in sorted order . It ' s not
* an error to have two successive keyframes with the same frame value .
* @ p interpolation acts as a behavior hint to users that might want to
* supply their own interpolator function to @ ref at ( ) or
* @ ref atStrict ( ) .
*/
explicit Track ( Containers : : Array < std : : pair < K , V > > & & data , Interpolation interpolation , Interpolator interpolator , Extrapolation before , Extrapolation after ) noexcept : _data { Utility : : move ( data ) } , _interpolator { interpolator } , _interpolation { interpolation } , _before { before } , _after { after } { }
/** @overload */
explicit Track ( std : : initializer_list < std : : pair < K , V > > data , Interpolation interpolation , Interpolator interpolator , Extrapolation before , Extrapolation after ) : Track < K , V , R > { Containers : : Array < std : : pair < K , V > > { InPlaceInit , data } , interpolation , interpolator , before , after } { }
/** @overload
* Equivalent to calling @ ref Track ( Containers : : Array < std : : pair < K , V > > & & , Interpolation , Interpolator , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
explicit Track ( Containers : : Array < std : : pair < K , V > > & & data , Interpolation interpolation , Interpolator interpolator , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : Track < K , V , R > { Utility : : move ( data ) , interpolation , interpolator , extrapolation , extrapolation } { }
/** @overload */
explicit Track ( std : : initializer_list < std : : pair < K , V > > data , Interpolation interpolation , Interpolator interpolator , Extrapolation extrapolation = Extrapolation : : Constant ) : Track < K , V , R > { Containers : : Array < std : : pair < K , V > > { InPlaceInit , data } , interpolation , interpolator , extrapolation } { }
/**
* @ brief Construct with generic interpolation behavior
* @ param data Keyframe data
* @ param interpolation Interpolation behavior
* @ param before Extrapolation behavior
* @ param after Extrapolation behavior after
*
* The keyframe data are assumed to be stored in sorted order . It ' s not
* an error to have two successive keyframes with the same frame value .
* The @ ref interpolator ( ) function is autodetected from
* @ p interpolation using @ ref interpolatorFor ( ) . See its documentation
* for more information .
*/
explicit Track ( Containers : : Array < std : : pair < K , V > > & & data , Interpolation interpolation , Extrapolation before , Extrapolation after ) noexcept : _data { Utility : : move ( data ) } , _interpolator { interpolatorFor < V , R > ( interpolation ) } , _interpolation { interpolation } , _before { before } , _after { after } { }
/** @overload */
explicit Track ( std : : initializer_list < std : : pair < K , V > > data , Interpolation interpolation , Extrapolation before , Extrapolation after ) : Track < K , V , R > { Containers : : Array < std : : pair < K , V > > { InPlaceInit , data } , interpolation , before , after } { }
/** @overload
* Equivalent to calling @ ref Track ( Containers : : Array < std : : pair < K , V > > & & , Interpolation , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
explicit Track ( Containers : : Array < std : : pair < K , V > > & & data , Interpolation interpolation , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : Track < K , V , R > { Utility : : move ( data ) , interpolation , extrapolation , extrapolation } { }
/** @overload */
explicit Track ( std : : initializer_list < std : : pair < K , V > > data , Interpolation interpolation , Extrapolation extrapolation = Extrapolation : : Constant ) : Track < K , V , R > { Containers : : Array < std : : pair < K , V > > { InPlaceInit , data } , interpolation , extrapolation , extrapolation } { }
/** @brief Copying is not allowed */
Track ( const Track < K , V , R > & ) = delete ;
/** @brief Move constructor */
Track ( Track < K , V , R > & & ) noexcept = default ;
/** @brief Copying is not allowed */
Track < K , V , R > & operator = ( const Track < K , V , R > & ) = delete ;
/** @brief Move constructor */
Track < K , V , R > & operator = ( Track < K , V , R > & & ) noexcept = default ;
/** @brief Conversion to a view */
operator TrackView < const K , const V , R > ( ) const noexcept {
return TrackView < const K , const V , R > { _data , _interpolation , _interpolator , _before , _after } ;
}
/** @overload */
operator TrackView < K , V , R > ( ) noexcept {
return TrackView < K , V , R > { _data , _interpolation , _interpolator , _before , _after } ;
}
/**
* @ brief Interpolation behavior
*
* Acts as a behavior hint to users that might want to supply their own
* interpolator function to @ ref at ( ) or @ ref atStrict ( ) .
* @ see @ ref interpolator ( )
*/
Interpolation interpolation ( ) const { return _interpolation ; }
/**
* @ brief Interpolation function
*
* @ see @ ref interpolation ( )
*/
Interpolator interpolator ( ) const { return _interpolator ; }
/**
* @ brief Extrapolation behavior before first keyframe
*
* @ see @ ref after ( ) , @ ref at ( )
*/
Extrapolation before ( ) const { return _before ; }
/**
* @ brief Extrapolation behavior after last keyframe
*
* @ see @ ref before ( ) , @ ref at ( )
*/
Extrapolation after ( ) const { return _after ; }
/**
* @ brief Duration of the track
*
* Calculated from first and last keyframe . If there are no keyframes ,
* a default - constructed value is returned . Use @ ref Math : : join ( ) to
* calculate combined duration for a set of tracks .
*/
Math : : Range1D < K > duration ( ) const {
return _data . isEmpty ( ) ? Math : : Range1D < K > { } : Math : : Range1D < K > { _data . front ( ) . first , _data . back ( ) . first } ;
}
/** @brief Keyframe count */
std : : size_t size ( ) const { return _data . size ( ) ; }
/**
* @ brief Keyframe data
*
* @ see @ ref keys ( ) , @ ref values ( ) , @ ref operator [ ] ( )
*/
Containers : : ArrayView < const std : : pair < K , V > > data ( ) const { return _data ; }
/** @overload */
Containers : : ArrayView < std : : pair < K , V > > data ( ) { return _data ; }
/**
* @ brief Key data
*
* @ see @ ref data ( ) , @ ref values ( ) , @ ref operator [ ] ( )
*/
Containers : : StridedArrayView1D < const K > keys ( ) const {
return _data ? Containers : : StridedArrayView1D < const K > { _data , & _data [ 0 ] . first , _data . size ( ) , sizeof ( std : : pair < K , V > ) } : nullptr ;
}
/** @overload */
Containers : : StridedArrayView1D < K > keys ( ) {
return _data ? Containers : : StridedArrayView1D < K > { _data , & _data [ 0 ] . first , _data . size ( ) , sizeof ( std : : pair < K , V > ) } : nullptr ;
}
/**
* @ brief Value data
*
* @ see @ ref data ( ) , @ ref keys ( ) , @ ref operator [ ] ( )
*/
Containers : : StridedArrayView1D < const V > values ( ) const {
return _data ? Containers : : StridedArrayView1D < const V > { _data , & _data [ 0 ] . second , _data . size ( ) , sizeof ( std : : pair < K , V > ) } : nullptr ;
}
/** @overload */
Containers : : StridedArrayView1D < V > values ( ) {
return _data ? Containers : : StridedArrayView1D < V > { _data , & _data [ 0 ] . second , _data . size ( ) , sizeof ( std : : pair < K , V > ) } : nullptr ;
}
/**
* @ brief Keyframe access
*
* @ see @ ref size ( )
*/
const std : : pair < K , V > & operator [ ] ( std : : size_t i ) const { return _data [ i ] ; }
/** @overload */
std : : pair < K , V > & operator [ ] ( std : : size_t i ) { return _data [ i ] ; }
/**
* @ brief Animated value at a given time
*
* Calls @ ref interpolate ( ) , see its documentation for more
* information . Note that this function performs a linear search every
* time , use @ ref at ( K , std : : size_t & ) const to supply a search hint .
* @ see @ ref atStrict ( K , std : : size_t & ) const ,
* @ ref at ( Interpolator , K ) const
*/
R at ( K frame ) const {
std : : size_t hint { } ;
return at ( _interpolator , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* Calls @ ref interpolate ( ) , see its documentation for more
* information .
* @ see @ ref at ( K ) const , @ ref atStrict ( K , std : : size_t & ) const ,
* @ ref at ( Interpolator , K , std : : size_t & ) const
*/
R at ( K frame , std : : size_t & hint ) const {
return at ( _interpolator , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* Unlike @ ref at ( K ) const calls @ ref interpolate ( ) with
* @ p interpolator , overriding the interpolator function set in
* constructor . See its documentation for more information .
* @ see @ ref at ( K , std : : size_t & ) const ,
* @ ref atStrict ( Interpolator , K , std : : size_t & ) const
*/
R at ( Interpolator interpolator , K frame ) const {
std : : size_t hint { } ;
return at ( interpolator , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* Unlike @ ref at ( K , std : : size_t & ) const calls @ ref interpolate ( ) with
* @ p interpolator , overriding the interpolator function set in
* constructor . See its documentation for more information .
* @ see @ ref atStrict ( Interpolator , K , std : : size_t & ) const
*/
R at ( Interpolator interpolator , K frame , std : : size_t & hint ) const {
return interpolate ( keys ( ) , values ( ) , _before , _after , interpolator , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* A faster version of @ ref at ( K , std : : size_t & ) const with some
* restrictions . Calls @ ref interpolateStrict ( ) , see its documentation
* for more information .
* @ see @ ref atStrict ( Interpolator , K , std : : size_t & ) const
*/
R atStrict ( K frame , std : : size_t & hint ) const {
return atStrict ( _interpolator , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* Unlike @ ref atStrict ( K , std : : size_t & ) const calls @ ref interpolate ( )
* with @ p interpolator , overriding the interpolator function set in
* constructor . See its documentation for more information .
* @ see @ ref at ( K , std : : size_t & ) const
*/
R atStrict ( Interpolator interpolator , K frame , std : : size_t & hint ) const {
return interpolateStrict ( keys ( ) , values ( ) , interpolator , frame , hint ) ;
}
private :
Containers : : Array < std : : pair < K , V > > _data ;
Interpolator _interpolator ;
Interpolation _interpolation ;
Extrapolation _before , _after ;
} ;
}
# ifndef DOXYGEN_GENERATING_OUTPUT
/* For a friend declaration in TrackViewStorage */
namespace Trade { class AnimationTrackData ; }
# endif
namespace Animation {
/**
@ brief Type - erased track view storage
Cast to @ ref TrackView of correct type to get access to all members .
@ experimental
*/
template < class K > class TrackViewStorage {
public :
/** @brief Key type */
typedef K KeyType ;
constexpr /*implicit*/ TrackViewStorage ( ) noexcept : _keys { } , _values { } , _interpolator { } , _interpolation { } , _before { } , _after { } { }
/**
* @ brief Interpolation behavior
*
* Acts as a behavior hint to users that might want to supply their own
* interpolator function to @ ref TrackView : : at ( ) or
* @ ref TrackView : : atStrict ( ) .
* @ see @ ref TrackView : : interpolator ( )
*/
Interpolation interpolation ( ) const { return _interpolation ; }
/**
* @ brief Extrapolation behavior before first keyframe
*
* @ see @ ref TrackView : : after ( ) , @ ref TrackView : : at ( ) ,
* @ ref TrackView : : atStrict ( )
*/
Extrapolation before ( ) const { return _before ; }
/**
* @ brief Extrapolation behavior after last keyframe
*
* @ see @ ref TrackView : : before ( ) , @ ref TrackView : : at ( ) ,
* @ ref TrackView : : atStrict ( )
*/
Extrapolation after ( ) const { return _after ; }
/**
* @ brief Duration of the track
*
* Calculated from first and last keyframe . If there are no keyframes ,
* a default - constructed value is returned . Use @ ref Math : : join ( ) to
* calculate combined duration for a set of tracks .
*/
Math : : Range1D < typename std : : remove_const < K > : : type > duration ( ) const {
return _keys . isEmpty ( ) ? Math : : Range1D < typename std : : remove_const < K > : : type > { } : Math : : Range1D < typename std : : remove_const < K > : : type > { _keys . front ( ) , _keys . back ( ) } ;
}
/** @brief Keyframe count */
std : : size_t size ( ) const {
return _keys . size ( ) ;
}
/**
* @ brief Type - erased interpolation function
* @ m_since_latest
*
* Has to be cast to a type corresponding to the value type before use .
* Use @ ref TrackView and @ ref TrackView : : interpolator ( ) to get the
* interpolator function in a concrete type .
*/
void ( * interpolator ( ) const ) ( ) {
return _interpolator ;
}
/**
* @ brief Key data
*
* @ see @ ref values ( ) , @ ref TrackView : : operator [ ] ( )
*/
Containers : : StridedArrayView1D < K > keys ( ) const {
return _keys ;
}
/**
* @ brief Type - erased value data
* @ m_since { 2020 , 06 }
*
* Use @ ref TrackView and @ ref TrackView : : values ( ) to get a typed view ,
* alternatively you can cast to a concrete type using
* @ ref Corrade : : Containers : : arrayCast ( ) .
* @ see @ ref keys ( ) , @ ref TrackView : : operator [ ] ( )
*/
Containers : : StridedArrayView1D < typename std : : conditional < std : : is_const < K > : : value , const void , void > : : type > values ( ) const {
return _values ;
}
private :
template < class , class , class > friend class TrackView ;
# ifndef DOXYGEN_GENERATING_OUTPUT
/* This one creates TrackViewStorage instances on the fly using the
below constructor */
friend Trade : : AnimationTrackData ;
# endif
explicit TrackViewStorage ( const Containers : : StridedArrayView1D < K > & keys , const Containers : : StridedArrayView1D < typename std : : conditional < std : : is_const < K > : : value , const void , void > : : type > & values , Interpolation interpolation , void ( * interpolator ) ( ) , Extrapolation before , Extrapolation after ) noexcept : _keys { keys } , _values { values } , _interpolator { interpolator } , _interpolation { interpolation } , _before { before } , _after { after } {
CORRADE_ASSERT ( keys . size ( ) = = values . size ( ) , " Animation::TrackView: expected key and value view to have the same size but got " < < keys . size ( ) < < " and " < < values . size ( ) , ) ;
}
Containers : : StridedArrayView1D < K > _keys ;
Containers : : StridedArrayView1D < typename std : : conditional < std : : is_const < K > : : value , const void , void > : : type > _values ;
void ( * _interpolator ) ( ) ;
Interpolation _interpolation ;
Extrapolation _before , _after ;
} ;
/**
@ brief Animation track view
@ tparam K Key type
@ tparam V Value type
@ tparam R Result type
Unlike @ ref Track this is a non - owning view onto keyframe + value pairs . The
@ p K and @ p V can be either both mutable or both @ cpp const @ ce . See the
@ ref Track documentation for more information .
@ experimental
*/
template < class K , class V , class R
# ifdef DOXYGEN_GENERATING_OUTPUT
= ResultOf < V >
# endif
> class TrackView : public TrackViewStorage < K > {
static_assert ( std : : is_const < K > : : value = = std : : is_const < V > : : value & & ! std : : is_const < R > : : value ,
" K and V should be either both mutable or both const; R shouldn't be const " ) ;
public :
/** @brief Value type */
typedef V ValueType ;
/**
* @ brief Key - value type
*
* Used mainly when converting from @ ref Track . Equal to
* @ cpp std : : pair < K , V > @ ce if @ p K and @ p V are not @ cpp const @ ce ,
* and to @ cpp const std : : pair < K_ , V_ > @ ce ( where @ p K_ / @ p V_ are
* with @ cpp const @ ce removed ) when they are @ cpp const @ ce .
*/
/** @todo drop this, supplying strided array views is the usual
workflow at this point */
typedef typename std : : conditional < std : : is_const < K > : : value , const std : : pair < typename std : : remove_const < K > : : type , typename std : : remove_const < V > : : type > , std : : pair < K , V > > : : type KeyValueType ;
/** @brief Animation result type */
typedef R ResultType ;
/** @brief Interpolation function */
typedef ResultType ( * Interpolator ) ( const ValueType & , const ValueType & , Float ) ;
/**
* @ brief Construct an empty track
*
* The @ ref keys ( ) , @ ref values ( ) and @ ref interpolator ( ) functions
* return @ cpp nullptr @ ce , @ ref at ( ) always returns a
* default - constructed value .
*/
/*implicit*/ TrackView ( ) noexcept { }
/**
* @ brief Construct with custom interpolator
* @ param keys Frame keys
* @ param values Frame values
* @ param interpolator Interpolation function
* @ param before Extrapolation behavior before
* @ param after Extrapolation behavior after
*
* The keyframe data are assumed to be stored in sorted order . It ' s not
* an error to have two successive keyframes with the same frame value .
* The @ ref interpolation ( ) field is set to @ ref Interpolation : : Custom .
* See @ ref TrackView ( const Containers : : StridedArrayView1D < K > & , const Containers : : StridedArrayView1D < V > & , Interpolation , Interpolator , Extrapolation , Extrapolation ) or
* @ ref TrackView ( const Containers : : StridedArrayView1D < K > & , const Containers : : StridedArrayView1D < V > & , Interpolation , Extrapolation , Extrapolation )
* for an alternative .
*/
/*implicit*/ TrackView ( const Containers : : StridedArrayView1D < K > & keys , const Containers : : StridedArrayView1D < V > & values , Interpolator interpolator , Extrapolation before , Extrapolation after ) noexcept : TrackViewStorage < K > { keys , values , Interpolation : : Custom , reinterpret_cast < void ( * ) ( ) > ( interpolator ) , before , after } { }
/** @overload
* Equivalent to calling @ ref TrackView ( const Containers : : StridedArrayView1D < K > & , const Containers : : StridedArrayView1D < V > & , Interpolator , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
/*implicit*/ TrackView ( const Containers : : StridedArrayView1D < K > & keys , const Containers : : StridedArrayView1D < V > & values , Interpolator interpolator , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : TrackView < K , V , R > { keys , values , interpolator , extrapolation , extrapolation } { }
/**
* @ brief Construct with custom interpolator from an interleaved array
* @ param data Keyframe data
* @ param interpolator Interpolation function
* @ param before Extrapolation behavior before
* @ param after Extrapolation behavior after
*
* Converts @ p data to a pair of strided array views and calls
* @ ref TrackView ( const Containers : : StridedArrayView1D < K > & , const Containers : : StridedArrayView1D < V > & , Interpolator , Extrapolation , Extrapolation ) .
*/
/** @todo drop this, supplying strided array views is the usual
workflow at this point */
/*implicit*/ TrackView ( Containers : : ArrayView < KeyValueType > data , Interpolator interpolator , Extrapolation before , Extrapolation after ) noexcept : TrackView < K , V , R > { Containers : : StridedArrayView1D < K > { data , data ? & data [ 0 ] . first : nullptr , data . size ( ) , sizeof ( std : : pair < K , V > ) } , Containers : : StridedArrayView1D < V > { data , data ? & data [ 0 ] . second : nullptr , data . size ( ) , sizeof ( std : : pair < K , V > ) } , interpolator , before , after } { }
/** @overload
* Equivalent to calling @ ref TrackView ( Containers : : ArrayView < KeyValueType > , Interpolator , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
/** @todo drop this, supplying strided array views is the usual
workflow at this point */
explicit TrackView ( Containers : : ArrayView < KeyValueType > data , Interpolator interpolator , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : TrackView < K , V , R > { data , interpolator , extrapolation , extrapolation } { }
/**
* @ brief Construct with both generic and custom interpolator
* @ param keys Frame keys
* @ param values Frame values
* @ param interpolation Interpolation behavior
* @ param interpolator Interpolator function
* @ param before Extrapolation behavior before
* @ param after Extrapolation behavior after
*
* The keyframe data are assumed to be stored in sorted order . It ' s not
* an error to have two successive keyframes with the same frame value .
* @ p interpolation acts as a behavior hint to users that might want to
* supply their own interpolator function to @ ref at ( ) or
* @ ref atStrict ( ) .
*/
/*implicit*/ TrackView ( const Containers : : StridedArrayView1D < K > & keys , const Containers : : StridedArrayView1D < V > & values , Interpolation interpolation , Interpolator interpolator , Extrapolation before , Extrapolation after ) noexcept : TrackViewStorage < K > { keys , values , interpolation , reinterpret_cast < void ( * ) ( ) > ( interpolator ) , before , after } { }
/** @overload
* Equivalent to calling @ ref TrackView ( const Containers : : StridedArrayView1D < K > & , const Containers : : StridedArrayView1D < V > & , Interpolation , Interpolator , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
/*implicit*/ TrackView ( const Containers : : StridedArrayView1D < K > & keys , const Containers : : StridedArrayView1D < V > & values , Interpolation interpolation , Interpolator interpolator , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : TrackView < K , V , R > { keys , values , interpolation , interpolator , extrapolation , extrapolation } { }
/**
* @ brief Construct with both generic and custom interpolator from an interleaved array
* @ param data Keyframe data
* @ param interpolation Interpolation behavior
* @ param interpolator Interpolator function
* @ param before Extrapolation behavior before
* @ param after Extrapolation behavior after
*
* Converts @ p data to a pair of strided array views and calls
* @ ref TrackView ( const Containers : : StridedArrayView1D < K > & , const Containers : : StridedArrayView1D < V > & , Interpolator , Extrapolation , Extrapolation ) .
*/
/** @todo drop this, supplying strided array views is the usual
workflow at this point */
/*implicit*/ TrackView ( Containers : : ArrayView < KeyValueType > data , Interpolation interpolation , Interpolator interpolator , Extrapolation before , Extrapolation after ) noexcept : TrackViewStorage < K > { Containers : : StridedArrayView1D < K > { data , data ? & data [ 0 ] . first : nullptr , data . size ( ) , sizeof ( std : : pair < K , V > ) } , Containers : : StridedArrayView1D < V > { data , data ? & data [ 0 ] . second : nullptr , data . size ( ) , sizeof ( std : : pair < K , V > ) } , interpolation , reinterpret_cast < void ( * ) ( ) > ( interpolator ) , before , after } { }
/** @overload
* Equivalent to calling @ ref TrackView ( Containers : : ArrayView < KeyValueType > , Interpolation , Interpolator , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
/** @todo drop this, supplying strided array views is the usual
workflow at this point */
/*implicit*/ TrackView ( Containers : : ArrayView < KeyValueType > data , Interpolation interpolation , Interpolator interpolator , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : TrackView < K , V , R > { data , interpolation , interpolator , extrapolation , extrapolation } { }
/**
* @ brief Construct with generic interpolation behavior
* @ param keys Frame keys
* @ param values Frame values
* @ param interpolation Interpolation behavior
* @ param before Extrapolation behavior before
* @ param after Extrapolation behavior after
*
* The keyframe data are assumed to be stored in sorted order . It ' s not
* an error to have two successive keyframes with the same frame value .
* The @ ref interpolator ( ) function is autodetected from
* @ p interpolation using @ ref interpolatorFor ( ) . See its documentation
* for more information .
*/
/*implicit*/ TrackView ( const Containers : : StridedArrayView1D < K > & keys , const Containers : : StridedArrayView1D < V > & values , Interpolation interpolation , Extrapolation before , Extrapolation after ) noexcept : TrackViewStorage < K > { keys , values , interpolation , reinterpret_cast < void ( * ) ( ) > ( interpolatorFor < V , R > ( interpolation ) ) , before , after } { }
/** @overload
* Equivalent to calling @ ref TrackView ( const Containers : : StridedArrayView1D < K > & , const Containers : : StridedArrayView1D < V > & , Interpolation , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
/*implicit*/ TrackView ( const Containers : : StridedArrayView1D < K > & keys , const Containers : : StridedArrayView1D < V > & values , Interpolation interpolation , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : TrackView < K , V , R > { keys , values , interpolation , extrapolation , extrapolation } { }
/**
* @ brief Construct with generic interpolation behavior from an interleaved array
* @ param data Keyframe data
* @ param interpolation Interpolation behavior
* @ param before Extrapolation behavior before
* @ param after Extrapolation behavior after
*
* Converts @ p data to a pair of strided array views and calls
* @ ref TrackView ( const Containers : : StridedArrayView1D < K > & , const Containers : : StridedArrayView1D < V > & , Interpolator , Extrapolation , Extrapolation ) .
*/
/** @todo drop this, supplying strided array views is the usual
workflow at this point */
/*implicit*/ TrackView ( Containers : : ArrayView < KeyValueType > data , Interpolation interpolation , Extrapolation before , Extrapolation after ) noexcept : TrackView < K , V , R > { Containers : : StridedArrayView1D < K > { data , data ? & data [ 0 ] . first : nullptr , data . size ( ) , sizeof ( std : : pair < K , V > ) } , Containers : : StridedArrayView1D < V > { data , data ? & data [ 0 ] . second : nullptr , data . size ( ) , sizeof ( std : : pair < K , V > ) } , interpolation , before , after } { }
/** @overload
* Equivalent to calling @ ref TrackView ( Containers : : ArrayView < KeyValueType > , Interpolation , Extrapolation , Extrapolation )
* with both @ p before and @ p after set to @ p extrapolation .
*/
/** @todo drop this, supplying strided array views is the usual
workflow at this point */
/*implicit*/ TrackView ( Containers : : ArrayView < KeyValueType > data , Interpolation interpolation , Extrapolation extrapolation = Extrapolation : : Constant ) noexcept : TrackView < K , V , R > { data , interpolation , extrapolation , extrapolation } { }
/** @brief Convert a mutable view to a const one */
/* This is the only variant that works on MSVC 2015, std::remove_const
in the signature didn ' t work there */
template < class K2 , class V2 , class = typename std : : enable_if < std : : is_same < const K2 , K > : : value & & std : : is_same < const V2 , V > : : value > : : type > /*implicit*/ TrackView ( const TrackView < K2 , V2 , R > & other ) noexcept : TrackViewStorage < K > { other . _keys , other . _values , other . _interpolation , other . _interpolator , other . _before , other . _after } { }
/**
* @ brief Interpolation function
*
* @ see @ ref interpolation ( )
*/
Interpolator interpolator ( ) const {
return reinterpret_cast < Interpolator > ( TrackViewStorage < K > : : _interpolator ) ;
}
/**
* @ brief Value data
*
* @ see @ ref keys ( ) , @ ref operator [ ] ( )
*/
Containers : : StridedArrayView1D < V > values ( ) const {
return Containers : : arrayCast < V > ( TrackViewStorage < K > : : _values ) ;
}
/**
* @ brief Keyframe access
*
* @ see @ ref size ( )
*/
std : : pair < typename std : : remove_const < K > : : type , typename std : : remove_const < V > : : type > operator [ ] ( std : : size_t i ) const {
return { TrackViewStorage < K > : : _keys [ i ] , values ( ) [ i ] } ;
}
/**
* @ brief Animated value at a given time
*
* Calls @ ref interpolate ( ) , see its documentation for more
* information . Note that this function performs a linear search every
* time , use @ ref at ( K , std : : size_t & ) const to supply a search hint .
* @ see @ ref atStrict ( K , std : : size_t & ) const ,
* @ ref at ( Interpolator , K ) const
*/
R at ( K frame ) const {
std : : size_t hint { } ;
return at ( interpolator ( ) , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* Calls @ ref interpolate ( ) , see its documentation for more
* information .
* @ see @ ref at ( K ) const , @ ref atStrict ( K , std : : size_t & ) const ,
* @ ref at ( Interpolator , K , std : : size_t & ) const
*/
R at ( K frame , std : : size_t & hint ) const {
return at ( interpolator ( ) , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* Unlike @ ref at ( K ) const calls @ ref interpolate ( ) with
* @ p interpolator , overriding the interpolator function set in
* constructor . See its documentation for more information .
* @ see @ ref at ( K , std : : size_t & ) const ,
* @ ref atStrict ( Interpolator , K , std : : size_t & ) const
*/
R at ( Interpolator interpolator , K frame ) const {
std : : size_t hint { } ;
return at ( interpolator , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* Unlike @ ref at ( K , std : : size_t & ) const calls @ ref interpolate ( ) with
* @ p interpolator , overriding the interpolator function set in
* constructor . See its documentation for more information .
* @ see @ ref atStrict ( Interpolator , K , std : : size_t & ) const
*/
R at ( Interpolator interpolator , K frame , std : : size_t & hint ) const {
return interpolate < typename std : : remove_const < K > : : type , typename std : : remove_const < V > : : type , R > ( TrackViewStorage < K > : : _keys , values ( ) , TrackViewStorage < K > : : _before , TrackViewStorage < K > : : _after , interpolator , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* A faster version of @ ref at ( K , std : : size_t & ) const with some
* restrictions . Calls @ ref interpolateStrict ( ) , see its documentation
* for more information .
* @ see @ ref atStrict ( Interpolator , K , std : : size_t & ) const
*/
R atStrict ( K frame , std : : size_t & hint ) const {
return atStrict ( interpolator ( ) , frame , hint ) ;
}
/**
* @ brief Animated value at a given time
*
* Unlike @ ref atStrict ( K , std : : size_t & ) const calls @ ref interpolate ( )
* with @ p interpolator , overriding the interpolator function set in
* constructor . See its documentation for more information .
* @ see @ ref at ( K , std : : size_t & ) const
*/
R atStrict ( Interpolator interpolator , K frame , std : : size_t & hint ) const {
return interpolateStrict < typename std : : remove_const < K > : : type , typename std : : remove_const < V > : : type , R > ( TrackViewStorage < K > : : _keys , values ( ) , interpolator , frame , hint ) ;
}
} ;
} }
# endif