Bläddra i källkod

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

Kieran Cunney 14 år sedan
förälder
incheckning
fea5e09cde

+ 1 - 4
gameplay/gameplay.vcxproj

@@ -171,11 +171,8 @@
     <None Include="res\textures\particle-default.png" />
     <None Include="src\BoundingBox.inl" />
     <None Include="src\BoundingSphere.inl" />
-<<<<<<< HEAD
     <None Include="src\Curve.inl" />
-=======
-    <None Include="src\Game.inl" />
->>>>>>> 1e19bf6c4a08f8d9f44ef8c341b712ee50f83df9
+    <None Include="src\Game.inl" />
     <None Include="src\gameplay-main-macos.mm" />
     <None Include="src\Matrix.inl" />
     <None Include="src\Plane.inl" />

+ 2 - 3
gameplay/gameplay.vcxproj.filters

@@ -475,11 +475,10 @@
     <None Include="res\textures\particle-default.png">
       <Filter>res\textures</Filter>
     </None>
-<<<<<<< HEAD
     <None Include="src\Curve.inl">
-=======
+        <Filter>src</Filter>
+    </None>
     <None Include="src\Game.inl">
->>>>>>> 1e19bf6c4a08f8d9f44ef8c341b712ee50f83df9
       <Filter>src</Filter>
     </None>
   </ItemGroup>

+ 87 - 77
gameplay/src/Animation.cpp

@@ -7,7 +7,6 @@
 #include "Transform.h"
 #include "Properties.h"
 
-#define ANIMATION_DEFAULT_CLIP_SUFFIX "__default__clip"
 #define ANIMATION_INDEFINITE_STR "INDEFINITE"
 #define ANIMATION_DEFAULT_CLIP 0
 #define ANIMATION_ROTATE_OFFSET 0
@@ -30,7 +29,13 @@ Animation::Animation(const char* id, AnimationTarget* target, int propertyId, un
 
 Animation::~Animation()
 {
-    if (_clips != NULL)
+    if (_defaultClip)
+    {
+        _defaultClip->stop();
+        SAFE_RELEASE(_defaultClip);
+    }
+
+    if (_clips)
     {
         std::vector<AnimationClip*>::iterator clipIter = _clips->begin();
     
@@ -44,10 +49,6 @@ Animation::~Animation()
         _clips->clear();
     }
     SAFE_DELETE(_clips);
-
-    SAFE_DELETE(_defaultClip);
-
-    _channels.clear();
 }
 
 Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
@@ -82,47 +83,18 @@ void Animation::createClips(const char* animationFile)
 {
     assert(animationFile);
 
-    Properties* pAnim = Properties::create(animationFile);
-    assert(pAnim);
-
-    Properties* animation = pAnim->getNextNamespace();
-    int frameCount = animation->getInt("frameCount");
-
-    const Properties* pClip = animation->getNextNamespace();
-    while (pClip != NULL)
-    {
-        int begin = pClip->getInt("begin");
-        int end = pClip->getInt("end");
-
-        AnimationClip* clip = createClip(pClip->getId(), ((float) begin / frameCount) * _duration, ((float) end / frameCount) * _duration);
-
-        const char* repeat = pClip->getString("repeatCount");
-        if (repeat)
-        {
-            if (strcmp(repeat, ANIMATION_INDEFINITE_STR) == 0)
-            {
-                clip->setRepeatCount(AnimationClip::REPEAT_INDEFINITE);
-            }
-            else
-            {
-                float value;
-                sscanf(repeat, "%f", &value);
-                clip->setRepeatCount(value);
-            }
-        }
+    Properties* properties = Properties::create(animationFile);
+    assert(properties);
 
-        const char* speed = pClip->getString("speed");
-        if (speed)
-        {
-            float value;
-            sscanf(speed, "%f", &value);
-            clip->setSpeed(value);
-        }
+    Properties* pAnimation = properties->getNextNamespace();
+    assert(pAnimation);
+    
+    int frameCount = pAnimation->getInt("frameCount");
+    assert(frameCount > 0);
 
-        pClip = animation->getNextNamespace();
-    }
+    createClips(pAnimation, (unsigned int)frameCount);
 
-    SAFE_DELETE(pAnim);
+    SAFE_DELETE(properties);
 }
 
 AnimationClip* Animation::createClip(const char* id, unsigned long start, unsigned long end)
@@ -190,6 +162,77 @@ void Animation::stop(const char* id)
     }
 }
 
