Просмотр исходного кода

Merge branch 'next' of https://github.com/blackberry-gaming/GamePlay into next-dgough

Darryl Gough 14 лет назад
Родитель
Сommit
00dee12ced

+ 4 - 2
gameplay/src/Animation.cpp

@@ -31,7 +31,8 @@ Animation::~Animation()
 {
     if (_defaultClip)
     {
-        _defaultClip->stop();
+        if (_defaultClip->isClipStateBitSet(AnimationClip::CLIP_IS_PLAYING_BIT))
+            _controller->unschedule(_defaultClip);
         SAFE_RELEASE(_defaultClip);
     }
 
@@ -42,7 +43,8 @@ Animation::~Animation()
         while (clipIter != _clips->end())
         {   
             AnimationClip* clip = *clipIter;
-            clip->stop();
+            if (clip->isClipStateBitSet(AnimationClip::CLIP_IS_PLAYING_BIT))
+                _controller->unschedule(clip);
             SAFE_RELEASE(clip);
             clipIter++;
         }

+ 81 - 36
gameplay/src/AnimationClip.cpp

@@ -36,10 +36,31 @@ AnimationClip::~AnimationClip()
     SAFE_RELEASE(_crossFadeToClip);
     SAFE_DELETE(_beginListeners);
     SAFE_DELETE(_endListeners);
-    SAFE_DELETE(_listeners);
+
+    if (_listeners)
+    {
+        *_listenerItr = _listeners->begin();
+        while (*_listenerItr != _listeners->end())
+        {
+            ListenerEvent* lEvt = **_listenerItr;
+            SAFE_DELETE(lEvt);
+            ++*_listenerItr;
+        }
+        SAFE_DELETE(_listeners);
+    }
     SAFE_DELETE(_listenerItr);
 }
 
+AnimationClip::ListenerEvent::ListenerEvent(Listener* listener, unsigned long eventTime)
+{
+    _listener = listener;
+    _eventTime = eventTime;
+}
+
+AnimationClip::ListenerEvent::~ListenerEvent()
+{
+}
+
 const char* AnimationClip::getID() const
 {
     return _id.c_str();
@@ -108,6 +129,11 @@ unsigned long AnimationClip::getActiveDuration() const
     return _activeDuration;
 }
 
+unsigned long AnimationClip::getDuration() const
+{
+    return _duration;
+}
+
 void AnimationClip::setSpeed(float speed)
 {
     _speed = speed;
@@ -137,13 +163,19 @@ void AnimationClip::play()
 {
     if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
     {
-        onEnd();
-        _animation->_controller->unschedule(this);
+        // If the clip is set to be removed, reset the flag.
+        if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT))
+            resetClipStateBit(CLIP_IS_MARKED_FOR_REMOVAL_BIT);
+
+        // Set the state bit to restart.
+        setClipStateBit(CLIP_IS_RESTARTED_BIT);
+    }
+    else
+    {
+        setClipStateBit(CLIP_IS_PLAYING_BIT);
+        _animation->_controller->schedule(this);
     }
     
-    setClipStateBit(CLIP_IS_PLAYING_BIT);
-    
-    _animation->_controller->schedule(this);
     _timeStarted = Game::getGameTime();
 }
 
@@ -151,8 +183,12 @@ void AnimationClip::stop()
 {
     if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
     {
-        onEnd();
-        _animation->_controller->unschedule(this);
+        // If the clip was slated to be restarted, reset this flag.
+        if (isClipStateBitSet(CLIP_IS_RESTARTED_BIT))
+            resetClipStateBit(CLIP_IS_RESTARTED_BIT);
+
+        // Mark the clip to removed from the AnimationController.
+        setClipStateBit(CLIP_IS_MARKED_FOR_REMOVAL_BIT);
     }
 }
 
