Browse Source

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

Darryl Gough 14 years ago
parent
commit
23bc784506
3 changed files with 231 additions and 144 deletions
  1. 99 48
      gameplay/src/AnimationClip.cpp
  2. 60 27
      gameplay/src/AnimationClip.h
  3. 72 69
      gameplay/src/AudioController.cpp

+ 99 - 48
gameplay/src/AnimationClip.cpp

@@ -10,9 +10,9 @@ 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), _runningTime(0), 
-      _crossFadeToClip(NULL), _crossFadeStart(0), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f), 
-      _isFadingOutStarted(false), _isFadingOut(false), _isFadingIn(false), _beginListeners(NULL), _endListeners(NULL)
+      _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)
 {
     assert(0 <= startTime && startTime <= animation->_duration && 0 <= endTime && endTime <= animation->_duration);
     
@@ -36,6 +36,7 @@ AnimationClip::~AnimationClip()
     SAFE_RELEASE(_crossFadeToClip);
     SAFE_DELETE(_beginListeners);
     SAFE_DELETE(_endListeners);
+    SAFE_DELETE(_listeners);
 }
 
 const char* AnimationClip::getID() const
@@ -151,37 +152,71 @@ void AnimationClip::crossFade(AnimationClip* clip, unsigned long duration)
 {
     assert(clip);
 
-    if (clip->_isPlaying && clip->_isFadingOut)
-    {
-        clip->_isFadingOut = false;
-        clip->_crossFadeToClip->_isFadingIn = false;
-        SAFE_RELEASE(clip->_crossFadeToClip);
-    }
-
-    // If I already have a clip I'm fading too.. release it.
+    // 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)
         SAFE_RELEASE(_crossFadeToClip);
-
-    // Assign the clip we're fading to, and increase its ref count.
+        
     _crossFadeToClip = clip;
     _crossFadeToClip->addRef();
         
-    // Set the fade in clip to fading in, and set the duration of the fade in.
+    // Set the crossfade clip to fading in, and initialize it's blend weight to zero.
     _crossFadeToClip->_isFadingIn = true;
+    _crossFadeToClip->_blendWeight = 0.0f;
     
-    // Set this clip to fade out, and reset the elapsed time for the fade out.
+    // Set this clip to fade out, set the fade duration and reset the fade elapsed time.
     _isFadingOut = true;
     _crossFadeOutElapsed = 0;
     _crossFadeOutDuration = duration;
-    _crossFadeStart = (Game::getGameTime() - _timeStarted);
     _isFadingOutStarted = true;
     
+    // If this clip is currently not playing, we should start playing it.
     if (!_isPlaying)
         play();
 
+    // Start playing the cross fade clip.
     _crossFadeToClip->play(); 
 }
 
+void AnimationClip::addListener(AnimationClip::Listener* listener, unsigned long eventTime)
+{
+    assert(listener);
+    assert(eventTime < _duration);
+
+    listener->_listenerTime = eventTime;
+
+    if (!_listeners)
+    {
+        _listeners = new ListenerList;
+        _listeners->_list.push_front(listener);
+        if (_isPlaying)
+            _listeners->_listItr = _listeners->_list.begin();
+    }
+    else
+    {
+        for (std::list<Listener*>::iterator itr = _listeners->_list.begin(); itr != _listeners->_list.begin(); itr++)
+        {
+            if (eventTime < (*itr)->_listenerTime)
+            {
+                itr = _listeners->_list.insert(itr, listener);
+
+                // If playing, update the iterator if we need to.
+                // otherwise, it will just be set the next time the clip gets played.
+                if (_isPlaying)
+                {
+                    unsigned long currentTime = _elapsedTime % _duration;
+                    if ((_speed >= 0.0f && currentTime < eventTime && eventTime < (*_listeners->_listItr)->_listenerTime) || 
+                        (_speed <= 0 && currentTime > eventTime && eventTime > (*_listeners->_listItr)->_listenerTime))
+                        _listeners->_listItr = itr;
+                }
+
+                return;
+            }
+        }
+    }
+}
+
 void AnimationClip::addBeginListener(AnimationClip::Listener* listener)
 {
     if (!_beginListeners)
@@ -200,83 +235,92 @@ void AnimationClip::addEndListener(AnimationClip::Listener* listener)
 
 bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
 {
-    float speed = _speed;
     if (!_isPlaying)
-    {
         onBegin();
-        _elapsedTime = Game::getGameTime() - _timeStarted;
-        _runningTime = _elapsedTime * speed;
-    }
-    else
-    {
-        // Update elapsed time.
-        _elapsedTime += elapsedTime;
-        _runningTime += elapsedTime * speed;
-    }
-
-    float percentComplete = 0.0f;
+    else 
+        _elapsedTime += elapsedTime * _speed;
 
+    unsigned long currentTime = 0L;
     // Check to see if clip is complete.
-    if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0 && _runningTime >= (long) _activeDuration) || (_speed < 0 && _runningTime <= 0)))
+    if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0.0f && _elapsedTime >= (long) _activeDuration) || (_speed <= 0.0f && _elapsedTime <= 0L)))
     {
         _isPlaying = false;
-        if (_speed >= 0)
+        if (_speed >= 0.0f)
         {
-            percentComplete = _activeDuration % _duration; // Get's the fractional part of the final repeat.
-            if (percentComplete == 0.0f)
-                percentComplete = _duration;
+            currentTime = _activeDuration % _duration; // Get's the fractional part of the final repeat.
+            if (currentTime == 0L)
+                currentTime = _duration;
         }
         else
         {
-            percentComplete = 0.0f; // If we are negative speed, the end value should be 0.
+            currentTime = 0L; // If we are negative speed, the end value should be 0.
         }
     }
     else
     {
         // Gets portion/fraction of the repeat.
-        percentComplete = (float) (_runningTime % _duration);
+        currentTime = _elapsedTime % _duration;
+    }
+
+    // Notify any listeners of Animation events.
+    if (_listeners)
+    {
+        while (_listeners->_listItr != _listeners->_list.end() && (_speed >= 0.0f && currentTime % _duration >= (*_listeners->_listItr)->_listenerTime) || 
+                                                     (_speed <= 0.0f && currentTime % _duration <= (*_listeners->_listItr)->_listenerTime))
+        {
+            
+            (*_listeners->_listItr)->animationEvent(this, Listener::DEFAULT);
+            (_listeners->_listItr)++;
+        }
     }
 
     // Add back in start time, and divide by the total animation's duration to get the actual percentage complete