+void Animation::createDefaultClip()
+{
+    _defaultClip = new AnimationClip("default_clip", this, 0.0f, _duration);
+}
+
+void Animation::createClips(Properties* animationProperties, unsigned int frameCount)
+{   
+    assert(animationProperties);
+    
+    Properties* pClip = animationProperties->getNextNamespace();
+    
+    while (pClip != NULL && std::strcmp(pClip->getNamespace(), "clip") == 0)
+    {
+        int begin = pClip->getInt("begin");
+        int end = pClip->getInt("end");
+
+        AnimationClip* clip = createClip(pClip->getId(), ((float) begin / frameCount) * _duration, ((float) end / frameCount) * _duration);
+
+        const char* repeat = pClip->getString("repeatCount");
+        if (repeat)
+        {
+            if (strcmp(repeat, ANIMATION_INDEFINITE_STR) == 0)
+            {
+                clip->setRepeatCount(AnimationClip::REPEAT_INDEFINITE);
+            }
+            else
+            {
+                float value;
+                sscanf(repeat, "%f", &value);
+                clip->setRepeatCount(value);
+            }
+        }
+
+        const char* speed = pClip->getString("speed");
+        if (speed)
+        {
+            float value;
+            sscanf(speed, "%f", &value);
+            clip->setSpeed(value);
+        }
+
+        pClip = animationProperties->getNextNamespace();
+    }
+}
+
+void Animation::addClip(AnimationClip* clip)
+{
+    if (_clips == NULL)
+        _clips = new std::vector<AnimationClip*>;
+
+    _clips->push_back(clip);
+}
+
+AnimationClip* Animation::findClip(const char* id) const
+{
+    if (_clips)
+    {
+        AnimationClip* clip = NULL;
+        unsigned int clipCount = _clips->size();
+        for (unsigned int i = 0; i < clipCount; i++)
+        {
+            clip = _clips->at(i);
+            if (clip->_id.compare(id) == 0)
+            {
+                return _clips->at(i);
+            }
+        }
+    }
+    return NULL;
+}
+
 Animation::Channel* Animation::createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, unsigned int type)
 {
     unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
@@ -313,37 +356,4 @@ void Animation::removeChannel(Channel* channel)
         _controller->destroyAnimation(this);
 }
 
-void Animation::createDefaultClip()
-{
-    std::string clipId = _id + ANIMATION_DEFAULT_CLIP_SUFFIX;
-
-    _defaultClip = new AnimationClip(clipId.c_str(), this, 0.0f, _duration);
-}
-
-void Animation::addClip(AnimationClip* clip)
-{
-    if (_clips == NULL)
-        _clips = new std::vector<AnimationClip*>;
-
-    _clips->push_back(clip);
-}
-
-AnimationClip* Animation::findClip(const char* id) const
-{
-    if (_clips)
-    {
-        AnimationClip* clip = NULL;
-        unsigned int clipCount = _clips->size();
-        for (unsigned int i = 0; i < clipCount; i++)
-        {
-            clip = _clips->at(i);
-            if (clip->_id.compare(id) == 0)
-            {
-                return _clips->at(i);
-            }
-        }
-    }
-    return NULL;
-}
-
 }

+ 11 - 5
gameplay/src/Animation.h

@@ -2,6 +2,7 @@
 #define ANIMATION_H_
 
 #include "Ref.h"
+#include "Properties.h"
 
 namespace gameplay
 {
@@ -133,6 +134,16 @@ private:
      */
     ~Animation();
 
+    /**
+     * Creates the default clip.
+     */
+    void createDefaultClip();
+
+    /**
+     * Creates AnimationClip's for this Animation from the specified Property object.
+     */
+    void createClips(Properties* animationProperties, unsigned int frameCount);
+
     /**
      * Adds a clip to this Animation.
      */
@@ -143,11 +154,6 @@ private:
      */
     AnimationClip* findClip(const char* id) const;
 
-    /**
-     * Creates the default clip.
-     */
-    void createDefaultClip();
-
     /**
      * Creates a channel within this animation.
      */ 

+ 2 - 6
gameplay/src/AnimationClip.cpp

@@ -11,18 +11,15 @@ 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), 
-      _channelPriority(NULL), _crossFadeToClip(NULL), _crossFadeStart(0), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f), 
+      _crossFadeToClip(NULL), _crossFadeStart(0), _crossFadeOutElapsed(0), _crossFadeOutDuration(0), _blendWeight(1.0f), 
       _isFadingOutStarted(false), _isFadingOut(false), _isFadingIn(false), _beginListeners(NULL), _endListeners(NULL)
 {
     assert(0 <= startTime && startTime <= animation->_duration && 0 <= endTime && endTime <= animation->_duration);
     
-    unsigned int channelCount = _animation->_channels.size();
-    _channelPriority = new unsigned int[channelCount];
-    
+    unsigned int channelCount = _animation->_channels.size();    
     for (unsigned int i = 0; i < channelCount; i++)
     {
         _values.push_back(new AnimationValue(_animation->_channels[i]->_curve->getComponentCount()));
-        _channelPriority[i] = 0;
     }
 }
 
@@ -37,7 +34,6 @@ AnimationClip::~AnimationClip()
     _values.clear();
 
     SAFE_RELEASE(_crossFadeToClip);
-    SAFE_DELETE(_channelPriority);
     SAFE_DELETE(_beginListeners);
     SAFE_DELETE(_endListeners);
 }

+ 0 - 1
gameplay/src/AnimationClip.h

@@ -239,7 +239,6 @@ private:
     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.
-    unsigned int* _channelPriority;           // Keeps track of each channel's priority.
     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.

+ 149 - 19
gameplay/src/AnimationController.cpp