@@ -200,39 +236,40 @@ void AnimationClip::crossFade(AnimationClip* clip, unsigned long duration)
 void AnimationClip::addListener(AnimationClip::Listener* listener, unsigned long eventTime)
 {
     assert(listener);
-    assert(eventTime < _duration);
+    assert(eventTime < _activeDuration);
 
-    listener->_listenerTime = eventTime;
+    ListenerEvent* listenerEvent = new ListenerEvent(listener, eventTime);
 
     if (!_listeners)
     {
-        _listeners = new std::list<Listener*>;
-        _listeners->push_front(listener);
+        _listeners = new std::list<ListenerEvent*>;
+        _listeners->push_front(listenerEvent);
 
-        _listenerItr = new std::list<Listener*>::iterator;
+        _listenerItr = new std::list<ListenerEvent*>::iterator;
         if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
             *_listenerItr = _listeners->begin();
     }
     else
     {
-        for (std::list<Listener*>::iterator itr = _listeners->begin(); itr != _listeners->begin(); itr++)
+        for (std::list<ListenerEvent*>::iterator itr = _listeners->begin(); itr != _listeners->end(); itr++)
         {
-            if (eventTime < (*itr)->_listenerTime)
+            if (eventTime < (*itr)->_eventTime)
             {
-                itr = _listeners->insert(itr, listener);
+                itr = _listeners->insert(itr, listenerEvent);
 
                 // If playing, update the iterator if we need to.
                 // otherwise, it will just be set the next time the clip gets played.
                 if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
                 {
                     unsigned long currentTime = _elapsedTime % _duration;
-                    if ((_speed >= 0.0f && currentTime < eventTime && (*_listenerItr == _listeners->end() || eventTime < (**_listenerItr)->_listenerTime)) || 
-                        (_speed <= 0 && currentTime > eventTime && (*_listenerItr == _listeners->begin() || eventTime > (**_listenerItr)->_listenerTime)))
+                    if ((_speed >= 0.0f && currentTime < eventTime && (*_listenerItr == _listeners->end() || eventTime < (**_listenerItr)->_eventTime)) || 
+                        (_speed <= 0 && currentTime > eventTime && (*_listenerItr == _listeners->begin() || eventTime > (**_listenerItr)->_eventTime)))
                         *_listenerItr = itr;
                 }
                 return;
             }
         }
+        _listeners->push_back(listenerEvent);
     }
 }
 
@@ -254,8 +291,17 @@ void AnimationClip::addEndListener(AnimationClip::Listener* listener)
 
 bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
 {
-    if (!isClipStateBitSet(CLIP_IS_STARTED_BIT))
+    if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT))
+    {   // If the marked for removal bit is set, it means stop() was called on the AnimationClip at some point
+        // after the last update call. Reset the flag, and return true so the AnimationClip is removed from the 
+        // running clips on the AnimationController.
+        onEnd();
+        return true;
+    }
+    else if (!isClipStateBitSet(CLIP_IS_STARTED_BIT))
+    {
         onBegin();
+    }
     else
     {
         _elapsedTime += elapsedTime * _speed;
@@ -302,17 +348,17 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
     {
         if (_speed >= 0.0f)
         {
-            while (*_listenerItr != _listeners->end() && currentTime >= (**_listenerItr)->_listenerTime)
+            while (*_listenerItr != _listeners->end() && _elapsedTime >= (long) (**_listenerItr)->_eventTime)
             {
-                (**_listenerItr)->animationEvent(this, Listener::DEFAULT);
+                (**_listenerItr)->_listener->animationEvent(this, Listener::DEFAULT);
                 ++*_listenerItr;
             }
         }
         else
         {
-            while (*_listenerItr != _listeners->begin() && currentTime <= (**_listenerItr)->_listenerTime)
+            while (*_listenerItr != _listeners->begin() && _elapsedTime <= (long) (**_listenerItr)->_eventTime)
             {
-                (**_listenerItr)->animationEvent(this, Listener::DEFAULT);
+                (**_listenerItr)->_listener->animationEvent(this, Listener::DEFAULT);
                 --*_listenerItr;
             }
         }
@@ -387,20 +433,9 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
     }
 
     // When ended. Probably should move to it's own method so we can call it when the clip is ended early.
-    if (!isClipStateBitSet(CLIP_IS_STARTED_BIT))
+    if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT) || !isClipStateBitSet(CLIP_IS_STARTED_BIT))
     {
         onEnd();
-        // Notify end listeners if any.
-        if (_endListeners)
-        {
-            std::vector<Listener*>::iterator listener = _endListeners->begin();
-            while (listener != _endListeners->end())
-            {
-                (*listener)->animationEvent(this, Listener::END);
-                listener++;
-            }
-        }
-
         return true;
     }
 