-    percentComplete = (float)(_startTime + percentComplete) / (float) _animation->_duration;
+    float percentComplete = (float)(_startTime + currentTime) / (float) _animation->_duration;
     
     if (_isFadingOut)
     {
         if (_isFadingOutStarted) // Calculate elapsed time since the fade out begin.
         {
-            _crossFadeOutElapsed = (_elapsedTime - _crossFadeStart) * speed;
+            _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * _speed; 
             _isFadingOutStarted = false;
         }
         else
         {
             // continue tracking elapsed time.
-            _crossFadeOutElapsed += elapsedTime * speed;
+            _crossFadeOutElapsed += elapsedTime * abs(_speed);
         }
 
         if (_crossFadeOutElapsed < _crossFadeOutDuration)
         {
+            // Calculate this clip's blend weight.
             float tempBlendWeight = (float) (_crossFadeOutDuration - _crossFadeOutElapsed) / (float) _crossFadeOutDuration;
-            _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight);
             
-            // adjust the clip your blending to's weight to be a percentage of your current blend weight
+            // If this clip is fading in, adjust the crossfade clip's weight to be a percentage of your current blend weight
             if (_isFadingIn)
             {
-                _crossFadeToClip->_blendWeight *= _blendWeight;
+                _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight) * _blendWeight;
                 _blendWeight -= _crossFadeToClip->_blendWeight;
             }
             else
             {
+                // Just set the blend weight.
+                _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight);
                 _blendWeight = tempBlendWeight;
             }
         }
         else