@@ -19,8 +19,8 @@ AnimationController::~AnimationController()
 Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, Curve::InterpolationType type)
 {
     assert(type != Curve::BEZIER && type != Curve::HERMITE);
-    assert(id && keyCount >= 2 && keyTimes && keyValues);
-    
+    assert(keyCount >= 2 && keyTimes && keyValues && target);
+
     Animation* animation = new Animation(id, target, propertyId, keyCount, keyTimes, keyValues, type);
 
     addAnimation(animation);
@@ -30,7 +30,7 @@ Animation* AnimationController::createAnimation(const char* id, AnimationTarget*
 
 Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type)
 {
-    assert(id && keyCount >= 2 && keyTimes && keyValues && keyInValue && keyOutValue);
+    assert(target && keyCount >= 2 && keyTimes && keyValues && keyInValue && keyOutValue);
     Animation* animation = new Animation(id, target, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
 
     addAnimation(animation);
@@ -38,21 +38,16 @@ Animation* AnimationController::createAnimation(const char* id, AnimationTarget*
     return animation;
 }
 
-Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, Properties* p)
+Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, const char* animationFile)
 {
-    Animation* animation = getAnimation(id);
-
-    if (animation != NULL)
-        return NULL;
+    assert(target && animationFile);
     
-    // TODO: Implement loading from a properties object here.
-    /*
-    animation = new Animation(id, target, p);
+    Properties* p = Properties::create(animationFile);
+    assert(p);
 
-    addAnimation(animation);
+    Animation* animation = createAnimation(id, target, p->getNextNamespace());
 
-    target->addAnimation(animation);
-    */
+    SAFE_DELETE(p);
 
     return animation;
 }
@@ -116,7 +111,6 @@ void AnimationController::stopAllAnimations()
         AnimationClip* clip = *clipIter;
         clip->_isPlaying = false;
         clip->onEnd();
-        clipIter = _runningClips.erase(clipIter);
         SAFE_RELEASE(clip);
     }
     _runningClips.clear();
@@ -124,6 +118,144 @@ void AnimationController::stopAllAnimations()
     _state = IDLE;
 }
 
+Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, Properties* animationProperties)
+{
+    assert(target && animationProperties);
+    assert(std::strcmp(animationProperties->getNamespace(), "animation") == 0);
+    
+    const char* propertyIdStr = animationProperties->getString("property");
+    assert(propertyIdStr);
+    
+    // Get animation target property id
+    int propertyId = AnimationTarget::getPropertyId(target->_targetType, propertyIdStr);
+    assert(propertyId != -1);
+    
+    unsigned int keyCount = animationProperties->getInt("keyCount");
+    assert(keyCount > 0);
+
+    const char* keyTimesStr = animationProperties->getString("keyTimes");
+    assert(keyTimesStr);
+    
+    const char* keyValuesStr = animationProperties->getString("keyValues");
+    assert(keyValuesStr);
+    
+    const char* curveStr = animationProperties->getString("curve");
+    assert(curveStr);
+    
+    char delimeter = ' ';
+    unsigned int startOffset = 0;
+    unsigned int endOffset = std::string::npos;
+    
+    unsigned long* keyTimes = new unsigned long[keyCount];
+    for (unsigned int i = 0; i < keyCount; i++)
+    {
+        endOffset = static_cast<std::string>(keyTimesStr).find_first_of(delimeter, startOffset);
+        if (endOffset != std::string::npos)
+        {
+            keyTimes[i] = std::strtoul(static_cast<std::string>(keyTimesStr).substr(startOffset, endOffset - startOffset).c_str(), NULL, 0);
+        }
+        else
+        {
+            keyTimes[i] = std::strtoul(static_cast<std::string>(keyTimesStr).substr(startOffset, static_cast<std::string>(keyTimesStr).length()).c_str(), NULL, 0);
+        }
+        startOffset = endOffset + 1;
+    }
+
+    startOffset = 0;
+    endOffset = std::string::npos;
+    
+    int componentCount = target->getAnimationPropertyComponentCount(propertyId);
+    assert(componentCount > 0);
+    
+    unsigned int components = keyCount * componentCount;
+    
+    float* keyValues = new float[components];
+    for (unsigned int i = 0; i < components; i++)
+    {
+        endOffset = static_cast<std::string>(keyValuesStr).find_first_of(delimeter, startOffset);
+        if (endOffset != std::string::npos)
+        {   
+            keyValues[i] = std::atof(static_cast<std::string>(keyValuesStr).substr(startOffset, endOffset - startOffset).c_str());
+        }
+        else
+        {
+            keyValues[i] = std::atof(static_cast<std::string>(keyValuesStr).substr(startOffset, static_cast<std::string>(keyValuesStr).length()).c_str());
+        }
+        startOffset = endOffset + 1;
+    }
+
+    const char* keyInStr = animationProperties->getString("keyIn");
+    float* keyIn = NULL;
+    if (keyInStr)
+    {
+        keyIn = new float[components];
+        startOffset = 0;
+        endOffset = std::string::npos;
+        for (unsigned int i = 0; i < components; i++)
+        {
+            endOffset = static_cast<std::string>(keyInStr).find_first_of(delimeter, startOffset);
+            if (endOffset != std::string::npos)
+            {   
+                keyIn[i] = std::atof(static_cast<std::string>(keyInStr).substr(startOffset, endOffset - startOffset).c_str());
+            }
+            else
+            {
+                keyIn[i] = std::atof(static_cast<std::string>(keyInStr).substr(startOffset, static_cast<std::string>(keyInStr).length()).c_str());
+            }
+            startOffset = endOffset + 1;
+        }
+    }
+    
+    const char* keyOutStr = animationProperties->getString("keyOut");
+    float* keyOut = NULL;
+    if(keyOutStr)
+    {   
+        keyOut = new float[components];
+        startOffset = 0;
+        endOffset = std::string::npos;
+        for (unsigned int i = 0; i < components; i++)
+        {
+            endOffset = static_cast<std::string>(keyOutStr).find_first_of(delimeter, startOffset);
+            if (endOffset != std::string::npos)
+            {   
+                keyOut[i] = std::atof(static_cast<std::string>(keyOutStr).substr(startOffset, endOffset - startOffset).c_str());
+            }
+            else
+            {
+                keyOut[i] = std::atof(static_cast<std::string>(keyOutStr).substr(startOffset, static_cast<std::string>(keyOutStr).length()).c_str());
+            }
+            startOffset = endOffset + 1;
+        }
+    }
+
+    int curve = Curve::getInterpolationType(curveStr);
+
+    Animation* animation = NULL;
+    if (keyIn && keyOut)
+    {
+        animation = createAnimation(id, target, propertyId, keyCount, keyTimes, keyValues, keyIn, keyOut, (Curve::InterpolationType)curve);
+    }
+    else
+    {
+        animation = createAnimation(id, target, propertyId, keyCount, keyTimes, keyValues, (Curve::InterpolationType) curve);
+    }
+
+    SAFE_DELETE(keyOut);
+    SAFE_DELETE(keyIn);
+    SAFE_DELETE(keyValues);
+    SAFE_DELETE(keyTimes);
+
+    Properties* pClip = animationProperties->getNextNamespace();
+    if (pClip && std::strcmp(pClip->getNamespace(), "clip") == 0)
+    {
+        int frameCount = animationProperties->getInt("frameCount");
+        assert(frameCount > 0);
+        animation->createClips(animationProperties, (unsigned int) frameCount);
+    }
+
+    return animation;
+}
+
 AnimationController::State AnimationController::getState() const
 {
     return _state;
@@ -192,20 +324,18 @@ void AnimationController::update(long elapsedTime)
         return;
 
     std::list<AnimationClip*>::iterator clipIter = _runningClips.begin();
-    unsigned int clipCount = 0;
     while (clipIter != _runningClips.end())
     {
         AnimationClip* clip = (*clipIter);
         if (clip->update(elapsedTime))
         {
-            clipIter = _runningClips.erase(clipIter);
             SAFE_RELEASE(clip);
+            clipIter = _runningClips.erase(clipIter);
         }
         else
         {
             clipIter++;
         }
-        clipCount++;
     }
     
     if (_runningClips.empty())
@@ -226,8 +356,8 @@ void AnimationController::destroyAnimation(Animation* animation)
         if (animation == *itr)
         {
             Animation* animation = *itr;
-            SAFE_RELEASE(animation);
             _animations.erase(itr);
+            SAFE_RELEASE(animation);
             return;
         }
         itr++;

+ 15 - 3
gameplay/src/AnimationController.h

@@ -17,6 +17,7 @@ class AnimationController
     friend class Game;
     friend class Animation;
     friend class AnimationClip;
+    friend class SceneLoader;
 
 public:
 
@@ -58,11 +59,11 @@ public:
      * 
      * @param id The ID of the animation.
      * @param target The animation target.
-     * @param properties The properties object defining the animation data.
+     * @param animationFile The animation file defining the animation data.
      *
      * @return The newly created animation.
      */
-    Animation* createAnimation(const char* id, AnimationTarget* target, Properties* p);
+    Animation* createAnimation(const char* id, AnimationTarget* target, const char* animationFile);
 
     /**
      * Creates a simple two keyframe from-to animation.
@@ -134,6 +135,17 @@ private:
      */
     ~AnimationController();
     
+    /**
+     * Creates an animation on this target using the data from the given properties object. 
+     * 
+     * @param id The ID of the animation.
+     * @param target The animation target.
+     * @param properties The properties object defining the animation data.
+     *
+     * @return The newly created animation.
+     */
+    Animation* createAnimation(const char* id, AnimationTarget* target, Properties* animationProperties);
+
     /**
      * Gets the controller's state.
      *
@@ -175,7 +187,7 @@ private:
      * Callback for when the controller receives a frame update event.
      */
     void update(long elapsedTime);
-    
+
     /**
      * Adds an animation on this AnimationTarget.
      */ 

+ 87 - 1
gameplay/src/AnimationTarget.cpp

@@ -19,9 +19,11 @@ AnimationTarget::~AnimationTarget()
         std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
         while (itr != _animationChannels->end())
         {
-            SAFE_DELETE((*itr));
+            Animation::Channel* channel = (*itr);
+            SAFE_DELETE(channel);
             itr++;
         }
+        _animationChannels->clear();
         SAFE_DELETE(_animationChannels);
     }
 }
@@ -34,6 +36,90 @@ void AnimationTarget::addChannel(Animation::Channel* channel)
     _animationChannels->push_back(channel);
 }
 
