Browse Source

Fixes 47.

Fixes memory management in animation. Animations now cleaned up when scene is deleted.
Fixes bug in MaterialParameter implementation of AnimationTarget - Can now animate MaterialParameters.
Refactored code for blending animations.
Removes inheritance of Ref from AnimationTarget because it was not being used.
Node and MaterialParameter now inherit from Ref.
Kieran Cunney 14 năm trước cách đây
mục cha
commit
4361af0cbd

+ 42 - 23
gameplay/src/Animation.cpp

@@ -31,15 +31,6 @@ Animation::Animation(const char* id, AnimationTarget* target, int propertyId, un
 
 Animation::~Animation()
 {
-    std::vector<Channel*>::iterator channelIter = _channels.begin();
-    
-    while (channelIter != _channels.end())
-    {
-        SAFE_DELETE(*channelIter);
-        channelIter++;
-    }
-    _channels.clear();
-    
     if (_clips != NULL)
     {
         std::vector<AnimationClip*>::iterator clipIter = _clips->begin();
@@ -47,31 +38,42 @@ Animation::~Animation()
         while (clipIter != _clips->end())
         {   
             AnimationClip* clip = *clipIter;
+            clip->stop();
             SAFE_RELEASE(clip);
             clipIter++;
         }
         _clips->clear();
     }
-
     SAFE_DELETE(_clips);
 
     SAFE_DELETE(_defaultClip);
+
+    /*std::vector<Channel*>::iterator channelIter = _channels.begin();
+    while (channelIter != _channels.end())
+    {
+        Animation::Channel* channel = *channelIter;
+        channel->_target->removeChannel(channel);
+        SAFE_RELEASE(channel);
+        channelIter++;
+    }*/
+    _channels.clear();
 }
 
-Animation::Channel::Channel(AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
-    : _isRelative(false)
+Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
+    : _animation(animation), _target(target), _propertyId(propertyId), _curve(curve), _duration(duration)
 {
     // get property component count, and ensure the property exists on the AnimationTarget by getting the property component count.
-    assert(target->getAnimationPropertyComponentCount(propertyId));
+    assert(_target->getAnimationPropertyComponentCount(propertyId));
+
+    _animation->addRef();
 
-    _target = target;
-    _propertyId = propertyId;
-    _curve = curve;
-    _duration = duration;
+    _target->addChannel(this);
 }
 
 Animation::Channel::~Channel()
 {
+    _animation->removeChannel(this);
+    SAFE_RELEASE(_animation);
     SAFE_DELETE(_curve);
 }
 
@@ -246,10 +248,8 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
 
     SAFE_DELETE(normalizedKeyTimes);
 
-    Channel* channel = new Channel(target, propertyId, curve, duration);
-
+    Channel* channel = new Channel(this, target, propertyId, curve, duration);
     addChannel(channel);
-
     return channel;
 }
 
@@ -295,10 +295,8 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
 
     SAFE_DELETE(normalizedKeyTimes);
 
-    Channel* channel = new Channel(target, propertyId, curve, duration);
-
+    Channel* channel = new Channel(this, target, propertyId, curve, duration);
     addChannel(channel);
-
     return channel;
 }
 
@@ -310,6 +308,27 @@ void Animation::addChannel(Channel* channel)
         _duration = channel->_duration;
 }
 
+void Animation::removeChannel(Channel* channel)
+{
+    std::vector<Animation::Channel*>::iterator itr = _channels.begin();
+    while (itr != _channels.end())
+    {
+        Animation::Channel* chan = *itr;
+        if (channel == chan) 
+        {
+            _channels.erase(itr);
+            itr = _channels.end();
+        }
+        else
+        {
+            itr++;
+        }
+    }
+
+    if (_channels.empty())
+        _controller->destroyAnimation(this);
+}
+
 void Animation::createDefaultClip()
 {
     std::string clipId = _id + ANIMATION_DEFAULT_CLIP_SUFFIX;

+ 8 - 2
gameplay/src/Animation.h

@@ -93,18 +93,19 @@ private:
     {
         friend class AnimationClip;
         friend class Animation;
+        friend class AnimationTarget;
 
     private:
 
-        Channel(AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration);
+        Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration);
         Channel(const Channel& copy);
         ~Channel();
 
+        Animation* _animation;                // Reference to the animation this channel belongs to.
         AnimationTarget* _target;             // The target of this channel.
         int _propertyId;                      // The target property this channel targets.
         Curve* _curve;                        // The curve used to represent the animation data.
         unsigned long _duration;              // The length of the animation (in milliseconds).
-        bool _isRelative;                     // Whether the data should be treated relatively or not. 
     };
 
     /**
@@ -161,6 +162,11 @@ private:
      * Adds a channel to the animation.
      */
     void addChannel(Channel* channel);