-        {   // Fade done.
+        {   // Fade is done.
+            // Set the crossFadeToClip's blend weight to 1
             _crossFadeToClip->_blendWeight = 1.0f;
-                
+            
+            // Adjust the crossfade clip's blend weight if this clip is also fading in.
             if (_isFadingIn)
                 _crossFadeToClip->_blendWeight *= _blendWeight;
 
+            // The crossfade clip is no longer fading in
             _crossFadeToClip->_isFadingIn = false;
+
+            // Release the crossfade clip, mark ourselves as done and set our blend weight to 0.
             SAFE_RELEASE(_crossFadeToClip);
             _blendWeight = 0.0f; 
             _isFadingOut = false;
@@ -330,17 +374,24 @@ void AnimationClip::onBegin()
 {
     // Initialize animation to play.
     _isPlaying = true;
-    _elapsedTime = 0;
 
-    if (_speed > 0)
+    if (_speed >= 0)
     {
-        _runningTime = 0;
+        _elapsedTime = 0;
+
+        if (_listeners)
+            _listeners->_listItr = _listeners->_list.begin();
     }
     else
     {
-        _runningTime = _activeDuration;
+        _elapsedTime = _activeDuration;
+
+        if (_listeners)
+            _listeners->_listItr = _listeners->_list.end();
     }
 
+    _elapsedTime += (Game::getGameTime() - _timeStarted) * _speed;
+
     // Notify begin listeners.. if any.
     if (_beginListeners)
     {

+ 60 - 27
gameplay/src/AnimationClip.h

@@ -32,13 +32,25 @@ public:
      */
     class Listener
     {
+        friend AnimationClip;
+
     public:
 
+        Listener() 
+            : _listenerTime(0L)
+        {
+        }
+
         /**
          * The type of animation event.
          */
         enum EventType 
         {
+            /**
+             * Default event type.
+             */
+            DEFAULT,
+
             /**
              * Event fired when the clip begins.
              */
@@ -54,6 +66,9 @@ public:
          * Handles when animation event occurs.
          */
         virtual void animationEvent(AnimationClip* clip, EventType type) = 0;
+
+    private:
+        unsigned long _listenerTime;
     };
 
     /**
@@ -177,19 +192,30 @@ public:
     void crossFade(AnimationClip* clip, unsigned long duration);
 
     /**
-     * Adds a animation begin listener.
+     * Adds an animation begin listener.
      *
-     * @param listener The listener to be called when an animation clip begins.
+     * @param listener The listener to be called when an AnimationClip begins.
      */
     void addBeginListener(AnimationClip::Listener* listener);
 
     /**
-     * Adds a animation end listener.
+     * Adds an animation end listener.
      *
-     * @param listener The listener to be called when an animation clip ends.
+     * @param listener The listener to be called when an AnimationClip ends.
      */
     void addEndListener(AnimationClip::Listener* listener);
 
+    /**
+     * Adds an animation listener to be called back at the specified eventTime during the playback 
+     * of the AnimationClip.
+     *
+     * @param listener The listener to be called when the AnimationClip reaches the 
+     *      specified time in its playback.
+     * @param eventTime The time the listener will be called during the playback of the AnimationClip. 
+     *      Must be between 0 and the duration of the AnimationClip.
+     */
+    void addListener(AnimationClip::Listener* listener, unsigned long eventTime);
+
 private:
 
     /**
@@ -227,30 +253,37 @@ private:
      */
     void onEnd();
 
-    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.
-    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.
-    unsigned long _elapsedTime;               // Time elapsed while the clip is running.
-    long _runningTime;                        // Keeps track of the Animation's relative time in respect to the active duration.
-    AnimationClip* _crossFadeToClip;          // The clip to cross fade to
-    unsigned long _crossFadeStart;            // The time at which the cross fade started.
-    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
+    /**
+     * A list that keeps a pointer to the next listener event to be triggered.
+     */
+    struct ListenerList
+    {
+        std::list<Listener*> _list;
+        std::list<Listener*>::iterator _listItr;
+    };
 
+    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.
+    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.
+    ListenerList* _listeners;                       // Collection of listeners on the clip.
 };
 
 }

+ 72 - 69
gameplay/src/AudioController.cpp

@@ -56,49 +56,49 @@ void AudioController::initialize()
 #else
     // Create the engine.
     SLresult result = slCreateEngine(&_engineObject, 0, NULL, 0, NULL, NULL);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL engine.");
-        return;
-    }
-
-    // Realize the engine.
-    result = (*_engineObject)->Realize(_engineObject, SL_BOOLEAN_FALSE);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL engine.");
-        return;
-    }
-
-    // Get the engine interface in order to create other objects later on.
-    result = (*_engineObject)->GetInterface(_engineObject, SL_IID_ENGINE, &_engineEngine);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to retrieve OpenSL engine interface.");
-        return;
-    }
-
-    // Create the output mix.
-    result = (*_engineEngine)->CreateOutputMix(_engineEngine, &_outputMixObject, 0, NULL, NULL);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL output mix.");
-        return;
-    }
-
-    // Realize the output mix.
-    result = (*_outputMixObject)->Realize(_outputMixObject, SL_BOOLEAN_FALSE);
-    if (result != SL_RESULT_SUCCESS)
-    {
-        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL output mix.");
-        return;
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL engine.");
+        return;
+    }
+
+    // Realize the engine.
+    result = (*_engineObject)->Realize(_engineObject, SL_BOOLEAN_FALSE);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL engine.");
+        return;
+    }
+
+    // Get the engine interface in order to create other objects later on.
+    result = (*_engineObject)->GetInterface(_engineObject, SL_IID_ENGINE, &_engineEngine);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to retrieve OpenSL engine interface.");
+        return;
+    }
+
+    // Create the output mix.
+    result = (*_engineEngine)->CreateOutputMix(_engineEngine, &_outputMixObject, 0, NULL, NULL);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL output mix.");
+        return;
+    }
+
+    // Realize the output mix.
+    result = (*_outputMixObject)->Realize(_outputMixObject, SL_BOOLEAN_FALSE);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL output mix.");
+        return;
     }
 #endif
 }
 
 void AudioController::finalize()
 {
-#ifndef __ANDROID__
+#ifndef __ANDROID__
     alcMakeContextCurrent(NULL);
     if (_alcContext)
     {
@@ -111,17 +111,17 @@ void AudioController::finalize()
         _alcDevice = NULL;
     }
 #else
-    if (_outputMixObject != NULL)
-    {
-        (*_outputMixObject)->Destroy(_outputMixObject);
-        _outputMixObject = NULL;
-    }
-
-    if (_engineObject != NULL)
-    {
-        (*_engineObject)->Destroy(_engineObject);
-        _engineObject = NULL;
-        _engineEngine = NULL;
+    if (_outputMixObject != NULL)
+    {
+        (*_outputMixObject)->Destroy(_outputMixObject);
+        _outputMixObject = NULL;
+    }
+
+    if (_engineObject != NULL)
+    {
+        (*_engineObject)->Destroy(_engineObject);
+        _engineObject = NULL;
+        _engineEngine = NULL;
     }
 #endif
 }
@@ -145,6 +145,9 @@ void AudioController::pause()
 
 void AudioController::resume()
 {
+#ifndef __ANDROID__    
+    alcMakeContextCurrent(_alcContext);
+#endif
     std::list<AudioSource*>::iterator itr = _playingSources.begin();
 
     // For each source that is playing, resume it.
@@ -173,7 +176,7 @@ void AudioController::update(long elapsedTime)
 #else
         if (!_listenerObject)
         {
-            const SLInterfaceID interfaces[3] = {SL_IID_3DDOPPLER, SL_IID_3DLOCATION};
+            const SLInterfaceID interfaces[3] = {SL_IID_3DDOPPLER, SL_IID_3DLOCATION};
             const SLboolean required[3] = {SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE};
             SLresult result = (*_engineEngine)->CreateListener(_engineEngine, &_listenerObject, 2, interfaces, required);
             if (result != SL_RESULT_SUCCESS)
@@ -189,20 +192,20 @@ void AudioController::update(long elapsedTime)
                 return;
             }
 
-            // Get the doppler interface in order to set the listener's velocity.
-            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DDOPPLER, &_listenerDoppler);
-            if (result != SL_RESULT_SUCCESS)
-            {
-                WARN("AudioController: Unable to retrieve listener doppler interface.");
-                return;
+            // Get the doppler interface in order to set the listener's velocity.
+            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DDOPPLER, &_listenerDoppler);
+            if (result != SL_RESULT_SUCCESS)
+            {
+                WARN("AudioController: Unable to retrieve listener doppler interface.");
+                return;
             }
 
             // Get the location interface in order to set the listener's position and orientation.
-            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DLOCATION, &_listenerLocation);
-            if (result != SL_RESULT_SUCCESS)
-            {
-                WARN("AudioController: Unable to retrieve listener location interface.");
-                return;
+            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DLOCATION, &_listenerLocation);
+            if (result != SL_RESULT_SUCCESS)
+            {
+                WARN("AudioController: Unable to retrieve listener location interface.");
+                return;
             }
         }
         