+int AnimationTarget::getPropertyId(TargetType type, const char* propertyIdStr)
+{
+    if (type == AnimationTarget::TRANSFORM)
+    {
+        if (strcmp(propertyIdStr, "ANIMATE_SCALE") == 0)
+        {
+            return Transform::ANIMATE_SCALE;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_SCALE_X") == 0)
+        {
+            return Transform::ANIMATE_SCALE_X;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_SCALE_Y") == 0)
+        {
+            return Transform::ANIMATE_SCALE_Y;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_SCALE_Z") == 0)
+        {
+            return Transform::ANIMATE_SCALE_Z;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_SCALE_XY") == 0)
+        {
+            return Transform::ANIMATE_SCALE_XY;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_SCALE_XZ") == 0)
+        {
+            return Transform::ANIMATE_SCALE_XZ;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_SCALE_YZ") == 0)
+        {
+            return Transform::ANIMATE_SCALE_YZ;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_ROTATE") == 0)
+        {
+            return Transform::ANIMATE_ROTATE;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_TRANSLATE") == 0)
+        {
+            return Transform::ANIMATE_TRANSLATE;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_TRANSLATE_X") == 0)
+        {
+            return Transform::ANIMATE_TRANSLATE_X;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_TRANSLATE_Y") == 0)
+        {
+            return Transform::ANIMATE_TRANSLATE_Y;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_TRANSLATE_Z") == 0)
+        {
+            return Transform::ANIMATE_TRANSLATE_Z;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_TRANSLATE_XY") == 0)
+        {
+            return Transform::ANIMATE_TRANSLATE_XY;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_TRANSLATE_XZ") == 0)
+        {
+            return Transform::ANIMATE_TRANSLATE_XZ;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_TRANSLATE_YZ") == 0)
+        {
+            return Transform::ANIMATE_TRANSLATE_YZ;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_ROTATE_TRANSLATE") == 0)
+        {
+            return Transform::ANIMATE_ROTATE_TRANSLATE;
+        }
+        else if (strcmp(propertyIdStr, "ANIMATE_SCALE_ROTATE_TRANSLATE") == 0)
+        {
+            return Transform::ANIMATE_SCALE_ROTATE_TRANSLATE;
+        }
+    }
+    else
+    {
+        if (strcmp(propertyIdStr, "ANIMATE_UNIFORM") == 0)
+        {
+            return MaterialParameter::ANIMATE_UNIFORM;
+        }
+    }
+
+    return -1;
+}
+
 }
 
 

+ 10 - 0
gameplay/src/AnimationTarget.h

@@ -76,6 +76,16 @@ private:
      */
     AnimationTarget(const AnimationTarget& copy);
 
+    /**
+     * Gets the TargetType's property ID value for the specified property ID string.
+     * 
+     * @param type The TargetType of the AnimationTarget.
+     * @param propertyIdStr The property ID string.
+     * @return The property ID value for teh property ID string; -1 if the propertyIdStr does not exist
+     *    for the TargetType.
+     */
+    static int getPropertyId(TargetType type, const char* propertyIdStr);
+
     Animation::Channel* _highestPriority;
     std::vector<Animation::Channel*>* _animationChannels;   // Collection of all animation channels that target the AnimationTarget
 

+ 225 - 128
gameplay/src/Curve.cpp

@@ -1,6 +1,7 @@
 // Purposely not including Base.h here, or any other gameplay dependencies
 // so this class can be reused between gameplay and gameplay-encoder.
 #include "Curve.h"
+#include "Quaternion.h"
 #include <cassert>
 #include <cmath>
 #include <memory>
@@ -11,6 +12,7 @@ using std::sqrt;
 using std::cos;
 using std::sin;
 using std::exp;
+using std::strcmp;
 
 #ifndef NULL
 #define NULL 0
@@ -234,19 +236,19 @@ void Curve::evaluate(float time, float* dst) const
         }
         case QUADRATIC_OUT:
         {
-            t *= (t - 2.0f);
+            t *= -(t - 2.0f);
             break;
         }
         case QUADRATIC_IN_OUT:
         {
-            if (t *= 2.0f < 1.0f)
-            {
-                t *= t * 0.5f;
-            }
+            float tx2 = t * 2.0f;
+
+            if (tx2 < 1.0f)
+                t = 0.5f * (tx2 * tx2);
             else
             {
-                t -= 1.0f;
-                t = (-(t * (t - 2.0f)) + 1.0f) * 0.5f;
+                float temp = tx2 - 1.0f;
+                t = 0.5f * (-( temp * (temp - 2.0f)) + 1.0f);
             }
             break;
         }
@@ -414,7 +416,7 @@ void Curve::evaluate(float time, float* dst) const
                 }
                 else
                 {
-                    t = -0.5f * exp(10.0f * (2.0f * t + 1.0f)) + 1.0f;
+                    t = -0.5f * exp(10.0f * (-2.0f * t + 1.0f)) + 1.0f;
                 }
             }
             break;
@@ -450,12 +452,12 @@ void Curve::evaluate(float time, float* dst) const
             t *= 2.0f;
             if (t < 1.0f)
             {
-                t = 0.5f * -(sqrt(1.0f - t * t) + 1.0f);
+                t = 0.5f * (-sqrt((1.0f - t * t)) + 1.0f);
             }
             else
             {
                 t -= 2.0f;
-                t = 0.5f * (sqrt(1.0f - t * t) + 1.0f);
+                t = 0.5f * (sqrt((1.0f - t * t)) + 1.0f);
             }
             break;
         }
@@ -476,8 +478,8 @@ void Curve::evaluate(float time, float* dst) const
         {
             if (t != 0.0f && t != 1.0f)
             {
-                t--;
-                t = -exp(10.0f * t) * sin(t - 0.075f) * (MATH_PIX2 / 0.3f);
+                t = t - 1.0f;
+                t = -1.0f * ( exp(10.0f * t) * sin( (t - 0.075f) * MATH_PIX2 / 0.3f ) );
             }
             break;
         }
@@ -496,11 +498,11 @@ void Curve::evaluate(float time, float* dst) const
                 t = 2.0f * t - 1.0f;
                 if (t < 0.0f)
                 {
-                    t = -0.5f * (exp((10 * time)) * sin(((time - 0.1125f) * MATH_PIX2 / 0.45f)));
+                    t = -0.5f * (exp((10 * t)) * sin(((t - 0.1125f) * MATH_PIX2 / 0.45f)));
                 }
                 else
                 {
-                    t = 0.5f * exp((-10 * time)) * sin(((time - 0.1125f) * MATH_PIX2 / 0.45f)) + 1.0f;
+                    t = 0.5f * exp((-10 * t)) * sin(((t - 0.1125f) * MATH_PIX2 / 0.45f)) + 1.0f;
                 }
             }
             break;
@@ -510,26 +512,26 @@ void Curve::evaluate(float time, float* dst) const
             if (t != 0.0f && t != 1.0f)
             {
                 t *= 2.0f;
-                if (time < 1.0f)
+                if (t < 1.0f)
                 {
-                    t = 0.5f * (exp(-10.0f * t) * sin((t - 0.1125f) * MATH_PIX2 / 0.45f)) + 0.5f;
+                    t = 0.5f * (exp((-10 * t)) * sin(((t - 0.1125f) * (MATH_PIX2) / 0.45f))) + 0.5f;
                 }
                 else
                 {
-                    t = 0.5f * exp(10.0f * (t - 2.0f)) * sin((t - 0.1125f) * MATH_PIX2 / 0.45f) + 0.5f;
+                    t = 0.5f * (exp((10 *(t - 2))) * sin(((t - 0.1125f) * (MATH_PIX2) / 0.45f))) + 0.5f;
                 }
             }
             break;
         }
         case OVERSHOOT_IN:
         {
-            t = t * t * 2.70158f * t - 1.70158f;
+            t = t * t * (2.70158f * t - 1.70158f);
             break;
         }
         case OVERSHOOT_OUT:
         {
             t--;
-            t = t * t * 2.70158f * t + 1.70158f;
+            t = t * t * (2.70158f * t + 1.70158f) + 1;
             break;
         }
         case OVERSHOOT_IN_OUT:
@@ -542,7 +544,7 @@ void Curve::evaluate(float time, float* dst) const
             else
             {
                 t -= 2.0f;
-                t = 0.5f * t * t * (3.5949095f * t + 2.5949095f) + 2.0f;
+                t = 0.5f * (t * t * (3.5949095f * t + 2.5949095f) + 2.0f);
             }
             break;
         }
@@ -551,11 +553,11 @@ void Curve::evaluate(float time, float* dst) const
             t = 2.0f * t - 1.0f;
             if (t < 0.0f)
             {
-                t = 0.5f * t * t * (3.5949095f * t + 2.5949095f) + 1.0f;
+                t = 0.5f * (t * t * (3.5949095f * t + 2.5949095f) + 1.0f);
             }
             else
             {
-                t = 0.5f * t * t * (3.5949095f * t - 2.5949095f) + 1.0f;
+                t = 0.5f * (t * t * (3.5949095f * t - 2.5949095f) + 1.0f);
             }
             break;
         }
@@ -660,7 +662,7 @@ void Curve::evaluate(float time, float* dst) const
                     t = 7.5625f * t * t + 0.984375f;
                 }
 
-                t = (t + 0.5f) * 0.5f;
+                t = 0.5f * t + 0.5f;
             }
             break;
         }
@@ -1146,119 +1148,20 @@ void Curve::interpolateLinear(float s, Point* from, Point* to, float* dst) const
     }
 }
 
-void slerpQuat(float* q1, float* q2, float t, float* dst)
-{
-    // Fast slerp implementation by kwhatmough:
-    // It contains no division operations, no trig, no inverse trig
-    // and no sqrt. Not only does this code tolerate small constraint
-    // errors in the input quaternions, it actually corrects for them.
-    assert(dst);
-    assert(!(t < 0.0f || t > 1.0f));
-
-    if (t == 0.0f)
-    {
-        memcpy(dst, q1, sizeof(float) * 4);
-        return;
-    }
-    else if (t == 1.0f)
-    {
-        memcpy(dst, q2, sizeof(float) * 4);
-        return;
-    }
-
-    float halfY, alpha, beta;
-    float u, f1, f2a, f2b;
-    float ratio1, ratio2;
-    float halfSecHalfTheta, versHalfTheta;
-    float sqNotU, sqU;
-
-    float cosTheta = q1[3] * q2[3] + q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2];
-
-    // As usual in all slerp implementations, we fold theta.
-    alpha = cosTheta >= 0 ? 1.0f : -1.0f;
-    halfY = 1.0f + alpha * cosTheta;
-
-    // Here we bisect the interval, so we need to fold t as well.
-    f2b = t - 0.5f;
-    u = f2b >= 0 ? f2b : -f2b;
-    f2a = u - f2b;
-    f2b += u;
-    u += u;
-    f1 = 1.0f - u;
-
-    // One iteration of Newton to get 1-cos(theta / 2) to good accuracy.
-    halfSecHalfTheta = 1.09f - (0.476537f - 0.0903321f * halfY) * halfY;
-    halfSecHalfTheta *= 1.5f - halfY * halfSecHalfTheta * halfSecHalfTheta;
-    versHalfTheta = 1.0f - halfY * halfSecHalfTheta;
-
-    // Evaluate series expansions of the coefficients.
-    sqNotU = f1 * f1;
-    ratio2 = 0.0000440917108f * versHalfTheta;
-    ratio1 = -0.00158730159f + (sqNotU - 16.0f) * ratio2;
-    ratio1 = 0.0333333333f + ratio1 * (sqNotU - 9.0f) * versHalfTheta;
-    ratio1 = -0.333333333f + ratio1 * (sqNotU - 4.0f) * versHalfTheta;
-    ratio1 = 1.0f + ratio1 * (sqNotU - 1.0f) * versHalfTheta;
-
-    sqU = u * u;
-    ratio2 = -0.00158730159f + (sqU - 16.0f) * ratio2;
-    ratio2 = 0.0333333333f + ratio2 * (sqU - 9.0f) * versHalfTheta;
-    ratio2 = -0.333333333f + ratio2 * (sqU - 4.0f) * versHalfTheta;
-    ratio2 = 1.0f + ratio2 * (sqU - 1.0f) * versHalfTheta;
-
-    // Perform the bisection and resolve the folding done earlier.
-    f1 *= ratio1 * halfSecHalfTheta;
-    f2a *= ratio2;
-    f2b *= ratio2;
-    alpha *= f1 + f2a;
-    beta = f1 + f2b;
-
-    // Apply final coefficients to a and b as usual.
-    float w = alpha * q1[3] + beta * q2[3];
-    float x = alpha * q1[0] + beta * q2[0];
-    float y = alpha * q1[1] + beta * q2[1];
-    float z = alpha * q1[2] + beta * q2[2];
-
-    // This final adjustment to the quaternion's length corrects for
-    // any small constraint error in the inputs q1 and q2. But as you
-    // can see, it comes at the cost of 9 additional multiplication
-    // operations. If this error-correcting feature is not required,
-    // the following code may be removed.
-    f1 = 1.5f - 0.5f * (w * w + x * x + y * y + z * z);
-    dst[3] = w * f1;
-    dst[0] = x * f1;
-    dst[1] = y * f1;
-    dst[2] = z * f1;
-}
-
-void normalizeQuat(float* q)
-{
-    float n = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
-
-    // Do we need to normalize?
-    if (fabs(n) > 0.00001f && fabs(n - 1.0f) > 0.00001f)
-    {
-        n = sqrt(n);
-        q[0] /= n;
-        q[1] /= n;
-        q[2] /= n;
-        q[3] /= n;
-    }
-}
-
 void Curve::interpolateQuaternion(float s, float* from, float* to, float* dst) const
 {
-    float quatFrom[4] = { from[0], from[1], from[2], from[3] };
-    float quatTo[4] = { to[0], to[1], to[2], to[3] };
+    Quaternion quatFrom(from);
+    Quaternion quatTo(to);
 
     // Normalize the quaternions.
-    normalizeQuat(quatFrom);
-    normalizeQuat(quatTo);
+    quatFrom.normalize();
+    quatTo.normalize();
         
     // Evaluate.
     if (s >= 0)
-        slerpQuat(quatFrom, quatTo, s, dst);
+        Quaternion::slerp(quatFrom, quatTo, s, (Quaternion*)dst);
     else
-        slerpQuat(quatTo, quatFrom, -s, dst);
+        Quaternion::slerp(quatTo, quatFrom, -s, (Quaternion*)dst);
 }
 
 int Curve::determineIndex(float time) const