@@ -441,8 +476,18 @@ void AnimationClip::onBegin()
 void AnimationClip::onEnd()
 {
     _blendWeight = 1.0f;
-    _timeStarted = 0;
     resetClipStateBit(CLIP_ALL_BITS);
+
+    // Notify end listeners if any.
+    if (_endListeners)
+    {
+        std::vector<Listener*>::iterator listener = _endListeners->begin();
+        while (listener != _endListeners->end())
+        {
+            (*listener)->animationEvent(this, Listener::END);
+            listener++;
+        }
+    }
 }
 
 bool AnimationClip::isClipStateBitSet(char bit) const

+ 54 - 25
gameplay/src/AnimationClip.h

@@ -37,7 +37,6 @@ public:
     public:
 
         Listener() 
-            : _listenerTime(0L)
         {
         }
 
@@ -66,9 +65,6 @@ public:
          * Handles when animation event occurs.
          */
         virtual void animationEvent(AnimationClip* clip, EventType type) = 0;
-
-    private:
-        unsigned long _listenerTime;
     };
 
     /**
@@ -138,6 +134,13 @@ public:
      */
     unsigned long getActiveDuration() const;
 
+    /**
+     * Gets the AnimationClip's duration.
+     *
+     * @return the AnimationClip's duration.
+     */
+    unsigned long getDuration() const;
+
     /**
      * Set the AnimationClip's running speed. 
      *
@@ -217,12 +220,38 @@ public:
     void addListener(AnimationClip::Listener* listener, unsigned long eventTime);
 
 private:
+    /**
+     * State bits.
+     */
     static const char CLIP_IS_PLAYING_BIT = 0x01;             // Bit representing whether AnimationClip is a running clip in AnimationController
     static const char CLIP_IS_STARTED_BIT = 0x02;             // Bit representing whether the AnimationClip has actually been started (ie: received first call to update())
     static const char CLIP_IS_FADING_OUT_STARTED_BIT = 0x04;  // Bit representing that a cross fade has started.
     static const char CLIP_IS_FADING_OUT_BIT = 0x08;          // Bit representing whether the clip is fading out.
     static const char CLIP_IS_FADING_IN_BIT = 0x10;           // Bit representing whether the clip is fading out.
-    static const char CLIP_ALL_BITS = 0x1F;                   // Bit mask for all the state bits.
+    static const char CLIP_IS_MARKED_FOR_REMOVAL_BIT = 0x20;  // Bit representing whether the clip has ended and should be removed from the AnimationController.
+    static const char CLIP_IS_RESTARTED_BIT = 0x40;           // Bit representing if the clip should be restarted by the AnimationController.
+    static const char CLIP_ALL_BITS = 0x4F;                   // Bit mask for all the state bits.
+
+    /**
+     * ListenerEvent.
+     *
+     * Internal structure used for storing the event time at which an AnimationClip::Listener should be called back.
+     */
+    struct ListenerEvent
+    {
+        /** 
+         * Constructor.
+         */
+        ListenerEvent(Listener* listener, unsigned long eventTime);
+
+        /**
+         * Destructor.
+         */
+        ~ListenerEvent();
+
+        Listener* _listener;        // This listener to call back when this event is triggered.
+        unsigned long _eventTime;   // The time at which the listener will be called back at during the playback of the AnimationClip.
+    };
 
     /**
      * Constructor.
@@ -274,26 +303,26 @@ private:
      */
     void resetClipStateBit(char bit);
 