@@ -215,9 +218,9 @@ void AudioController::update(long elapsedTime)
         a.y = listener->getOrientationUp().y;
         a.z = listener->getOrientationUp().z;
         SLresult result = (*_listenerLocation)->SetOrientationVectors(_listenerLocation, &f, &a);
-        if (result != SL_RESULT_SUCCESS)
-        {
-            WARN("AudioController: Unable to set listener orientation.");
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener orientation.");
         }
 
         SLVec3D p;
@@ -225,9 +228,9 @@ void AudioController::update(long elapsedTime)
         p.y = listener->getPosition().y;
         p.z = listener->getPosition().z;
         result = (*_listenerLocation)->SetLocationCartesian(_listenerLocation, &p);
-        if (result != SL_RESULT_SUCCESS)
-        {
-            WARN("AudioController: Unable to set listener location.");
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener location.");
         }
 
         SLVec3D v;
@@ -235,9 +238,9 @@ void AudioController::update(long elapsedTime)
         v.y = listener->getVelocity().y;
         v.z = listener->getVelocity().z;
         result = (*_listenerDoppler)->SetVelocityCartesian(_listenerDoppler, &v);
-        if (result != SL_RESULT_SUCCESS)
-        {
-            WARN("AudioController: Unable to set listener velocity.");
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener velocity.");
         }
 #endif
     }