@@ -1284,4 +1187,198 @@ int Curve::determineIndex(float time) const
     return -1;
 }
 
+int Curve::getInterpolationType(const char* curveId)
+{
+    if (strcmp(curveId, "BEZIER") == 0)
+    {
+        return Curve::BEZIER;
+    }
+    else if (strcmp(curveId, "BSPLINE") == 0)
+    {
+        return Curve::BSPLINE;
+    }
+    else if (strcmp(curveId, "FLAT") == 0)
+    {
+        return Curve::FLAT;
+    }
+    else if (strcmp(curveId, "HERMITE") == 0)
+    {
+        return Curve::HERMITE;
+    }
+    else if (strcmp(curveId, "LINEAR") == 0)
+    {
+        return Curve::LINEAR;
+    }
+    else if (strcmp(curveId, "SMOOTH") == 0)
+    {
+        return Curve::SMOOTH;
+    }
+    else if (strcmp(curveId, "STEP") == 0)
+    {
+        return Curve::STEP;
+    }
+    else if (strcmp(curveId, "QUADRATIC_IN") == 0)
+    {
+        return Curve::QUADRATIC_IN;
+    }
+    else if (strcmp(curveId, "QUADRATIC_OUT") == 0)
+    {
+        return Curve::QUADRATIC_OUT;
+    }
+    else if (strcmp(curveId, "QUADRATIC_IN_OUT") == 0)
+    {
+        return Curve::QUADRATIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "QUADRATIC_OUT_IN") == 0)
+    {
+        return Curve::QUADRATIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "CUBIC_IN") == 0)
+    {
+        return Curve::CUBIC_IN;
+    }
+    else if (strcmp(curveId, "CUBIC_OUT") == 0)
+    {
+        return Curve::CUBIC_OUT;
+    }
+    else if (strcmp(curveId, "CUBIC_IN_OUT") == 0)
+    {
+        return Curve::CUBIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "CUBIC_OUT_IN") == 0)
+    {
+        return Curve::CUBIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "QUARTIC_IN") == 0)
+    {
+        return Curve::QUARTIC_IN;
+    }
+    else if (strcmp(curveId, "QUARTIC_OUT") == 0)
+    {
+        return Curve::QUARTIC_OUT;
+    }
+    else if (strcmp(curveId, "QUARTIC_IN_OUT") == 0)
+    {
+        return Curve::QUARTIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "QUARTIC_OUT_IN") == 0)
+    {
+        return Curve::QUARTIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "QUINTIC_IN") == 0)
+    {
+        return Curve::QUINTIC_IN;
+    }
+    else if (strcmp(curveId, "QUINTIC_OUT") == 0)
+    {
+        return Curve::QUINTIC_OUT;
+    }
+    else if (strcmp(curveId, "QUINTIC_IN_OUT") == 0)
+    {
+        return Curve::QUINTIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "QUINTIC_OUT_IN") == 0)
+    {
+        return Curve::QUINTIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "SINE_IN") == 0)
+    {
+        return Curve::SINE_IN;
+    }
+    else if (strcmp(curveId, "SINE_OUT") == 0)
+    {
+        return Curve::SINE_OUT;
+    }
+    else if (strcmp(curveId, "SINE_IN_OUT") == 0)
+    {
+        return Curve::SINE_IN_OUT;
+    }
+    else if (strcmp(curveId, "SINE_OUT_IN") == 0)
+    {
+        return Curve::SINE_OUT_IN;
+    }
+    else if (strcmp(curveId, "EXPONENTIAL_IN") == 0)
+    {
+        return Curve::EXPONENTIAL_IN;
+    }
+    else if (strcmp(curveId, "EXPONENTIAL_OUT") == 0)
+    {
+        return Curve::EXPONENTIAL_OUT;
+    }
+    else if (strcmp(curveId, "EXPONENTIAL_IN_OUT") == 0)
+    {
+        return Curve::EXPONENTIAL_IN_OUT;
+    }
+    else if (strcmp(curveId, "EXPONENTIAL_OUT_IN") == 0)
+    {
+        return Curve::EXPONENTIAL_OUT_IN;
+    }
+    else if (strcmp(curveId, "CIRCULAR_IN") == 0)
+    {
+        return Curve::CIRCULAR_IN;
+    }
+    else if (strcmp(curveId, "CIRCULAR_OUT") == 0)
+    {
+        return Curve::CIRCULAR_OUT;
+    }
+    else if (strcmp(curveId, "CIRCULAR_IN_OUT") == 0)
+    {
+        return Curve::CIRCULAR_IN_OUT;
+    }
+    else if (strcmp(curveId, "CIRCULAR_OUT_IN") == 0)
+    {
+        return Curve::CIRCULAR_OUT_IN;
+    }
+    else if (strcmp(curveId, "ELASTIC_IN") == 0)
+    {
+        return Curve::ELASTIC_IN;
+    }
+    else if (strcmp(curveId, "ELASTIC_OUT") == 0)
+    {
+        return Curve::ELASTIC_OUT;
+    }
+    else if (strcmp(curveId, "ELASTIC_IN_OUT") == 0)
+    {
+        return Curve::ELASTIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "ELASTIC_OUT_IN") == 0)
+    {
+        return Curve::ELASTIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "OVERSHOOT_IN") == 0)
+    {
+        return Curve::OVERSHOOT_IN;
+    }
+    else if (strcmp(curveId, "OVERSHOOT_OUT") == 0)
+    {
+        return Curve::OVERSHOOT_OUT;
+    }
+    else if (strcmp(curveId, "OVERSHOOT_IN_OUT") == 0)
+    {
+        return Curve::OVERSHOOT_IN_OUT;
+    }
+    else if (strcmp(curveId, "OVERSHOOT_OUT_IN") == 0)
+    {
+        return Curve::OVERSHOOT_OUT_IN;
+    }
+    else if (strcmp(curveId, "BOUNCE_IN") == 0)
+    {
+        return Curve::BOUNCE_IN;
+    }
+    else if (strcmp(curveId, "BOUNCE_OUT") == 0)
+    {
+        return Curve::BOUNCE_OUT;
+    }
+    else if (strcmp(curveId, "BOUNCE_IN_OUT") == 0)
+    {
+        return Curve::BOUNCE_IN_OUT;
+    }
+    else if (strcmp(curveId, "BOUNCE_OUT_IN") == 0)
+    {
+        return Curve::BOUNCE_OUT_IN;
+    }
+
+    return -1;
+}
+
 }

