00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #pragma once
00026
00027 #include "cinder/Cinder.h"
00028 #include "cinder/TimelineItem.h"
00029 #include "cinder/CinderMath.h"
00030 #include "cinder/Easing.h"
00031 #include "cinder/Function.h"
00032
00033 #include <list>
00034 #include <boost/utility.hpp>
00035
00036 namespace cinder {
00037
00038 class Timeline;
00039 typedef std::shared_ptr<Timeline> TimelineRef;
00040
00041 template<typename T>
00042 class Tween;
00043 typedef std::function<float (float)> EaseFn;
00044
00045 template<typename T>
00046 class Anim;
00047
00048 template<typename T>
00049 T tweenLerp( const T &start, const T &end, float time )
00050 {
00051 return start * ( 1 - time ) + end * time;
00052 }
00053
00054 class TweenBase : public TimelineItem {
00055 public:
00056 typedef std::function<void ()> StartFn;
00057 typedef std::function<void ()> FinishFn;
00058 typedef std::function<void ()> UpdateFn;
00059
00060 TweenBase( void *target, bool copyStartValue, float startTime, float duration, EaseFn easeFunction = easeNone );
00061 virtual ~TweenBase() {}
00062
00064 void setEaseFn( EaseFn easeFunction ) { mEaseFunction = easeFunction; }
00065 EaseFn getEaseFn() const { return mEaseFunction; }
00066
00067 void setStartFn( StartFn startFunction ) { mStartFunction = startFunction; }
00068 StartFn getStartFn() const { return mStartFunction; }
00069
00070 void setReverseStartFn( StartFn reverseStartFunction ) { mReverseStartFunction = reverseStartFunction; }
00071 StartFn getReverseStartFn() const { return mReverseStartFunction; }
00072
00073 void setUpdateFn( UpdateFn updateFunction ) { mUpdateFunction = updateFunction; }
00074 UpdateFn getUpdateFn() const { return mUpdateFunction; }
00075
00076 void setFinishFn( FinishFn finishFn ) { mFinishFunction = finishFn; }
00077 FinishFn getFinishFn() const { return mFinishFunction; }
00078
00079 void setReverseFinishFn( FinishFn reverseFinishFn ) { mReverseFinishFunction = reverseFinishFn; }
00080 FinishFn getReverseFinishFn() const { return mReverseFinishFunction; }
00081
00082 class Options {
00083 protected:
00084 Options( TimelineRef timeline )
00085 : mTimeline( timeline )
00086 {}
00087
00088 void appendTo( TweenBase &tweenBase, void *target, float offset );
00089 void timelineEnd( TweenBase &tweenBase, float offset );
00090
00091 TimelineRef mTimeline;
00092 };
00093
00094 protected:
00095 virtual void reset( bool unsetStarted )
00096 {
00097 TimelineItem::reset( unsetStarted );
00098 }
00099
00100 virtual void complete( bool reverse )
00101 {
00102 if( reverse && mReverseFinishFunction )
00103 mReverseFinishFunction();
00104 else if( ( ! reverse ) && mFinishFunction )
00105 mFinishFunction();
00106 }
00107
00108
00109 StartFn mStartFunction, mReverseStartFunction;
00110 UpdateFn mUpdateFunction;
00111 FinishFn mFinishFunction, mReverseFinishFunction;
00112
00113 EaseFn mEaseFunction;
00114 float mDuration;
00115 bool mCopyStartValue;
00116 };
00117
00118 template<typename T>
00119 class TweenRef : public std::shared_ptr<Tween<T> > {
00120 public:
00121 TweenRef( const std::shared_ptr<Tween<T> > &sp )
00122 : std::shared_ptr<Tween<T> >( sp )
00123 {}
00124 TweenRef( Tween<T> *tween )
00125 : std::shared_ptr<Tween<T> >( tween )
00126 {}
00127 TweenRef()
00128 : std::shared_ptr<Tween<T> >()
00129 {}
00130 };
00131
00132 template<typename T>
00133 class Tween : public TweenBase {
00134 public:
00135 typedef std::function<T (const T&, const T&, float)> LerpFn;
00136
00137
00138 Tween( T *target, T endValue, float startTime, float duration,
00139 EaseFn easeFunction = easeNone, LerpFn lerpFunction = &tweenLerp<T> )
00140 : TweenBase( target, true, startTime, duration, easeFunction ), mStartValue( *target ), mEndValue( endValue ), mLerpFunction( lerpFunction )
00141 {
00142 }
00143
00144 Tween( T *target, T startValue, T endValue, float startTime, float duration,
00145 EaseFn easeFunction = easeNone, LerpFn lerpFunction = &tweenLerp<T> )
00146 : TweenBase( target, false, startTime, duration, easeFunction ), mStartValue( startValue ), mEndValue( endValue ), mLerpFunction( lerpFunction )
00147 {
00148 }
00149
00150 virtual ~Tween() {}
00151
00153 T getStartValue() const { return mStartValue; }
00154 T getEndValue() const { return mEndValue; }
00155 T* getTarget() const { return reinterpret_cast<T*>( mTarget ); }
00156
00158 bool isCopyStartValue() { return mCopyStartValue; }
00159
00160 void setLerpFn( const LerpFn &lerpFn ) { mLerpFunction = lerpFn; }
00161
00163 TweenRef<T> getThisRef(){ return TweenRef<T>( std::static_pointer_cast<Tween<T> >( shared_from_this() ) ); }
00164
00165
00166 class Options : public TweenBase::Options {
00167 public:
00168 Options& startFn( const TweenBase::StartFn &startFn ) { mTweenRef->setStartFn( startFn ); return *this; }
00169 Options& reverseStartFn( const TweenBase::StartFn &reverseStartFn ) { mTweenRef->setReverseStartFn( reverseStartFn ); return *this; }
00170 Options& updateFn( const TweenBase::UpdateFn &updateFn ) { mTweenRef->setUpdateFn( updateFn ); return *this; }
00171 Options& finishFn( const TweenBase::FinishFn &finishFn ) { mTweenRef->setFinishFn( finishFn ); return *this; }
00172 Options& reverseFinishFn( const TweenBase::FinishFn &reverseFinishFn ) { mTweenRef->setReverseFinishFn( reverseFinishFn ); return *this; }
00173 Options& easeFn( const EaseFn &easeFunc ) { mTweenRef->setEaseFn( easeFunc ); return *this; }
00174 Options& delay( float delayAmt ) { mTweenRef->setStartTime( mTweenRef->getStartTime() + delayAmt ); return *this; }
00175 Options& autoRemove( bool remove = true ) { mTweenRef->setAutoRemove( remove ); return *this; }
00176 Options& loop( bool doLoop = true ) { mTweenRef->setLoop( doLoop ); return *this; }
00177 Options& pingPong( bool doPingPong = true ) { mTweenRef->setPingPong( doPingPong ); return *this; }
00178 Options& timelineEnd( float offset = 0 ) { TweenBase::Options::timelineEnd( *mTweenRef, offset ); return *this; }
00179 template<typename Y>
00180 Options& appendTo( Anim<Y> *endTarget, float offset = 0 ) { TweenBase::Options::appendTo( *mTweenRef, endTarget->ptr(), offset ); return *this; }
00181 Options& appendTo( void *endTarget, float offset = 0 ) { TweenBase::Options::appendTo( *mTweenRef, endTarget, offset ); return *this; }
00182 Options& lerpFn( const typename Tween<T>::LerpFn &lerpFn ) { mTweenRef->setLerpFn( lerpFn ); return *this; }
00183
00184 operator TweenRef<T>() { return mTweenRef; }
00185
00186 protected:
00187 Options( TweenRef<T> tweenRef, TimelineRef timeline )
00188 : TweenBase::Options( timeline ), mTweenRef( tweenRef )
00189 {}
00190
00191 TweenRef<T> mTweenRef;
00192
00193 friend class Timeline;
00194 };
00195
00196
00197 protected:
00198 virtual void reverse()
00199 {
00200 std::swap( mStartValue, mEndValue );
00201 }
00202
00203 virtual TimelineItemRef clone() const
00204 {
00205 std::shared_ptr<Tween<T> > result( new Tween<T>( *this ) );
00206 result->mCopyStartValue = false;
00207 return result;
00208 }
00209
00210 virtual TimelineItemRef cloneReverse() const
00211 {
00212 std::shared_ptr<Tween<T> > result( new Tween<T>( *this ) );
00213 std::swap( result->mStartValue, result->mEndValue );
00214 result->mCopyStartValue = false;
00215 return result;
00216 }
00217
00218 virtual void start( bool reverse )
00219 {
00220 if( mCopyStartValue )
00221 mStartValue = *(reinterpret_cast<T*>( mTarget ) );
00222 if( reverse && mReverseStartFunction )
00223 mReverseStartFunction();
00224 else if( ( ! reverse ) && mStartFunction )
00225 mStartFunction();
00226 }
00227
00228 virtual void update( float relativeTime )
00229 {
00230 *reinterpret_cast<T*>(mTarget) = mLerpFunction( mStartValue, mEndValue, mEaseFunction( relativeTime ) );
00231 if( mUpdateFunction )
00232 mUpdateFunction();
00233 }
00234
00235
00236 T mStartValue, mEndValue;
00237
00238 LerpFn mLerpFunction;
00239 };
00240
00241 template<typename T>
00242 class FnTween : public Tween<T> {
00243 public:
00244 FnTween( std::function<void (T)> fn, T startValue, T endValue, float startTime, float duration, EaseFn easeFunction = easeNone, typename Tween<T>::LerpFn lerpFunction = &tweenLerp<T> )
00245 : Tween<T>( &mValue, startValue, endValue, startTime, duration, easeFunction, lerpFunction ), mFn( fn ), mValue( startValue )
00246 {
00247 }
00248
00249 virtual void update( float relativeTime )
00250 {
00251 Tween<T>::update( relativeTime );
00252 if( mFn )
00253 mFn( mValue );
00254 }
00255
00256 std::function<void (T)> mFn;
00257 T mValue;
00258 };
00259
00260 template<typename T>
00261 class FnTweenRef : public TweenRef<T> {
00262 public:
00263 FnTweenRef( const std::shared_ptr<FnTween<T> > &sp )
00264 : TweenRef<T>( sp )
00265 {}
00266 FnTweenRef( FnTween<T> *fnTween )
00267 : TweenRef<T>( fnTween )
00268 {}
00269 FnTweenRef()
00270 : TweenRef<T>()
00271 {}
00272 };
00273
00274 class AnimBase {
00275 public:
00277 void stop();
00278
00280 TimelineRef getParent() const { return mParentTimeline; }
00281
00282 protected:
00283 AnimBase( void *voidPtr ) : mVoidPtr( voidPtr ) {}
00284 AnimBase( const AnimBase &rhs, void *voidPtr );
00285 ~AnimBase();
00286
00287 void set( const AnimBase &rhs );
00288 void setReplace( const AnimBase &rhs );
00289
00290 void setParentTimeline( TimelineRef parentTimeline );
00291
00292 void *mVoidPtr;
00293 TimelineRef mParentTimeline;
00294 };
00295
00296 template<typename T>
00297 class Anim : public AnimBase {
00298 public:
00299 Anim()
00300 : AnimBase( &mValue )
00301 {}
00302 Anim( T value )
00303 : AnimBase( &mValue), mValue( value )
00304 {}
00305 Anim( const Anim<T> &rhs )
00306 : AnimBase( rhs, &mValue ), mValue( rhs.mValue )
00307 {}
00308
00309 const T& operator()() const { return mValue; }
00310 T& operator()() { return mValue; }
00311
00312 operator const T&() const { return mValue; }
00313 Anim<T>& operator=( const Anim &rhs ) {
00314 if( this != &rhs ) {
00315 set( rhs );
00316 mValue = rhs.mValue;
00317 }
00318 return *this;
00319 }
00320
00321 #if defined( CINDER_RVALUE_REFERENCES )
00322 Anim( Anim &&rhs )
00323 : AnimBase( &mValue )
00324 {
00325 setReplace( rhs );
00326 rhs.mParentTimeline.reset();
00327 mValue = rhs.mValue;
00328 }
00329 Anim<T>& operator=( Anim &&rhs ) {
00330 if( this != &rhs ) {
00331 setReplace( rhs );
00332 rhs.mParentTimeline.reset();
00333 mValue = rhs.mValue;
00334 }
00335 return *this;
00336 }
00337 #endif
00338
00339 Anim<T>& operator=( T value ) { mValue = value; return *this; }
00340
00341 const T& value() const { return mValue; }
00342 T& value() { return mValue; }
00343
00344 const T* ptr() const { return &mValue; }
00345 T* ptr() { return &mValue; }
00346
00347 protected:
00348
00349 friend class Timeline;
00350
00351 T mValue;
00352 };
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 }