Kaynağa Gözat

Merge remote-tracking branch 'upstream/next' into next

Brandon Slack 14 yıl önce
ebeveyn
işleme
f509d2bd44

+ 72 - 40
gameplay/src/AnimationClip.cpp

@@ -9,10 +9,10 @@ namespace gameplay
 {
 
 AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long startTime, unsigned long endTime)
-    : _id(id), _animation(animation), _startTime(startTime), _endTime(endTime), _duration(_endTime - _startTime), _repeatCount(1.0f), 
-      _activeDuration(_duration * _repeatCount), _speed(1.0f), _isPlaying(false), _timeStarted(0), _elapsedTime(0), 
-      _crossFadeToClip(NULL), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f), _isFadingOutStarted(false), 
-      _isFadingOut(false), _isFadingIn(false), _beginListeners(NULL), _endListeners(NULL), _listeners(NULL), _listenerItr(NULL)
+    : _id(id), _animation(animation), _startTime(startTime), _endTime(endTime), _duration(_endTime - _startTime), 
+      _stateBits(0x00), _repeatCount(1.0f), _activeDuration(_duration * _repeatCount), _speed(1.0f), _timeStarted(0), 
+      _elapsedTime(0), _crossFadeToClip(NULL), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f), 
+      _beginListeners(NULL), _endListeners(NULL), _listeners(NULL), _listenerItr(NULL)
 {
     assert(0 <= startTime && startTime <= animation->_duration && 0 <= endTime && endTime <= animation->_duration);
     
@@ -130,21 +130,30 @@ float AnimationClip::getBlendWeight() const
 
 bool AnimationClip::isPlaying() const
 {
-    return _isPlaying;
+    return isClipStateBitSet(CLIP_IS_PLAYING_BIT);
 }
 
 void AnimationClip::play()
 {
+    if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
+    {
+        _animation->_controller->unschedule(this);
+        resetClipStateBit(CLIP_IS_STARTED_BIT);
+        onEnd();
+    }
+    else
+        setClipStateBit(CLIP_IS_PLAYING_BIT);
+    
     _animation->_controller->schedule(this);
     _timeStarted = Game::getGameTime();
 }
 
 void AnimationClip::stop()
 {
-    _animation->_controller->unschedule(this);
-    if (_isPlaying)
+    if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
     {
-        _isPlaying = false;
+        _animation->_controller->unschedule(this);
+        resetClipStateBit(CLIP_IS_PLAYING_BIT | CLIP_IS_STARTED_BIT);
         onEnd();
     }
 }
@@ -155,25 +164,28 @@ void AnimationClip::crossFade(AnimationClip* clip, unsigned long duration)
 
     // If I already have a clip I'm fading to and it's not the same as the given clip release it.
     // Assign the new clip and increase it's ref count.
-    // TODO: Do I need to anything else to the crossFade clip here before releasing?
     if (_crossFadeToClip)
+    {
+        _crossFadeToClip->stop();
+        _crossFadeToClip->resetClipStateBit(CLIP_IS_FADING_IN_BIT);
         SAFE_RELEASE(_crossFadeToClip);
+    }
         
     _crossFadeToClip = clip;
     _crossFadeToClip->addRef();
         
     // Set the crossfade clip to fading in, and initialize it's blend weight to zero.
-    _crossFadeToClip->_isFadingIn = true;
+    _crossFadeToClip->setClipStateBit(CLIP_IS_FADING_IN_BIT);
     _crossFadeToClip->_blendWeight = 0.0f;
     
     // Set this clip to fade out, set the fade duration and reset the fade elapsed time.
-    _isFadingOut = true;
+    setClipStateBit(CLIP_IS_FADING_OUT_STARTED_BIT);
+    setClipStateBit(CLIP_IS_FADING_OUT_BIT);
     _crossFadeOutElapsed = 0;
     _crossFadeOutDuration = duration;
-    _isFadingOutStarted = true;
     
     // If this clip is currently not playing, we should start playing it.
-    if (!_isPlaying)
+    if (!isClipStateBitSet(CLIP_IS_PLAYING_BIT))
         play();
 
     // Start playing the cross fade clip.
@@ -193,7 +205,7 @@ void AnimationClip::addListener(AnimationClip::Listener* listener, unsigned long
         _listeners->push_front(listener);
 
         _listenerItr = new std::list<Listener*>::iterator;
-        if (_isPlaying)
+        if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
             *_listenerItr = _listeners->begin();
     }
     else
@@ -206,7 +218,7 @@ void AnimationClip::addListener(AnimationClip::Listener* listener, unsigned long
 
                 // If playing, update the iterator if we need to.
                 // otherwise, it will just be set the next time the clip gets played.
-                if (_isPlaying)
+                if (isClipStateBitSet(CLIP_IS_PLAYING_BIT))
                 {
                     unsigned long currentTime = _elapsedTime % _duration;
                     if ((_speed >= 0.0f && currentTime < eventTime && (*_listenerItr == _listeners->end() || eventTime < (**_listenerItr)->_listenerTime)) || 
@@ -237,16 +249,21 @@ void AnimationClip::addEndListener(AnimationClip::Listener* listener)
 
 bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
 {
-    if (!_isPlaying)
+    if (!isClipStateBitSet(CLIP_IS_STARTED_BIT))
         onBegin();
-    else 
+    else
+    {
         _elapsedTime += elapsedTime * _speed;
 
+        if (_repeatCount == REPEAT_INDEFINITE && _elapsedTime <= 0)
+            _elapsedTime = _activeDuration + _elapsedTime;
+    }
+
     unsigned long currentTime = 0L;
     // Check to see if clip is complete.
     if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0.0f && _elapsedTime >= (long) _activeDuration) || (_speed <= 0.0f && _elapsedTime <= 0L)))
     {
-        _isPlaying = false;
+        resetClipStateBit(CLIP_IS_STARTED_BIT);
         if (_speed >= 0.0f)
         {
             currentTime = _activeDuration % _duration; // Get's the fractional part of the final repeat.
@@ -288,12 +305,12 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
     // Add back in start time, and divide by the total animation's duration to get the actual percentage complete
     float percentComplete = (float)(_startTime + currentTime) / (float) _animation->_duration;
     
-    if (_isFadingOut)
+    if (isClipStateBitSet(CLIP_IS_FADING_OUT_BIT))
     {
-        if (_isFadingOutStarted) // Calculate elapsed time since the fade out begin.
+        if (isClipStateBitSet(CLIP_IS_FADING_OUT_STARTED_BIT)) // Calculate elapsed time since the fade out begin.
         {
-            _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * _speed; 
-            _isFadingOutStarted = false;
+            _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * abs(_speed); 
+            resetClipStateBit(CLIP_IS_FADING_OUT_STARTED_BIT);
         }
         else
         {
@@ -307,7 +324,7 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
             float tempBlendWeight = (float) (_crossFadeOutDuration - _crossFadeOutElapsed) / (float) _crossFadeOutDuration;
             
             // If this clip is fading in, adjust the crossfade clip's weight to be a percentage of your current blend weight
-            if (_isFadingIn)
+            if (isClipStateBitSet(CLIP_IS_FADING_IN_BIT))
             {
                 _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight) * _blendWeight;
                 _blendWeight -= _crossFadeToClip->_blendWeight;
@@ -321,21 +338,21 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
         }
         else
         {   // Fade is done.
-            // Set the crossFadeToClip's blend weight to 1
+            // Set blendweights
             _crossFadeToClip->_blendWeight = 1.0f;
-            
+
             // Adjust the crossfade clip's blend weight if this clip is also fading in.
-            if (_isFadingIn)
+            if (isClipStateBitSet(CLIP_IS_FADING_IN_BIT))
                 _crossFadeToClip->_blendWeight *= _blendWeight;
 
-            // The crossfade clip is no longer fading in
-            _crossFadeToClip->_isFadingIn = false;
+            _blendWeight = 0.0f; 
+
+            // reset the states of our clips to turn off the cross fade.
+            _crossFadeToClip->resetClipStateBit(CLIP_IS_FADING_IN_BIT);
+            resetClipStateBit(CLIP_IS_FADING_OUT_BIT | CLIP_IS_STARTED_BIT);
 
             // Release the crossfade clip, mark ourselves as done and set our blend weight to 0.
             SAFE_RELEASE(_crossFadeToClip);
-            _blendWeight = 0.0f; 
-            _isFadingOut = false;
-            _isPlaying = false;
         }
     }
     
@@ -363,7 +380,7 @@ 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 (!_isPlaying)
+    if (!isClipStateBitSet(CLIP_IS_STARTED_BIT))
     {
         onEnd();
         // Notify end listeners if any.
@@ -376,33 +393,32 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
                 listener++;
             }
         }
+
+        return true;
     }
 
-    return !_isPlaying;
+    return false;
 }
 
 void AnimationClip::onBegin()
 {
     // Initialize animation to play.
-    _isPlaying = true;
-
+    setClipStateBit(CLIP_IS_STARTED_BIT);
     if (_speed >= 0)
     {
-        _elapsedTime = 0;
+        _elapsedTime = (Game::getGameTime() - _timeStarted) * _speed;
 
         if (_listeners)
             *_listenerItr = _listeners->begin(); 
     }
     else
     {
-        _elapsedTime = _activeDuration;
+        _elapsedTime = _activeDuration + (Game::getGameTime() - _timeStarted) * _speed;
 
         if (_listeners)
             *_listenerItr = _listeners->end();
     }
-
-    _elapsedTime += (Game::getGameTime() - _timeStarted) * _speed;
-
+    
     // Notify begin listeners.. if any.
     if (_beginListeners)
     {
@@ -419,6 +435,22 @@ void AnimationClip::onEnd()
 {
     _blendWeight = 1.0f;
     _timeStarted = 0;
+    resetClipStateBit(CLIP_IS_PLAYING_BIT);
+}
+
+bool AnimationClip::isClipStateBitSet(char bit) const
+{
+    return (_stateBits & bit) == bit;
+}
+
+void AnimationClip::setClipStateBit(char bit)
+{
+    _stateBits |= bit;
+}
+
+void AnimationClip::resetClipStateBit(char bit)
+{
+    _stateBits &= ~bit;
 }
 
 }

+ 21 - 5
gameplay/src/AnimationClip.h

@@ -217,6 +217,11 @@ public:
     void addListener(AnimationClip::Listener* listener, unsigned long eventTime);
 
 private:
+    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.
 
     /**
      * Constructor.
@@ -253,24 +258,36 @@ private:
      */
     void onEnd();
 
+    /**
+     * Determines whether the given bit is set in the AnimationClip's state.
+     */
+    bool isClipStateBitSet(char bit) const;
+
+    /**
+     * Sets the given bit in the AnimationClip's state.
+     */
+    void setClipStateBit(char bit);
+
+    /**
+     * Resets the given bit in the AnimationClip's state.
+     */
+    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.
-    bool _isPlaying;                                // A flag to indicate whether the clip is playing.
     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.
-    bool _isFadingOutStarted;                       // Flag to indicate if the cross fade started.
-    bool _isFadingOut;                              // Flag to indicate if the clip is fading out.
-    bool _isFadingIn;                               // Flag to indicate if the clip is fading in.
     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.
@@ -279,5 +296,4 @@ private:
 };
 
 }
-
 #endif

+ 2 - 14
gameplay/src/AnimationController.cpp

@@ -111,10 +111,8 @@ void AnimationController::stopAllAnimations()
     while (clipIter != _runningClips.end())
     {
         AnimationClip* clip = *clipIter;
-        clip->_isPlaying = false;
-        clip->onEnd();
-        SAFE_RELEASE(clip);
         clipIter++;
+        clip->stop();
     }
     _runningClips.clear();
 
@@ -294,18 +292,8 @@ void AnimationController::schedule(AnimationClip* clip)
     {
         _state = RUNNING;
     }
-    
-    if (clip->_isPlaying)
-    {
-        _runningClips.remove(clip);
-        clip->_isPlaying = false;
-        clip->onEnd();
-    }
-    else
-    {
-        clip->addRef();
-    }
 
+    clip->addRef();
     _runningClips.push_back(clip);
 }