+ 9 - 0
gameplay/src/Curve.h

@@ -11,6 +11,7 @@ class Curve
 {
     friend class Animation;
     friend class AnimationClip;
+    friend class AnimationController;
 
 public:
 
@@ -445,6 +446,14 @@ private:
      */ 
     int determineIndex(float time) const;
 
+    /**
+     * Gets the InterpolationType value for the given string ID
+     *
+     * @param interpolationId The string representation of the InterpolationType
+     * @return the InterpolationType value; -1 if the string does not represent an InterpolationType.
+     */
+    static int getInterpolationType(const char* interpolationId);
+
     unsigned int _pointCount;           // Number of points on the curve.
     unsigned int _componentCount;       // Number of components on the curve.
     unsigned int _componentSize;        // The component size (in bytes).

+ 3 - 1
gameplay/src/Game.cpp

@@ -161,8 +161,10 @@ void Game::frame()
     else
     {
         if (!_initialized)
+        {
             initialize();
-        _initialized = true;
+            _initialized = true;
+        }
     }
 
     // Update Time.

+ 6 - 0
gameplay/src/Transform.cpp

@@ -402,6 +402,12 @@ void Transform::setRotation(const Matrix& rotation)
     dirty();
 }
 
+void Transform::setRotation(const Vector3& axis, float angle)
+{
+    _rotation.set(axis, angle);
+    dirty();
+}
+
 void Transform::setTranslation(const Vector3& translation)
 {
     _translation.set(translation);