/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ /*! \file animation.h A Set of functions to animate some floats inside of an Object We apologize, that most part of the Function-Definitions are located inside this h-file, but this must be like this because it is a template function. */ #ifndef _ANIMATION_H #define _ANIMATION_H #include "list.h" // FORWARD DEFINITION typedef enum ANIM_FUNCTION {ANIM_CONSTANT, ANIM_LINEAR, ANIM_SINE, ANIM_COSINE, ANIM_EXP, ANIM_NEG_EXP, ANIM_QUADRATIC, ANIM_RANDOM}; typedef enum ANIM_INFINITY {ANIM_INF_CONSTANT, ANIM_INF_LINEAR, ANIM_INF_PINGPONG, ANIM_INF_REWIND};//, ANIM_DELETE} typedef struct AnimKeyFrame { float duration; float value; ANIM_FUNCTION animFunc; }; /**********************TEST*******************************/ class aTest { public: aTest() { last = 0.0;} ~aTest() {} void littleDebug(float f) { diff = f - last; printf("f=%f, diff=%f\n", f,diff); last = f;} private: float diff; float last; }; //aTest::aTest() {} //aTest::~aTest() {} //void aTest::littleDebug(float f) /**********************TEST*******************************/ class Anim { public: virtual ~Anim(void); void doNotHandle(void); void setInfinity(ANIM_INFINITY postInfinity = ANIM_INF_CONSTANT); void play(); // equals resume(); void stop(); void pause(); void replay(); virtual void rewind() = 0; virtual void tick(float time) = 0; /* implement in subclasses: * * De-/Constructor * Animation Functions * virtual tick * List of keyFrames * currentKeyFrame/nextKeyFrame * virtual rewind, to go to the first Keyframe. (other functions will call this one) */ protected: Anim(void); // variables float localTime; ANIM_INFINITY postInfinity; bool bHasKeys; bool bHandled; //!< If this Animation is handled by the AnimationPlayer. bool bRunning; }; //! A Class to handle some animation for single floated values. template class tAnim : public Anim { public: tAnim(T* object = NULL, void (T::*funcToAnim)(float) = NULL); virtual ~tAnim(); virtual void rewind(); void setFuncToAnim(T* object, void (T::*funcToAnim)(float)); void addKeyFrame(float value, float duration, ANIM_FUNCTION animFunc = ANIM_LINEAR); virtual void tick(float time); // animation functions void setAnimFunc(ANIM_FUNCTION animFunc); float constant(float timePassed) const; float linear(float timePassed) const; float sine(float timePassed) const; float cosine(float timePassed) const; float exp(float timePassed) const; float negExp(float timePassed) const; float quadratic(float timePassed) const; float random(float timePassed) const; // ANIM_FUNCTION animFunc; float (tAnim::*animFunc)(float) const; AnimKeyFrame* currentKeyFrame; AnimKeyFrame* nextKeyFrame; tList* keyFrameList; private: T* object; void (T::*funcToAnim)(float); }; /** \brief standard constructor */ template tAnim::tAnim (T* object, void (T::*funcToAnim)(float)) { // create a new List this->keyFrameList = new tList(); AnimKeyFrame* tmpKeyFrame = new AnimKeyFrame; tmpKeyFrame->value = 0.0; tmpKeyFrame->duration = 1.0; keyFrameList->add(tmpKeyFrame); this->currentKeyFrame = tmpKeyFrame; this->nextKeyFrame = tmpKeyFrame; this->animFunc = &tAnim::linear; this->setFuncToAnim(object, funcToAnim); } /** \brief standard deconstructor */ template tAnim::~tAnim () { // delete all the KeyFrames tIterator* itKF = keyFrameList->getIterator(); AnimKeyFrame* enumKF = itKF->nextElement(); while (enumKF) { delete enumKF; enumKF = itKF->nextElement(); } delete itKF; delete this->keyFrameList; } template void tAnim::rewind(void) { this->currentKeyFrame = keyFrameList->firstElement(); this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement()); this->localTime = 0.0; } template void tAnim::setFuncToAnim(T* object, void (T::*funcToAnim)(float)) { this->object = object; this->funcToAnim = funcToAnim; } template void tAnim::addKeyFrame(float value, float duration, ANIM_FUNCTION animFunc) { // some small check if (duration <= 0.0) duration = 1.0; AnimKeyFrame* tmpKeyFrame; if (bHasKeys) { tmpKeyFrame = new AnimKeyFrame; if (this->currentKeyFrame == this->nextKeyFrame) this->nextKeyFrame = tmpKeyFrame; this->keyFrameList->add(tmpKeyFrame); } else { tmpKeyFrame = this->keyFrameList->firstElement(); bHasKeys = true; } tmpKeyFrame->value = value; tmpKeyFrame->duration = duration; tmpKeyFrame->animFunc = animFunc; } template void tAnim::tick(float time) { if (this->bRunning) { this->localTime += time; if (localTime >= this->currentKeyFrame->duration) { this->localTime = 0; if (this->currentKeyFrame == this->keyFrameList->lastElement()) switch (this->postInfinity) { case ANIM_INF_CONSTANT: this->bRunning = false; break; case ANIM_INF_REWIND: break; } this->currentKeyFrame = this->keyFrameList->nextElement(this->currentKeyFrame); this->nextKeyFrame = this->keyFrameList->nextElement(this->nextKeyFrame); printf("%p from:%f to:%f\n", this->currentKeyFrame,this->currentKeyFrame->value, this->nextKeyFrame->value); this->setAnimFunc(this->currentKeyFrame->animFunc); } (this->object->*(funcToAnim))((this->*animFunc)(this->localTime)); } } template void tAnim::setAnimFunc(ANIM_FUNCTION animFunc) { switch (animFunc) { default: case ANIM_CONSTANT: this->animFunc = &tAnim::constant; break; case ANIM_LINEAR: this->animFunc = &tAnim::linear; break; case ANIM_SINE: this->animFunc = &tAnim::sine; break; case ANIM_COSINE: this->animFunc = &tAnim::cosine; break; case ANIM_EXP: this->animFunc = &tAnim::exp; break; case ANIM_NEG_EXP: this->animFunc = &tAnim::negExp; break; case ANIM_QUADRATIC: this->animFunc = &tAnim::quadratic; break; case ANIM_RANDOM: this->animFunc = &tAnim::random; break; } } // animation functions template float tAnim::random(float timePassed) const { return (float)rand()/(float)RAND_MAX; } template float tAnim::constant(float timePassed) const { return this->currentKeyFrame->value; } template float tAnim::linear(float timePassed) const { return this->nextKeyFrame->value - (this->nextKeyFrame->value - this->currentKeyFrame->value) * (timePassed / this->currentKeyFrame->duration); // PRINTF(0)("value is %f, %p %p\n", val, this->currentKeyFrame, this->nextKeyFrame); // return val; } template float tAnim::sine(float timePassed) const { return this->currentKeyFrame->value - (this->nextKeyFrame->value - this->currentKeyFrame->value) * sin(timePassed / this->currentKeyFrame->duration * M_PI); } template float tAnim::cosine(float timePassed) const { return this->currentKeyFrame->value - (this->nextKeyFrame->value - this->currentKeyFrame->value) * cos(timePassed / this->currentKeyFrame->duration * M_PI); } template float tAnim::exp(float timePassed) const { } template float tAnim::negExp(float timePassed) const { } template float tAnim::quadratic(float timePassed) const { } #endif /* _ANIMATION_H */