-    std::string _id;                                // AnimationClip ID.
-    Animation* _animation;                          // The Animation this clip is created from.
-    unsigned long _startTime;                       // Start time of the clip.
-    unsigned long _endTime;                         // End time of the clip.
-    unsigned long _duration;                        // The total duration.
-    char _stateBits;                                // Bit flag used to keep track of the clip's current state.
-    float _repeatCount;                             // The clip's repeat count.
-    unsigned long _activeDuration;                  // The active duration of the clip.
-    float _speed;                                   // The speed that the clip is playing. Default is 1.0. Negative goes in reverse.
-    unsigned long _timeStarted;                     // The game time when this clip was actually started.
-    long _elapsedTime;                              // Time elapsed while the clip is running.
-    AnimationClip* _crossFadeToClip;                // The clip to cross fade to.
-    unsigned long _crossFadeOutElapsed;             // The amount of time that has elapsed for the crossfade.
-    unsigned long _crossFadeOutDuration;            // The duration of the cross fade.
-    float _blendWeight;                             // The clip's blendweight.
-    std::vector<AnimationValue*> _values;           // AnimationValue holder.
-    std::vector<Listener*>* _beginListeners;        // Collection of begin listeners on the clip.
-    std::vector<Listener*>* _endListeners;          // Collection of end listeners on the clip.
-    std::list<Listener*>* _listeners;               // Ordered collection of listeners on the clip.
-    std::list<Listener*>::iterator* _listenerItr;   // Iterator that points to the next listener event to be triggered.
+    std::string _id;                                    // AnimationClip ID.
+    Animation* _animation;                              // The Animation this clip is created from.
+    unsigned long _startTime;                           // Start time of the clip.
+    unsigned long _endTime;                             // End time of the clip.
+    unsigned long _duration;                            // The total duration.
+    char _stateBits;                                    // Bit flag used to keep track of the clip's current state.
+    float _repeatCount;                                 // The clip's repeat count.
+    unsigned long _activeDuration;                      // The active duration of the clip.
+    float _speed;                                       // The speed that the clip is playing. Default is 1.0. Negative goes in reverse.
+    unsigned long _timeStarted;                         // The game time when this clip was actually started.
+    long _elapsedTime;                                  // Time elapsed while the clip is running.
+    AnimationClip* _crossFadeToClip;                    // The clip to cross fade to.
+    unsigned long _crossFadeOutElapsed;                 // The amount of time that has elapsed for the crossfade.
+    unsigned long _crossFadeOutDuration;                // The duration of the cross fade.
+    float _blendWeight;                                 // The clip's blendweight.
+    std::vector<AnimationValue*> _values;               // AnimationValue holder.
+    std::vector<Listener*>* _beginListeners;            // Collection of begin listeners on the clip.
+    std::vector<Listener*>* _endListeners;              // Collection of end listeners on the clip.
+    std::list<ListenerEvent*>* _listeners;              // Ordered collection of listeners on the clip.
+    std::list<ListenerEvent*>::iterator* _listenerItr;  // Iterator that points to the next listener event to be triggered.
 };
 
 }

+ 9 - 1
gameplay/src/AnimationController.cpp

@@ -326,7 +326,15 @@ void AnimationController::update(long elapsedTime)
     while (clipIter != _runningClips.end())
     {
         AnimationClip* clip = (*clipIter);
-        if (clip->update(elapsedTime, &_activeTargets))
+        if (clip->isClipStateBitSet(AnimationClip::CLIP_IS_RESTARTED_BIT))
+        {   // If the CLIP_IS_RESTARTED_BIT is set, we should end the clip and 
+            // move it from where it is in the running clips list to the back.
+            clip->onEnd();
+            clip->setClipStateBit(AnimationClip::CLIP_IS_PLAYING_BIT);
+            _runningClips.push_back(clip);
+            clipIter = _runningClips.erase(clipIter);
+        }
+        else if (clip->update(elapsedTime, &_activeTargets))
         {
             SAFE_RELEASE(clip);
             clipIter = _runningClips.erase(clipIter);