+
+    /**
+     * Removes a channel from the animation.
+     */
+    void removeChannel(Channel* channel);
     
     AnimationController* _controller;       // The AnimationController that this Animation will run on.
     std::string _id;                        // The Animation's ID.

+ 20 - 28
gameplay/src/AnimationClip.cpp

@@ -29,20 +29,15 @@ AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long
 
 AnimationClip::~AnimationClip()
 {
-    // Explicitly stop this clip if it's currently playing so it gets removed from the controller
-    if (_isPlaying)
-    {
-        stop();
-    }
-
     std::vector<AnimationValue*>::iterator valueIter = _values.begin();
     while (valueIter != _values.end())
     {
         SAFE_DELETE(*valueIter);
         valueIter++;
     }
+    _values.clear();
 
-    SAFE_DELETE(_crossFadeToClip);
+    SAFE_RELEASE(_crossFadeToClip);
     SAFE_DELETE(_channelPriority);
     SAFE_DELETE(_beginListeners);
     SAFE_DELETE(_endListeners);
@@ -308,10 +303,12 @@ bool AnimationClip::update(unsigned long elapsedTime)
         // Get the current value.
         target->getAnimationPropertyValue(channel->_propertyId, value);
 
+        bool isHighest = false;
         // My channel priority has changed if my priority is greater than the active animation count.
-        if (target->_reassignPriorities)
+        if (!target->_highestPriority)
         {
-            _channelPriority[i] = target->getPriority();
+            target->_highestPriority = channel;
+            value->_isFirstActing = true;
         }
 
         if (_blendWeight != 0.0f)
@@ -321,7 +318,7 @@ bool AnimationClip::update(unsigned long elapsedTime)
 
             if (channel->_curve->_quaternionOffsetsCount == 0)
             {
-                if (_channelPriority[i] == 1)
+                if (value->_isFirstActing)
                 {
                     unsigned int componentCount = value->_componentCount;
                     for (unsigned int j = 0; j < componentCount; j++)
@@ -350,7 +347,7 @@ bool AnimationClip::update(unsigned long elapsedTime)
                 unsigned int quaternionOffsetIndex = 0;
                 unsigned int quaternionOffset = 0;
 
-                if (_channelPriority[i] == 1)
+                if (value->_isFirstActing)
                 {
                     do {
                         quaternionOffset = channel->_curve->_quaternionOffsets[quaternionOffsetIndex];
@@ -434,7 +431,7 @@ bool AnimationClip::update(unsigned long elapsedTime)
                 }
             }
         }
-        else if (_channelPriority[i] == 1)
+        else if (value->_isFirstActing)
         {
             if (channel->_curve->_quaternionOffsetsCount == 0)
             {
@@ -503,17 +500,6 @@ void AnimationClip::onBegin()
         _runningTime = _activeDuration;
     }
 
-    AnimationTarget* target = NULL;
-    unsigned int channelCount = _animation->_channels.size();
-    // Sets the starting value.
-    for (unsigned int i = 0; i < channelCount; i++)
-    {
-        target = _animation->_channels[i]->_target;
-
-        target->increaseActiveAnimationCount();
-        _channelPriority[i] = target->getPriority();
-    }
-
     // Notify begin listeners.. if any.
     if (_beginListeners)
     {
@@ -528,15 +514,21 @@ void AnimationClip::onBegin()
 
 void AnimationClip::onEnd()
 {
+    AnimationValue* value;
+    Animation::Channel* channel = NULL;
     AnimationTarget* target = NULL;
     unsigned int channelCount = _animation->_channels.size();
     for (unsigned int i = 0; i < channelCount; i++)
     {
-        target = _animation->_channels[i]->_target;
-        
-        // Decrease active animation count on target and reset the channel priority
-        target->decreaseActiveAnimationCount();
-        _channelPriority[i] = 0;
+        value = _values[i];
+
+        if (value->_isFirstActing)
+        {
+            channel = _animation->_channels[i];
+            target = channel->_target;
+            target->_highestPriority = NULL;
+            value->_isFirstActing = false;
+        }
     }
 
     _blendWeight = 1.0f;

+ 1 - 1
gameplay/src/AnimationClip.h

@@ -230,7 +230,7 @@ private:
     void onEnd();
 
     std::string _id;                          // AnimationClip ID.
-    Animation* _animation;                    // Animations that this clip plays in parallel.
+    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.

+ 4 - 7
gameplay/src/AnimationController.cpp

@@ -28,9 +28,7 @@ Animation* AnimationController::createAnimation(const char* id, AnimationTarget*
     animation = new Animation(id, target, propertyId, keyCount, keyTimes, keyValues, type);
 
     addAnimation(animation);
-
-    target->addAnimation(animation);
-
+    
     return animation;
 }
 
@@ -46,8 +44,6 @@ Animation* AnimationController::createAnimation(const char* id, AnimationTarget*
 
     addAnimation(animation);
 
-    target->addAnimation(animation);
-
     return animation;
 }
 
@@ -130,6 +126,7 @@ void AnimationController::initialize()
 
 void AnimationController::finalize()
 {
+    stopAllAnimations();
     _state = PAUSED;
 }
 
@@ -218,6 +215,8 @@ void AnimationController::destroyAnimation(Animation* animation)
     {
         if (animation == *itr)
         {
+            Animation* animation = *itr;
+            SAFE_RELEASE(animation);
             _animations.erase(itr);
             return;
         }
@@ -227,8 +226,6 @@ void AnimationController::destroyAnimation(Animation* animation)
 
 void AnimationController::destroyAllAnimations()
 {
-    stopAllAnimations();
-
     std::vector<Animation*>::iterator itr = _animations.begin();
     
     while (itr != _animations.end())

+ 2 - 1
gameplay/src/AnimationController.h

@@ -14,6 +14,7 @@ namespace gameplay
 class AnimationController
 {
     friend class Game;
+    friend class Animation;
     friend class AnimationClip;
 
 public:
@@ -180,7 +181,7 @@ private:
     
     State _state;                               // The current state of the AnimationController.
     std::list<AnimationClip*> _runningClips;    // A list of currently running AnimationClips.
-    std::vector<Animation*> _animations;
+    std::vector<Animation*> _animations;        // A list of animations registered with the AnimationController
 };
 
 }

+ 11 - 78
gameplay/src/AnimationTarget.cpp

@@ -9,97 +9,30 @@ namespace gameplay
 {
 
 AnimationTarget::AnimationTarget()
-    : _targetType(SCALAR), _activeAnimationCount(0), _currentPriority(0), _animations(NULL), _reassignPriorities(false)
+    : _targetType(SCALAR), _highestPriority(NULL), _animationChannels(NULL)
 {
 }
 
 AnimationTarget::~AnimationTarget()
 {
-    if (_animations)
+    if (_animationChannels)
     {
-        std::vector<Animation*>::iterator animationIter = _animations->begin();
-        while (animationIter != _animations->end())
+        std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
+        while (itr != _animationChannels->end())
         {
-            SAFE_RELEASE((*animationIter));
-            animationIter++;
+            SAFE_DELETE((*itr));
+            itr++;
         }
-        SAFE_DELETE(_animations);
+        SAFE_DELETE(_animationChannels);
     }
 }
 
-void AnimationTarget::addAnimation(Animation* animation)
+void AnimationTarget::addChannel(Animation::Channel* channel)
 {
-    if (_animations == NULL)
-    {
-        _animations = new std::vector<Animation*>;
-    }
-
-    _animations->push_back(animation);
-
-    animation->addRef();
-}
-
-unsigned int AnimationTarget::getAnimationCount() const
-{
-    if (_animations)
-        return _animations->size();
-
-    return 0;
-}
-
-Animation* AnimationTarget::getAnimation(unsigned int index) const
-{
-    if (_animations)
-        return _animations->at(index);
-    else
-        return 0;
-}
-
-Animation* AnimationTarget::getAnimation(const char* id) const
-{
-    if (_animations)
-    {
-        std::vector<Animation*>::iterator animationIter = _animations->begin();
-        while(animationIter != _animations->end())
-        {
-            if ((*animationIter)->_id.compare(id) == 0)
-            {
-                return *animationIter;
-            }
-
-            animationIter++;
-        }
-    }
-    
-    return NULL;
-}
-
-void AnimationTarget::increaseActiveAnimationCount()
-{
-    ++_activeAnimationCount;
-}
-
-void AnimationTarget::decreaseActiveAnimationCount()
-{
-    --_activeAnimationCount;
-
-    _reassignPriorities = true;
-    _currentPriority = 0;
-}
-
-unsigned int AnimationTarget::getPriority() 
-{
-    if (_reassignPriorities)
-    {
-        ++_currentPriority;
-
-        if (_currentPriority == _activeAnimationCount)
-            _reassignPriorities = false;
-
-        return _currentPriority;
-    }
+    if (_animationChannels == NULL)
+        _animationChannels = new std::vector<Animation::Channel*>;
 
-    return _activeAnimationCount;
+    _animationChannels->push_back(channel);
 }
 
 }

+ 7 - 24
gameplay/src/AnimationTarget.h

@@ -14,7 +14,7 @@ class AnimationValue;
  * Defines an interface allowing animation to target
  * an object for changing its animation properties.
  */
-class AnimationTarget : public Ref
+class AnimationTarget
 {
     friend class Animation;
     friend class AnimationClip;
@@ -52,7 +52,7 @@ public:
      * 
      * @return The number of Animations targeting this object.
      */
-    unsigned int getAnimationCount() const;
+    //unsigned int getAnimationCount() const;
 
     /**
      * Gets the Animation with the given index.
@@ -61,7 +61,7 @@ public:
      *
      * @return The Animation at the given index.
      */
-    Animation* getAnimation(unsigned int index) const;
+    //Animation* getAnimation(unsigned int index) const;
 
     /**
      * Finds the Animation with the given ID.
@@ -70,7 +70,7 @@ public:
      * 
      * @return The Animation with the given ID. NULL if the Animation is not found.
      */
-    Animation* getAnimation(const char* id) const;
+    //Animation* getAnimation(const char* id) const;
 
 protected:
     
@@ -90,7 +90,7 @@ protected:
      */
     virtual ~AnimationTarget();
 
-    void addAnimation(Animation* animation);
+    void addChannel(Animation::Channel* animation);
 
     TargetType _targetType;             // The type of target this is.
 
@@ -101,25 +101,8 @@ private:
      */
     AnimationTarget(const AnimationTarget& copy);
 
-    /**
-     * Increases the active animation count on the target by one.
-     */
-    void increaseActiveAnimationCount();
-
-    /**
-     * Decreases the active animation count on the target by one.
-     */
-    void decreaseActiveAnimationCount();
-
-    /**
-     * Gets the priority to assign to the channel when reassigning priorities.
-     */
-    unsigned int getPriority();
-
-    unsigned int _activeAnimationCount;        // The number of active animations targeting this AnimationTarget.
-    bool _reassignPriorities;                  // A flag to indicate that channel priorities for this AnimationTarget need to be reassigned
-    unsigned int _currentPriority;             // Used to keep track of the current priority when reassigning channel priorities
-    std::vector<Animation*>* _animations;      // Collection of all animations on that target the AnimationTarget
+    Animation::Channel* _highestPriority;
+    std::vector<Animation::Channel*>* _animationChannels;   // Collection of all animation channels that target the AnimationTarget
 
 };
 }

+ 1 - 1
gameplay/src/AnimationValue.cpp

@@ -5,7 +5,7 @@ namespace gameplay
 {
 
 AnimationValue::AnimationValue(unsigned int componentCount)
-  : _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
+  : _isFirstActing(false), _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
 {
     _currentValue = new float[_componentCount];
     _interpolatedValue = new float[_componentCount];

+ 3 - 2
gameplay/src/AnimationValue.h

@@ -72,10 +72,11 @@ private:
      */
     ~AnimationValue();
 
+    bool _isFirstActing;            // Flag indicating if this value's channel is the first to act on the target.
     unsigned int _componentCount;   // The number of float values for the property.
-    unsigned int _componentSize;
+    unsigned int _componentSize;    // The number of bytes of memory the property is.
     float* _currentValue;           // The current value of the property.
-    float* _interpolatedValue;
+    float* _interpolatedValue;      // The last interpolated value of the property.
 };
 
 }

+ 32 - 4
gameplay/src/MaterialParameter.cpp

@@ -302,8 +302,17 @@ unsigned int MaterialParameter::getAnimationPropertyComponentCount(int propertyI
                 case SAMPLER:
                 case METHOD:
                     return 0;
+                case FLOAT:
+                case INT:
+                    return 1;
+                case VECTOR2:
+                    return 2 * _count;
+                case VECTOR3:
+                    return 3 * _count;
+                case VECTOR4:
+                    return 4 * _count;
                 default:
-                    return _count;
+                    return 0;
             }
         }
     }
@@ -326,11 +335,21 @@ void MaterialParameter::getAnimationPropertyValue(int propertyId, AnimationValue
                     value->setFloat(0, _value.intValue);
                     break;
                 case VECTOR2:
+                    for (unsigned int i = 0; i < _count; i++)
+                    {
+                        value->setFloat(_value.floatPtrValue, i * 2, 2);
+                    }
+                    break;
                 case VECTOR3:
+                    for (unsigned int i = 0; i < _count; i++)
+                    {
+                        value->setFloat(_value.floatPtrValue, i * 3, 3);
+                    }
+                    break;
                 case VECTOR4:
                     for (unsigned int i = 0; i < _count; i++)
                     {
-                        value->setFloat(i, _value.floatPtrValue[i]);
+                        value->setFloat(_value.floatPtrValue, i * 4, 4);
                     }
                     break;
 
@@ -355,12 +374,21 @@ void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue
                     _value.intValue = value->getFloat(0);
                     break;
                 case VECTOR2:
+                    for (unsigned int i = 0; i < _count; i++)
+                    {
+                        value->getFloat(_value.floatPtrValue, i * 2, 2);
+                    }
+                    break;
                 case VECTOR3:
+                    for (unsigned int i = 0; i < _count; i++)
+                    {
+                        value->getFloat(_value.floatPtrValue, i * 3, 3);
+                    }
+                    break;
                 case VECTOR4:
-                case MATRIX:
                     for (unsigned int i = 0; i < _count; i++)
                     {
-                        _value.floatPtrValue[i] = value->getFloat(i);
+                        value->getFloat(_value.floatPtrValue, i * 4, 4);
                     }
                     break;
 

+ 1 - 1
gameplay/src/MaterialParameter.h

@@ -27,7 +27,7 @@ namespace gameplay
  * to the Matrix will automatically be reflected in the technique the
  * next time the parameter is applied to the render state.
  */
-class MaterialParameter : public AnimationTarget
+class MaterialParameter : public AnimationTarget, public Ref
 {
     friend class RenderState;
 

+ 1 - 1
gameplay/src/Node.h

@@ -19,7 +19,7 @@ class Scene;
 /**
  * Defines a basic hierachial structure of transformation spaces.
  */
-class Node : public Transform
+class Node : public Transform, public Ref
 {
     friend class Scene;
     friend class Package;