Commit bbc298a2 authored by Ole Untzelmann's avatar Ole Untzelmann

[Animations] Polishing #7

[Animations] Changed data structure from vector->list
[Animations] Added function to stop a running Animation
parent 6a1d9283
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Ole Untzelmann <ole.untzelmann@rwth-aachen.de> // // Copyright (c) 2011, Computer Graphics Group RWTH Aachen University //
// Animation classes // // All rights reserved. //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifndef ANIMATION_HH #ifndef ACGL_ANIMATIONS_ANIMATION_HH
#define ANIMATION_HH #define ACGL_ANIMATIONS_ANIMATION_HH
#include <math.h>
#include <vector>
#include <queue>
#include "Interpolator.hh"
#include "EaseFunctions.hh"
#include <ACGL/Utils/Log.hh>
#include <tr1/memory>
#include <ACGL/Base/Macros.hh>
#include <ACGL/Types.hh> #include <ACGL/Types.hh>
#include <ACGL/Base/Macros.hh>
#include <ACGL/Base/Interfaces.hh> #include <ACGL/Base/Interfaces.hh>
#include <ACGL/Animations/EaseFunctions.hh>
#include <ACGL/Animations/Interpolator.hh>
using namespace ACGL::Base; #include <list>
#include <queue>
namespace ACGL{ namespace ACGL{
namespace Animations{ namespace Animations{
// Animation ************************************************************************************* // Animation *************************************************************************************
class Animation class Animation
{ {
public: public:
Animation() : mInited(false) {}; enum RepeatMode {Endless = -1, EndlessNoRepeat = -2};
virtual ~Animation() {};
/**
Excecute an animation
@param msec The time in millicesonds to move on Animation() :
mInited(false),
mStopped(false) {};
virtual ~Animation() {};
@return Time left after the update virtual void init() = 0;
*/
virtual long update(uint_t msec) = 0; virtual long update(uint_t msec) = 0;
virtual bool finished() = 0;
virtual void init() = 0; inline const bool& isInited() const;
/** inline const bool& isStopped() const;
Returns if an animation has finished.
@return True if animation is finished inline void restart();
*/ inline void stop();
virtual bool finished() = 0;
protected: protected:
bool mInited; bool mInited;
bool mStopped;
private: private:
}; };
ACGL_SHARED_TYPEDEF(Animation) ACGL_SHARED_TYPEDEF(Animation)
typedef std::vector<SharedAnimation> AnimationList; typedef std::list<SharedAnimation> AnimationList;
typedef std::queue<SharedAnimation> AnimationQueue; typedef std::queue<SharedAnimation> AnimationQueue;
class AnimationManager class AnimationManager
{ {
public: public:
static void push(const SharedAnimation& _animation); static void push(const SharedAnimation& _animation);
static void update(uint_t _msec); static void update(uint_t _msec);
...@@ -84,14 +69,17 @@ private: ...@@ -84,14 +69,17 @@ private:
class AnimationEvent : public Animation class AnimationEvent : public Animation
{ {
public: public:
AnimationEvent(const uint_t _id, const SharedINotifiable& _event); AnimationEvent(const uint_t _id, const ACGL::Base::SharedINotifiable& _event);
virtual void init();
virtual long update(uint_t _msec); virtual long update(uint_t _msec);
virtual bool finished(); virtual bool finished();
private: private:
SharedINotifiable mEvent; ACGL::Base::SharedINotifiable mEvent;
uint_t mId; uint_t mId;
bool mEventCalled;
}; };
ACGL_SHARED_TYPEDEF(AnimationEvent) ACGL_SHARED_TYPEDEF(AnimationEvent)
...@@ -119,7 +107,7 @@ ACGL_SHARED_TYPEDEF(AnimationWait) ...@@ -119,7 +107,7 @@ ACGL_SHARED_TYPEDEF(AnimationWait)
class AnimationSequential : public Animation class AnimationSequential : public Animation
{ {
public: public:
AnimationSequential(const uint_t _loops = 0); AnimationSequential(const int_t _loops = 0);
virtual ~AnimationSequential(); virtual ~AnimationSequential();
virtual void init(); virtual void init();
...@@ -129,13 +117,10 @@ public: ...@@ -129,13 +117,10 @@ public:
void push_animation(const SharedAnimation& _animation); void push_animation(const SharedAnimation& _animation);
private: private:
uint_t mLoops; int_t mLoops;
bool mFrontInited; AnimationList::iterator mCurrentPosition;
uint_t mCurrentPosition;
AnimationList mAnimations; AnimationList mAnimations;
//AnimationQueue mFinishedAnimations;
}; };
ACGL_SHARED_TYPEDEF(AnimationSequential) ACGL_SHARED_TYPEDEF(AnimationSequential)
...@@ -145,7 +130,7 @@ ACGL_SHARED_TYPEDEF(AnimationSequential) ...@@ -145,7 +130,7 @@ ACGL_SHARED_TYPEDEF(AnimationSequential)
class AnimationParallel : public Animation class AnimationParallel : public Animation
{ {
public: public:
AnimationParallel(const uint_t _loops = 0); AnimationParallel(const int_t _loops = 0);
virtual ~AnimationParallel(); virtual ~AnimationParallel();
virtual void init(); virtual void init();
...@@ -155,12 +140,10 @@ public: ...@@ -155,12 +140,10 @@ public:
void push_animation(const SharedAnimation& animation); void push_animation(const SharedAnimation& animation);
private: private:
uint_t mLoops; int_t mLoops;
std::queue<uint_t> mAnimationsToInit;
AnimationList mAnimations; AnimationList mAnimations;
AnimationList mFinishedAnimations; uint_t mRunningAnimations;
}; };
ACGL_SHARED_TYPEDEF(AnimationParallel) ACGL_SHARED_TYPEDEF(AnimationParallel)
...@@ -188,6 +171,8 @@ public: ...@@ -188,6 +171,8 @@ public:
{ {
mCurrentTime = 0; mCurrentTime = 0;
mInterpolator.init(mpData); mInterpolator.init(mpData);
mInited = true;
} }
virtual long update(uint_t _msec) virtual long update(uint_t _msec)
...@@ -266,4 +251,4 @@ ACGL_SHARED_TYPEDEF(AnimationVec3Linear) ...@@ -266,4 +251,4 @@ ACGL_SHARED_TYPEDEF(AnimationVec3Linear)
#endif // ANIMATION_HH #endif // ACGL_ANIMATIONS_ANIMATION_HH
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Ole Untzelmann <ole.untzelmann@rwth-aachen.de> // // Copyright (c) 2011, Computer Graphics Group RWTH Aachen University //
// Interpolation Example // // All rights reserved. //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifndef EASEFUNCTIONS_HH #ifndef ACGL_ANIMATIONS_EASEFUNCTIONS_HH
#define EASEFUNCTIONS_HH #define ACGL_ANIMATIONS_EASEFUNCTIONS_HH
#include <math.h> #include <ACGL/Math/Math.hh>
#include <ACGL/Base/Macros.hh>
#include <tr1/memory> #include <tr1/memory>
#include <ACGL/Base/Macros.hh>
namespace ACGL namespace ACGL
{ {
...@@ -151,4 +151,4 @@ public: ...@@ -151,4 +151,4 @@ public:
} }
} }
#endif // EASEFUNCTIONS_HH #endif // ACGL_ANIMATIONS_EASEFUNCTIONS_HH
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Ole Untzelmann <ole.untzelmann@rwth-aachen.de> // // Copyright (c) 2011, Computer Graphics Group RWTH Aachen University //
// Interpolation Example // // All rights reserved. //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#ifndef INTERPOLATOR_HH #ifndef ACGL_ANIMATIONS_INTERPOLATOR_HH
#define INTERPOLATOR_HH #define ACGL_ANIMATIONS_INTERPOLATOR_HH
#include "EaseFunctions.hh" #include <ACGL/Animations/EaseFunctions.hh>
#include <ACGL/Utils/Log.hh>
#include <ACGL/Scene/NURBSCurve.hh> #include <ACGL/Scene/NURBSCurve.hh>
#include <vector>
#include <ACGL/Types.hh> #include <ACGL/Types.hh>
#include <ACGL/Base/Macros.hh>
#include <vector>
#include <tr1/memory> #include <tr1/memory>
#include <ACGL/Base/Macros.hh>
namespace ACGL namespace ACGL
{ {
...@@ -78,10 +76,8 @@ public: ...@@ -78,10 +76,8 @@ public:
} }
} }
inline const T interpolate(const float _progress) inline const T& interpolate(const float _progress)
{ {
//std::cout << "[LinearInterpolator] progress: "<<_progress<<std::endl;
return mStartValue + _progress*mDiffValue; return mStartValue + _progress*mDiffValue;
} }
...@@ -127,8 +123,9 @@ public: ...@@ -127,8 +123,9 @@ public:
{ {
} }
inline const T interpolate(float _progress) inline const T& interpolate(float _progress)
{ {
//TODO: This es very UGLY, implement a better way to find the current keypoint.
unsigned int i = 0; unsigned int i = 0;
for(i = 0 ;i < mKeypoints.size();i++) for(i = 0 ;i < mKeypoints.size();i++)
{ {
...@@ -187,7 +184,7 @@ public: ...@@ -187,7 +184,7 @@ public:
// insert_control_point(data, 0.0f); // insert_control_point(data, 0.0f);
} }
const T interpolate(float progress) const T& interpolate(float progress)
{ {
curve.insertKnot(progress); curve.insertKnot(progress);
// TODO: Interpolation code is missing // TODO: Interpolation code is missing
......
...@@ -7,6 +7,26 @@ namespace Animations ...@@ -7,6 +7,26 @@ namespace Animations
AnimationList AnimationManager::mAnimations; AnimationList AnimationManager::mAnimations;
const bool& Animation::isInited() const
{
return mInited;
}
const bool& Animation::isStopped() const
{
return mStopped;
}
void Animation::restart()
{
mInited = false;
}
void Animation::stop()
{
mStopped = true;
}
void AnimationManager::push(const SharedAnimation& _animation) void AnimationManager::push(const SharedAnimation& _animation)
{ {
mAnimations.push_back(_animation); mAnimations.push_back(_animation);
...@@ -16,19 +36,26 @@ void AnimationManager::push(const SharedAnimation& _animation) ...@@ -16,19 +36,26 @@ void AnimationManager::push(const SharedAnimation& _animation)
void AnimationManager::update(uint_t _msec) void AnimationManager::update(uint_t _msec)
{ {
uint_t id = 0; AnimationList::iterator current = mAnimations.begin();
while(id < mAnimations.size()) while(current != mAnimations.end())
{ {
mAnimations[id]->update(_msec); if((*current)->isStopped())
{
AnimationList::iterator toDelete = current;
current++;
mAnimations.erase(toDelete);
continue;
}
if(mAnimations[id]->finished()) (*current)->update(_msec);
if((*current)->finished())
{ {
mAnimations.erase(mAnimations.begin()+id); AnimationList::iterator toDelete = current;
/*mAnimations[id].reset(); current++;
mAnimations[id] = mAnimations[mAnimations.size()-1]; mAnimations.erase(toDelete);
mAnimations.erase(mAnimations.end()-1);*/ }else current++;
} else id++;
} }
} }
...@@ -37,24 +64,34 @@ void AnimationManager::cleanUp() ...@@ -37,24 +64,34 @@ void AnimationManager::cleanUp()
mAnimations.clear(); mAnimations.clear();
} }
AnimationEvent::AnimationEvent(const uint_t _id, const SharedINotifiable& _event) : AnimationEvent::AnimationEvent(const uint_t _id, const ACGL::Base::SharedINotifiable& _event) :
Animation(), Animation(),
mEvent(_event), mEvent(_event),
mId(_id) mId(_id),
mEventCalled(false)
{ {
} }
long AnimationEvent::update(uint_t _msec) void AnimationEvent::init()
{ {
return _msec; mEventCalled = false;
mInited = true;
} }
bool AnimationEvent::finished() long AnimationEvent::update(uint_t _msec)
{ {
if(mEvent) if(mEvent)
mEvent->notify(mId); mEvent->notify(mId);
return true; mEventCalled = true;
return _msec;
}
bool AnimationEvent::finished()
{
return mEventCalled;
} }
AnimationWait::AnimationWait(const uint_t _duration) : AnimationWait::AnimationWait(const uint_t _duration) :
...@@ -66,6 +103,8 @@ AnimationWait::AnimationWait(const uint_t _duration) : ...@@ -66,6 +103,8 @@ AnimationWait::AnimationWait(const uint_t _duration) :
void AnimationWait::init() void AnimationWait::init()
{ {
mTimeLeft = mDuration; mTimeLeft = mDuration;
mInited = true;
} }
long AnimationWait::update(uint_t _msec) long AnimationWait::update(uint_t _msec)
...@@ -89,9 +128,8 @@ bool AnimationWait::finished() ...@@ -89,9 +128,8 @@ bool AnimationWait::finished()
return mTimeLeft == 0; return mTimeLeft == 0;
} }
AnimationSequential::AnimationSequential(const uint_t _loops) : AnimationSequential::AnimationSequential(const int_t _loops) :
mLoops(_loops), mLoops(_loops),
mFrontInited(false),
mCurrentPosition(0), mCurrentPosition(0),
mAnimations() mAnimations()
{ {
...@@ -100,44 +138,52 @@ AnimationSequential::AnimationSequential(const uint_t _loops) : ...@@ -100,44 +138,52 @@ AnimationSequential::AnimationSequential(const uint_t _loops) :
AnimationSequential::~AnimationSequential() AnimationSequential::~AnimationSequential()
{ {
mAnimations.clear(); mAnimations.clear();
//while(!mAnimations.empty()) mAnimations.pop();
//while(!mFinishedAnimations.empty()) mFinishedAnimations.pop();
} }
void AnimationSequential::init() void AnimationSequential::init()
{ {
mCurrentPosition = 0; mCurrentPosition = mAnimations.begin();
mInited = true; mInited = true;
mFrontInited = false;
for(AnimationList::iterator current = mAnimations.begin(); current != mAnimations.end(); current++)
(*current)->restart();
} }
long AnimationSequential::update(uint_t _msec) long AnimationSequential::update(uint_t _msec)
{ {
while(!(mCurrentPosition >= mAnimations.size()) && _msec > 0) while(mCurrentPosition != mAnimations.end() && _msec > 0)
{ {
if(!mFrontInited) if((*mCurrentPosition)->isStopped())
{ {
mAnimations[mCurrentPosition]->init(); AnimationList::iterator toDelete = mCurrentPosition;
mFrontInited = true; mCurrentPosition++;
mAnimations.erase(toDelete);
continue;
} }
_msec = mAnimations[mCurrentPosition]->update(_msec); if(!(*mCurrentPosition)->isInited())
{
(*mCurrentPosition)->init();
}
_msec = (*mCurrentPosition)->update(_msec);
if(mAnimations[mCurrentPosition]->finished()) if((*mCurrentPosition)->finished())
{ {
//mFinishedAnimations.push(mAnimations.front()); if(mLoops == Animation::EndlessNoRepeat)
//mAnimations.pop(); {
mCurrentPosition++; AnimationList::iterator toDelete = mCurrentPosition;
mCurrentPosition++;
mAnimations.erase(toDelete);
}else mCurrentPosition++;
if(mCurrentPosition >= mAnimations.size() && mLoops != 0) if(mCurrentPosition == mAnimations.end() && mLoops != 0)
{ {
if(mLoops > 0) if(mLoops > 0)
mLoops--; mLoops--;
init(); init();
} }
mFrontInited = false;
} }
} }
...@@ -147,7 +193,7 @@ long AnimationSequential::update(uint_t _msec) ...@@ -147,7 +193,7 @@ long AnimationSequential::update(uint_t _msec)
bool AnimationSequential::finished() bool AnimationSequential::finished()
{ {
if(mLoops != 0) return false; if(mLoops != 0) return false;
else return mCurrentPosition >= mAnimations.size(); else return mCurrentPosition == mAnimations.end();
} }
void AnimationSequential::push_animation(const SharedAnimation& _animation) void AnimationSequential::push_animation(const SharedAnimation& _animation)
...@@ -155,7 +201,7 @@ void AnimationSequential::push_animation(const SharedAnimation& _animation) ...@@ -155,7 +201,7 @@ void AnimationSequential::push_animation(const SharedAnimation& _animation)
mAnimations.push_back(_animation); mAnimations.push_back(_animation);
} }
AnimationParallel::AnimationParallel(const uint_t _loops) : AnimationParallel::AnimationParallel(const int_t _loops) :
mLoops(_loops) mLoops(_loops)
{ {
...@@ -164,56 +210,73 @@ AnimationParallel::AnimationParallel(const uint_t _loops) : ...@@ -164,56 +210,73 @@ AnimationParallel::AnimationParallel(const uint_t _loops) :
AnimationParallel::~AnimationParallel() AnimationParallel::~AnimationParallel()
{ {
mAnimations.clear(); mAnimations.clear();
mFinishedAnimations.clear();
} }
void AnimationParallel::init() void AnimationParallel::init()
{ {
if(mFinishedAnimations.size() > 0) mRunningAnimations = mAnimations.size();
{
mAnimations.insert(mAnimations.end(), mFinishedAnimations.begin(), mFinishedAnimations.end());
mFinishedAnimations.clear();
}
while(!mAnimationsToInit.empty()) mAnimationsToInit.pop(); for(AnimationList::iterator it = mAnimations.begin(); it != mAnimations.end(); it++)
for(unsigned int i = 0;i < mAnimations.size();i++)
{ {
mAnimationsToInit.push(i); (*it)->restart();
} }
mInited = true;
} }
long AnimationParallel::update(uint_t _msec) long AnimationParallel::update(uint_t _msec)
{ {
while(!mAnimationsToInit.empty()) uint_t timeLeftMin = _msec;
{
mAnimations[mAnimationsToInit.front()]->init();
mAnimationsToInit.pop();
}
uint_t time_left_min = _msec;
unsigned int i = 0; AnimationList::iterator current = mAnimations.begin();
while(i < mAnimations.size()) while(current != mAnimations.end())
{ {
uint_t time_left = mAnimations[i]->update(_msec); if((*current)->isStopped())
{
if( !(*current)->finished() )
mRunningAnimations--;
if(time_left < time_left_min) AnimationList::iterator toDelete = current;
time_left_min = time_left; current++;
mAnimations.erase(toDelete);
continue;
}
if(!(*current)->isInited())
{
(*current)->init();
}
if(mAnimations[i]->finished()) if(!(*current)->finished())
{ {
mFinishedAnimations.push_back(mAnimations[i]); uint_t timeLeft = (*current)->update(_msec);
mAnimations[i] = mAnimations[mAnimations.size()-1];
mAnimations.erase(mAnimations.end()-1); if(timeLeft < timeLeftMin)
}else i++; timeLeftMin = timeLeft;
if((*current)->finished())
{
if(mLoops == Animation::EndlessNoRepeat)
{
AnimationList::iterator toDelete = current;
current++;
mAnimations.erase(toDelete);
current--;
}
mRunningAnimations--;
}
}
current++;
} }
return time_left_min; return timeLeftMin;
} }
bool AnimationParallel::finished() bool AnimationParallel::finished()
{ {
if(mAnimations.empty() && mLoops != 0) if(mRunningAnimations == 0 && mLoops != 0)
{ {
if(mLoops > 0) if(mLoops > 0)
mLoops--; mLoops--;
...