Sfoglia il codice sorgente

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

Adam Blake 13 anni fa
parent
commit
91f5662a6f
52 ha cambiato i file con 831 aggiunte e 596 eliminazioni
  1. 2 6
      gameplay/gameplay.xcodeproj/project.pbxproj
  2. 12 1
      gameplay/src/AbsoluteLayout.h
  3. 5 14
      gameplay/src/Animation.cpp
  4. 3 5
      gameplay/src/Animation.h
  5. 4 3
      gameplay/src/AnimationClip.h
  6. 1 303
      gameplay/src/AnimationController.cpp
  7. 5 119
      gameplay/src/AnimationController.h
  8. 275 6
      gameplay/src/AnimationTarget.cpp
  9. 115 5
      gameplay/src/AnimationTarget.h
  10. 2 1
      gameplay/src/AudioBuffer.h
  11. 0 3
      gameplay/src/AudioSource.h
  12. 0 2
      gameplay/src/Base.h
  13. 4 1
      gameplay/src/Button.h
  14. 0 1
      gameplay/src/Camera.h
  15. 4 1
      gameplay/src/CheckBox.h
  16. 24 0
      gameplay/src/Container.cpp
  17. 20 9
      gameplay/src/Container.h
  18. 18 17
      gameplay/src/Control.h
  19. 3 2
      gameplay/src/Curve.cpp
  20. 3 2
      gameplay/src/Curve.h
  21. 1 0
      gameplay/src/DebugNew.h
  22. 23 0
      gameplay/src/FlowLayout.h
  23. 1 4
      gameplay/src/Font.h
  24. 11 8
      gameplay/src/Form.h
  25. 4 1
      gameplay/src/FrameBuffer.h
  26. 2 2
      gameplay/src/Joint.h
  27. 5 2
      gameplay/src/Label.h
  28. 1 3
      gameplay/src/Light.h
  29. 6 5
      gameplay/src/Material.h
  30. 18 23
      gameplay/src/MaterialParameter.h
  31. 0 2
      gameplay/src/Mesh.h
  32. 6 0
      gameplay/src/MeshBatch.h
  33. 3 2
      gameplay/src/MeshSkin.h
  34. 0 1
      gameplay/src/Model.h
  35. 63 0
      gameplay/src/Node.cpp
  36. 8 0
      gameplay/src/Node.h
  37. 2 1
      gameplay/src/Package.cpp
  38. 15 11
      gameplay/src/PhysicsCharacter.cpp
  39. 8 1
      gameplay/src/PhysicsCollisionObject.cpp
  40. 0 1
      gameplay/src/PhysicsCollisionShape.h
  41. 85 7
      gameplay/src/PhysicsController.cpp
  42. 43 7
      gameplay/src/PhysicsController.h
  43. 1 0
      gameplay/src/PhysicsGhostObject.cpp
  44. 1 0
      gameplay/src/PhysicsGhostObject.h
  45. 2 2
      gameplay/src/PlatformQNX.cpp
  46. 1 1
      gameplay/src/PlatformWin32.cpp
  47. 1 1
      gameplay/src/SceneLoader.cpp
  48. 6 2
      gameplay/src/Slider.h
  49. 5 2
      gameplay/src/TextBox.h
  50. 5 5
      gameplay/src/VertexFormat.h
  51. 3 0
      gameplay/src/VerticalLayout.h
  52. 1 1
      gameplay/src/gameplay.h

+ 2 - 6
gameplay/gameplay.xcodeproj/project.pbxproj

@@ -567,8 +567,6 @@
 		5B2BC76A151251EB00D176CD /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
 		5B2BC76B151251EB00D176CD /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
 		5B2BC76C151251EB00D176CD /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
-		5B5ADCE214C22DF900AC6109 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = SDKs/MacOSX10.7.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
-		5B5ADCE414C22E1F00AC6109 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
 		5B5DB92D14C25B7B007755DB /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "../external-deps/bullet/lib/ios/i386/libbullet.a"; sourceTree = "<group>"; };
 		5B5DB92F14C25B94007755DB /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/ios/armv7/libpng.a"; sourceTree = "<group>"; };
 		5B5DB93114C25BA5007755DB /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libogg.a"; sourceTree = "<group>"; };
@@ -916,7 +914,6 @@
 			children = (
 				5B2BC766151251EB00D176CD /* CoreGraphics.framework */,
 				5B2BC767151251EB00D176CD /* Foundation.framework */,
-				5B2BC768151251EB00D176CD /* libz.dylib */,
 				5B2BC769151251EB00D176CD /* OpenAL.framework */,
 				5B2BC76A151251EB00D176CD /* OpenGLES.framework */,
 				5B2BC76B151251EB00D176CD /* QuartzCore.framework */,
@@ -929,7 +926,6 @@
 		5B04C5FE14BFE52F00EB0071 /* MacOSX */ = {
 			isa = PBXGroup;
 			children = (
-				5B2BC7631512516B00D176CD /* libz.dylib */,
 				5B2BC7611512514D00D176CD /* QuartzCore.framework */,
 				5B2BC75D1512514500D176CD /* OpenAL.framework */,
 				5B2BC75E1512514500D176CD /* OpenGL.framework */,
@@ -947,7 +943,7 @@
 				5B5DB93414C25BA5007755DB /* libvorbisfile.a */,
 				5B5DB92F14C25B94007755DB /* libpng.a */,
 				5B5DB92D14C25B7B007755DB /* libbullet.a */,
-				5B5ADCE414C22E1F00AC6109 /* libz.dylib */,
+				5B2BC768151251EB00D176CD /* libz.dylib */,
 			);
 			name = iOS;
 			sourceTree = "<group>";
@@ -955,7 +951,7 @@
 		5B5ADCE114C22DC700AC6109 /* MacOSX */ = {
 			isa = PBXGroup;
 			children = (
-				5B5ADCE214C22DF900AC6109 /* libz.dylib */,
+				5B2BC7631512516B00D176CD /* libz.dylib */,
 			);
 			name = MacOSX;
 			sourceTree = "<group>";

+ 12 - 1
gameplay/src/AbsoluteLayout.h

@@ -44,9 +44,20 @@ protected:
     void update(const Container* container);
 
 private:
-
+    
+    /*
+     * Constructor.
+     */
     AbsoluteLayout();
+    
+    /*
+     * Constructor.
+     */
     AbsoluteLayout(const AbsoluteLayout& copy);
+    
+    /*
+     * Destructor.
+     */
     virtual ~AbsoluteLayout();
 };
 

+ 5 - 14
gameplay/src/Animation.cpp

@@ -34,6 +34,8 @@ Animation::Animation(const char* id)
 
 Animation::~Animation()
 {
+    _channels.clear();
+
     if (_defaultClip)
     {
         if (_defaultClip->isClipStateBitSet(AnimationClip::CLIP_IS_PLAYING_BIT))
@@ -61,20 +63,15 @@ Animation::~Animation()
 Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
     : _animation(animation), _target(target), _propertyId(propertyId), _curve(curve), _duration(duration)
 {
-    _curve->addRef();
     // get property component count, and ensure the property exists on the AnimationTarget by getting the property component count.
     assert(_target->getAnimationPropertyComponentCount(propertyId));
 
-    _animation->addRef();
-
     _target->addChannel(this);
 }
 
 Animation::Channel::Channel(const Channel& copy, Animation* animation, AnimationTarget* target)
     : _animation(animation), _target(target), _propertyId(copy._propertyId), _curve(copy._curve), _duration(copy._duration)
-{
-    _curve->addRef();
-    _animation->addRef();
+{
     _target->addChannel(this);
 }
 
@@ -209,7 +206,7 @@ void Animation::createDefaultClip()
 }
 
 void Animation::createClips(Properties* animationProperties, unsigned int frameCount)
-{   
+{
     assert(animationProperties);
     
     Properties* pClip = animationProperties->getNextNamespace();
@@ -306,7 +303,6 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     SAFE_DELETE(normalizedKeyTimes);
 
     Channel* channel = new Channel(this, target, propertyId, curve, duration);
-    curve->release();
     addChannel(channel);
     return channel;
 }
@@ -343,7 +339,6 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     SAFE_DELETE(normalizedKeyTimes);
 
     Channel* channel = new Channel(this, target, propertyId, curve, duration);
-    curve->release();
     addChannel(channel);
     return channel;
 }
@@ -365,16 +360,13 @@ void Animation::removeChannel(Channel* channel)
         if (channel == chan) 
         {
             _channels.erase(itr);
-            itr = _channels.end();
+            return;
         }
         else
         {
             itr++;
         }
     }
-
-    if (_channels.empty())
-        _controller->destroyAnimation(this);
 }
 
 void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId)
@@ -396,7 +388,6 @@ void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId
 Animation* Animation::clone()
 {
     Animation* animation = new Animation(getId());
-    _controller->addAnimation(animation);
     return animation;
 }
 

+ 3 - 5
gameplay/src/Animation.h

@@ -22,7 +22,6 @@ class AnimationClip;
  */
 class Animation : public Ref
 {
-    friend class AnimationController;
     friend class AnimationClip;
     friend class AnimationTarget;
     friend class Package;
@@ -93,7 +92,7 @@ public:
      * Returns true if this animation targets the given AnimationTarget.
      */
     bool targets(AnimationTarget* target) const;
-
+    
 private:
 
     /**
@@ -104,7 +103,6 @@ private:
      */
     class Channel
     {
-        friend class AnimationController;
         friend class AnimationClip;
         friend class Animation;
         friend class AnimationTarget;
@@ -149,12 +147,12 @@ private:
      * Destructor.
      */
     ~Animation();
-
+    
     /**
      * Hidden copy assignment operator.
      */
     Animation& operator=(const Animation&);
-
+    
     /**
      * Creates the default clip.
      */

+ 4 - 3
gameplay/src/AnimationClip.h

@@ -36,6 +36,9 @@ public:
 
     public:
 
+        /*
+         * Constructor.
+         */
         Listener() 
         {
         }
@@ -225,9 +228,7 @@ public:
     void addListener(AnimationClip::Listener* listener, unsigned long eventTime);
 
 private:
-    /**
-     * State bits.
-     */
+    
     static const unsigned char CLIP_IS_PLAYING_BIT = 0x01;             // Bit representing whether AnimationClip is a running clip in AnimationController
     static const unsigned char CLIP_IS_STARTED_BIT = 0x02;             // Bit representing whether the AnimationClip has actually been started (ie: received first call to update())
     static const unsigned char CLIP_IS_FADING_OUT_STARTED_BIT = 0x04;  // Bit representing that a cross fade has started.

+ 1 - 303
gameplay/src/AnimationController.cpp

@@ -7,125 +7,12 @@ namespace gameplay
 {
 
 AnimationController::AnimationController()
-    : _state(STOPPED), _animations(NULL)
+    : _state(STOPPED)
 {
 }
 
 AnimationController::~AnimationController()
 {
-    std::vector<Animation*>::iterator itr = _animations.begin();
-    for ( ; itr != _animations.end(); itr++)
-    {
-        Animation* temp = *itr;
-        SAFE_RELEASE(temp);
-    }
-
-    _animations.clear();
-}
-
-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(keyCount >= 2 && keyTimes && keyValues && target);
-
-    Animation* animation = new Animation(id, target, propertyId, keyCount, keyTimes, keyValues, type);
-
-    addAnimation(animation);
-    
-    return animation;
-}
-
-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(target && keyCount >= 2 && keyTimes && keyValues && keyInValue && keyOutValue);
-    Animation* animation = new Animation(id, target, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
-
-    addAnimation(animation);
-
-    return animation;
-}
-
-Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, const char* animationFile)
-{
-    assert(target && animationFile);
-    
-    Properties* p = Properties::create(animationFile);
-    assert(p);
-
-    Animation* animation = createAnimation(id, target, p->getNextNamespace());
-
-    SAFE_DELETE(p);
-
-    return animation;
-}
-
-Animation* AnimationController::createAnimationFromTo(const char* id, AnimationTarget* target, int propertyId, float* from, float* to, Curve::InterpolationType type, unsigned long duration)
-{
-    const unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
-    float* keyValues = new float[2 * propertyComponentCount];
-
-    memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
-    memcpy(keyValues + propertyComponentCount, to, sizeof(float) * propertyComponentCount);
-
-    unsigned long* keyTimes = new unsigned long[2];
-    keyTimes[0] = 0;
-    keyTimes[1] = duration;
-
-    Animation* animation = createAnimation(id, target, propertyId, 2, keyTimes, keyValues, type);
-
-    SAFE_DELETE_ARRAY(keyValues);
-    SAFE_DELETE_ARRAY(keyTimes);
-    
-    return animation;
-}
-
-Animation* AnimationController::createAnimationFromBy(const char* id, AnimationTarget* target, int propertyId, float* from, float* by, Curve::InterpolationType type, unsigned long duration)
-{
-    const unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
-    float* keyValues = new float[2 * propertyComponentCount];
-
-    memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
-    memcpy(keyValues + propertyComponentCount, by, sizeof(float) * propertyComponentCount);
-
-    unsigned long* keyTimes = new unsigned long[2];
-    keyTimes[0] = 0;
-    keyTimes[1] = duration;
-
-    Animation* animation = createAnimation(id, target, propertyId, 2, keyTimes, keyValues, type);
-
-    SAFE_DELETE_ARRAY(keyValues);
-    SAFE_DELETE_ARRAY(keyTimes);
-
-    return animation;
-}
-
-Animation* AnimationController::getAnimation(const char* id) const
-{
-    unsigned int animationCount = _animations.size();
-    for (unsigned int i = 0; i < animationCount; i++)
-    {
-        if (_animations.at(i)->_id.compare(id) == 0)
-        {
-            return _animations.at(i);
-        }
-    }
-    return NULL;
-}
-
-Animation* AnimationController::getAnimation(AnimationTarget* target) const
-{
-    if (!target)
-        return NULL;
-    const unsigned int animationCount = _animations.size();
-    for (unsigned int i = 0; i < animationCount; ++i)
-    {
-        Animation* animation = _animations[i];
-        if (animation->targets(target))
-        {
-            return animation;
-        }
-    }
-    return NULL;
 }
 
 void AnimationController::stopAllAnimations() 
@@ -139,144 +26,6 @@ void AnimationController::stopAllAnimations()
     }
 }
 
-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 = (unsigned int)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 = (unsigned int)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 = (unsigned int)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 = (unsigned int)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;
@@ -385,55 +134,4 @@ void AnimationController::update(long elapsedTime)
         _state = IDLE;
 }
 
-void AnimationController::addAnimation(Animation* animation)
-{
-    _animations.push_back(animation);
-}
-
-void AnimationController::destroyAnimation(Animation* animation)
-{
-    assert(animation);
-
-    std::vector<Animation::Channel*>::iterator cItr = animation->_channels.begin();
-    for (; cItr != animation->_channels.end(); cItr++)
-    {
-        Animation::Channel* channel = *cItr;
-        channel->_target->deleteChannel(channel);
-    }
-
-    std::vector<Animation*>::iterator aItr = _animations.begin();
-    while (aItr != _animations.end())
-    {
-        if (animation == *aItr)
-        {
-            Animation* temp = *aItr;
-            SAFE_RELEASE(temp);
-            _animations.erase(aItr);
-            return;
-        }
-        aItr++;
-    }
-}
-
-void AnimationController::destroyAllAnimations()
-{
-    std::vector<Animation*>::iterator aItr = _animations.begin();
-    
-    while (aItr != _animations.end())
-    {
-        Animation* animation = *aItr;
-        std::vector<Animation::Channel*>::iterator cItr = animation->_channels.begin();
-        for (; cItr != animation->_channels.end(); cItr++)
-        {
-            Animation::Channel* channel = *cItr;
-            channel->_target->deleteChannel(channel);
-        }
-
-        SAFE_RELEASE(animation);
-        aItr++;
-    }
-
-    _animations.clear();
-}
-
 }

+ 5 - 119
gameplay/src/AnimationController.h

@@ -21,113 +21,16 @@ class AnimationController
 
 public:
 
-    /**
-     * Creates an animation on this target from a set of key value and key time pairs. 
-     * Cannot use Curve::BEZIER or CURVE::HERMITE as the interpolation type since they require tangents/control points.
-     * 
-     * @param id The ID of the animation.
-     * @param target The animation target.
-     * @param propertyId The property on this target to animate.
-     * @param keyCount The number of keyframes in the animation. Must be greater than one.
-     * @param keyTimes The list of key times for the animation (in milliseconds).
-     * @param keyValues The list of key values for the animation.
-     * @param type The curve interpolation type.
-     *
-     * @return The newly created animation.
-     */
-    Animation* createAnimation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, Curve::InterpolationType type);
-
-    /**
-     * Creates an animation on this target from a set of key value and key time pairs.
-     * 
-     * @param id The ID of the animation.
-     * @param target The animation target.
-     * @param propertyId The property on this target to animate.
-     * @param keyCount The number of keyframes in the animation. Must be greater than one.
-     * @param keyTimes The list of key times for the animation (in milliseconds).
-     * @param keyValues The list of key values for the animation.
-     * @param keyInValue The list of key in values for the animation.
-     * @param keyOutValue The list of key out values for the animation.
-     * @param type The curve interpolation type.
-     *
-     * @return The newly created animation.
-     */
-    Animation* createAnimation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type);
-
-    /**
-     * 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 animationFile The animation file defining the animation data.
-     *
-     * @return The newly created animation.
-     */
-    Animation* createAnimation(const char* id, AnimationTarget* target, const char* animationFile);
-
-    /**
-     * Creates a simple two keyframe from-to animation.
-     * Cannot use Curve::BEZIER or CURVE::HERMITE as the interpolation type since they require tangents/control points.
-     *
-     * @param id The ID of the animation.
-     * @param target The animation target.
-     * @param propertyId The property on this target to animate.
-     * @param from The values to animate from.
-     * @param to The values to animate to.
-     * @param type The curve interpolation type.
-     * @param duration The duration of the animation (in milliseconds).
-     *
-     * @return The newly created animation.
-     */
-    Animation* createAnimationFromTo(const char* id, AnimationTarget* target, int propertyId, float* from, float* to, Curve::InterpolationType type, unsigned long duration);
-
-    /**
-     * Creates a simple two keyframe from-by animation.
-     * Cannot use Curve::BEZIER or CURVE::HERMITE as the interpolation type since they require tangents/control points.
-     *
-     * @param id The ID of the animation.
-     * @param target The animation target.
-     * @param propertyId The property on this target to animate.
-     * @param from The values to animate from.
-     * @param by The values to animate by.
-     * @param type The curve interpolation type.
-     * @param duration The duration of the animation (in milliseconds).
-     *
-     * @return The newly created animation.
-     */
-    Animation* createAnimationFromBy(const char* id, AnimationTarget* target, int propertyId, float* from, float* by, Curve::InterpolationType type, unsigned long duration);
-
-    /**
-     * Finds the animation with the given ID.
-     *
-     * @param id The ID of the animation to get. NULL if the Animation is not found.
-     * 
-     * @return The animation, or NULL if not found.
-     */
-    Animation* getAnimation(const char* id) const;
-
-    /**
-     * Returns the first animation that targets the given AnimationTarget.
-     */
-    Animation* getAnimation(AnimationTarget* target) const;
-
     /** 
      * Stops all AnimationClips currently playing on the AnimationController.
      */
     void stopAllAnimations();
-
-    /**
-     * Removes the given animation from this AnimationTarget.
-     */
-    void destroyAnimation(Animation* animation);
-
-    /**
-     * Removes all animations from the AnimationTarget.
-     */ 
-    void destroyAllAnimations();
        
 private:
 
+    /**
+     * The states that the AnimationController may be in.
+     */
     enum State
     {
         RUNNING,
@@ -150,17 +53,6 @@ private:
      * Destructor.
      */
     ~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.
@@ -203,16 +95,10 @@ private:
      * Callback for when the controller receives a frame update event.
      */
     void update(long elapsedTime);
-
-    /**
-     * Adds an animation on this AnimationTarget.
-     */ 
-    void addAnimation(Animation* animation);
     
-    State _state;                               // The current state of the AnimationController.
-    std::list<AnimationClip*> _runningClips;    // A list of running AnimationClips.
+    State _state;                                 // The current state of the AnimationController.
+    std::list<AnimationClip*> _runningClips;      // A list of running AnimationClips.
     std::list<AnimationTarget*> _activeTargets;   // A list of animating AnimationTargets.
-    std::vector<Animation*> _animations;        // A list of animations registered with the AnimationController
 };
 
 }

+ 275 - 6
gameplay/src/AnimationTarget.cpp

@@ -29,12 +29,251 @@ AnimationTarget::~AnimationTarget()
     }
 }
 
-void AnimationTarget::addChannel(Animation::Channel* channel)
+Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, Curve::InterpolationType type)
 {
-    if (_animationChannels == NULL)
-        _animationChannels = new std::vector<Animation::Channel*>;
+    assert(type != Curve::BEZIER && type != Curve::HERMITE);
+    assert(keyCount >= 1 && keyTimes && keyValues);
 
-    _animationChannels->push_back(channel);
+    Animation* animation = new Animation(id, this, propertyId, keyCount, keyTimes, keyValues, type);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type)
+{
+    assert(keyCount >= 1 && keyTimes && keyValues && keyInValue && keyOutValue);
+    Animation* animation = new Animation(id, this, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimation(const char* id, const char* animationFile)
+{
+    assert(animationFile);
+    
+    Properties* p = Properties::create(animationFile);
+    assert(p);
+
+    Animation* animation = createAnimation(id, p->getNextNamespace());
+
+    SAFE_DELETE(p);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimationFromTo(const char* id, int propertyId, float* from, float* to, Curve::InterpolationType type, unsigned long duration)
+{
+    const unsigned int propertyComponentCount = getAnimationPropertyComponentCount(propertyId);
+    float* keyValues = new float[2 * propertyComponentCount];
+
+    memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
+    memcpy(keyValues + propertyComponentCount, to, sizeof(float) * propertyComponentCount);
+
+    unsigned long* keyTimes = new unsigned long[2];
+    keyTimes[0] = 0;
+    keyTimes[1] = duration;
+
+    Animation* animation = createAnimation(id, propertyId, 2, keyTimes, keyValues, type);
+
+    SAFE_DELETE_ARRAY(keyValues);
+    SAFE_DELETE_ARRAY(keyTimes);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimationFromBy(const char* id, int propertyId, float* from, float* by, Curve::InterpolationType type, unsigned long duration)
+{
+    const unsigned int propertyComponentCount = getAnimationPropertyComponentCount(propertyId);
+    float* keyValues = new float[2 * propertyComponentCount];
+
+    memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
+    memcpy(keyValues + propertyComponentCount, by, sizeof(float) * propertyComponentCount);
+
+    unsigned long* keyTimes = new unsigned long[2];
+    keyTimes[0] = 0;
+    keyTimes[1] = duration;
+
+    Animation* animation = createAnimation(id, propertyId, 2, keyTimes, keyValues, type);
+
+    SAFE_DELETE_ARRAY(keyValues);
+    SAFE_DELETE_ARRAY(keyTimes);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimation(const char* id, Properties* animationProperties)
+{
+    assert(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(_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 = (unsigned int)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 = (unsigned int)std::string::npos;
+    
+    int componentCount = 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 = (unsigned int)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 = (unsigned int)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, propertyId, keyCount, keyTimes, keyValues, keyIn, keyOut, (Curve::InterpolationType)curve);
+    }
+    else
+    {
+        animation = createAnimation(id, 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;
+}
+
+void AnimationTarget::destroyAnimation(const char* id)
+{
+    // Find the animation with the specified ID.
+    Animation::Channel* channel = getChannel(id);
+    if (channel == NULL)
+        return;
+
+    // Remove this target's channel from animation, and from the target's list of channels.
+    channel->_animation->removeChannel(channel);
+    removeChannel(channel);
+
+    SAFE_DELETE(channel);
+}
+
+Animation* AnimationTarget::getAnimation(const char* id) const
+{
+    if (_animationChannels)
+    {
+        std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
+
+        if (id == NULL)
+            return (*itr)->_animation;
+
+        Animation::Channel* channel = NULL;
+        for (; itr != _animationChannels->end(); itr++)
+        {
+            channel = (Animation::Channel*)(*itr);
+            if (channel->_animation->_id.compare(id) == 0)
+            {
+                return channel->_animation;
+            }
+        }
+    }
+
+    return NULL;
 }
 
 int AnimationTarget::getPropertyId(TargetType type, const char* propertyIdStr)
@@ -97,7 +336,15 @@ int AnimationTarget::getPropertyId(TargetType type, const char* propertyIdStr)
     return -1;
 }
 
-void AnimationTarget::deleteChannel(Animation::Channel* channel)
+void AnimationTarget::addChannel(Animation::Channel* channel)
+{
+    if (_animationChannels == NULL)
+        _animationChannels = new std::vector<Animation::Channel*>;
+
+    _animationChannels->push_back(channel);
+}
+
+void AnimationTarget::removeChannel(Animation::Channel* channel)
 {
     if (_animationChannels)
     {
@@ -107,7 +354,6 @@ void AnimationTarget::deleteChannel(Animation::Channel* channel)
             Animation::Channel* temp = *itr;
             if (channel == temp)
             {
-                SAFE_DELETE(channel);
                 _animationChannels->erase(itr);
 
                 if (_animationChannels->empty())
@@ -119,6 +365,29 @@ void AnimationTarget::deleteChannel(Animation::Channel* channel)
     }
 }
 
+Animation::Channel* AnimationTarget::getChannel(const char* id) const
+{
+    if (_animationChannels)
+    {
+        std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
+
+        if (id == NULL)
+            return (*itr);
+
+        Animation::Channel* channel = NULL;
+        for (; itr != _animationChannels->end(); itr++)
+        {
+            channel = (Animation::Channel*)(*itr);
+            if (channel->_animation->_id.compare(id) == 0)
+            {
+                return channel;
+            }
+        }
+    }
+
+    return NULL;
+}
+
 void AnimationTarget::cloneInto(AnimationTarget* target, NodeCloneContext &context) const
 {
     if (_animationChannels)

+ 115 - 5
gameplay/src/AnimationTarget.h

@@ -23,6 +23,100 @@ class AnimationTarget
 
 public:
 
+    /**
+     * Creates an animation on this target from a set of key value and key time pairs. 
+     * Cannot use Curve::BEZIER or CURVE::HERMITE as the interpolation type since they require tangents/control points.
+     * 
+     * @param id The ID of the animation.
+     * @param target The animation target.
+     * @param propertyId The property on this target to animate.
+     * @param keyCount The number of keyframes in the animation. Must be greater than one.
+     * @param keyTimes The list of key times for the animation (in milliseconds).
+     * @param keyValues The list of key values for the animation.
+     * @param type The curve interpolation type.
+     *
+     * @return The newly created animation.
+     */
+    Animation* createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, Curve::InterpolationType type);
+
+    /**
+     * Creates an animation on this target from a set of key value and key time pairs.
+     * 
+     * @param id The ID of the animation.
+     * @param target The animation target.
+     * @param propertyId The property on this target to animate.
+     * @param keyCount The number of keyframes in the animation. Must be greater than one.
+     * @param keyTimes The list of key times for the animation (in milliseconds).
+     * @param keyValues The list of key values for the animation.
+     * @param keyInValue The list of key in values for the animation.
+     * @param keyOutValue The list of key out values for the animation.
+     * @param type The curve interpolation type.
+     *
+     * @return The newly created animation.
+     */
+    Animation* createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type);
+
+    /**
+     * 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 animationFile The animation file defining the animation data.
+     *
+     * @return The newly created animation.
+     */
+    Animation* createAnimation(const char* id, const char* animationFile);
+
+    /**
+     * 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, Properties* animationProperties);
+
+    /**
+     * Creates a simple two keyframe from-to animation.
+     * Cannot use Curve::BEZIER or CURVE::HERMITE as the interpolation type since they require tangents/control points.
+     *
+     * @param id The ID of the animation.
+     * @param target The animation target.
+     * @param propertyId The property on this target to animate.
+     * @param from The values to animate from.
+     * @param to The values to animate to.
+     * @param type The curve interpolation type.
+     * @param duration The duration of the animation (in milliseconds).
+     *
+     * @return The newly created animation.
+     */
+    Animation* createAnimationFromTo(const char* id, int propertyId, float* from, float* to, Curve::InterpolationType type, unsigned long duration);
+
+    /**
+     * Creates a simple two keyframe from-by animation.
+     * Cannot use Curve::BEZIER or CURVE::HERMITE as the interpolation type since they require tangents/control points.
+     *
+     * @param id The ID of the animation.
+     * @param target The animation target.
+     * @param propertyId The property on this target to animate.
+     * @param from The values to animate from.
+     * @param by The values to animate by.
+     * @param type The curve interpolation type.
+     * @param duration The duration of the animation (in milliseconds).
+     *
+     * @return The newly created animation.
+     */
+    Animation* createAnimationFromBy(const char* id, int propertyId, float* from, float* by, Curve::InterpolationType type, unsigned long duration);
+
+    /**
+     * Destroys the animation with the specified ID. Destroys the first animation if ID is NULL.
+     *
+     * @param The animation to destroy.
+     */ 
+    void destroyAnimation(const char* id = NULL);
+
     /**
      * Abstract method to return the property component count of the given property ID on the AnimationTarget.
      * 
@@ -49,8 +143,18 @@ public:
      */
     virtual void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f) = 0;
 
+    /** 
+     * Gets the animation with the specified ID. If the ID is NULL, this function will return the first animation it finds.
+     *
+     * @param id The name of the animation to get.
+     */
+    Animation* getAnimation(const char* id = NULL) const;
+
 protected:
     
+    /**
+     * The type of animation target. 
+     */
     enum TargetType
     {
         SCALAR,
@@ -75,11 +179,18 @@ protected:
     void addChannel(Animation::Channel* channel);
 
     /**
-     * Deletes the given animation channel from this animation target.
+     * Removes the given animation channel from this animation target.
      * 
      * @param channel The animation channel to delete.
      */
-    void deleteChannel(Animation::Channel* channel);
+    void removeChannel(Animation::Channel* channel);
+
+    /**
+     * Gets the Animation::Channel that belongs to the Animation with the specified ID.
+     *
+     * @param id The ID of the Animation the Channel belongs to.
+     */
+    Animation::Channel* getChannel(const char* id) const;
 
     /**
      * Copies data from this animation target into the given target for the purpose of cloning.
@@ -89,9 +200,8 @@ protected:
      */
     void cloneInto(AnimationTarget* target, NodeCloneContext &context) const;
 
-    TargetType _targetType;             // The type of target this is.
-
-    unsigned char _animationPropertyBitFlag;     // Bit flag used to indicate which properties on the AnimationTarget are currently animating.
+    TargetType _targetType;                     // The type of target this is.
+    unsigned char _animationPropertyBitFlag;    // Bit flag used to indicate which properties on the AnimationTarget are currently animating.
 
 private:
 

+ 2 - 1
gameplay/src/AudioBuffer.h

@@ -11,13 +11,14 @@ class AudioSource;
 /**
  * The actual audio buffer data.
  *
- * Currently only supports OpenAL supported formats: .wav, .au and .raw files.
+ * Currently only supports supported formats: .wav, .au and .raw files.
  */
 class AudioBuffer : public Ref
 {
     friend class AudioSource;
 
 private:
+    
 #ifndef __ANDROID__
     /**
      * Constructor.

+ 0 - 3
gameplay/src/AudioSource.h

@@ -152,16 +152,13 @@ private:
      * Constructor that takes an AudioBuffer.
      */
     AudioSource(AudioBuffer* buffer, ALuint source);
-
 #else
-
     /**
      * Constructor that takes an AudioBuffer.
      */
     AudioSource(AudioBuffer* buffer, const SLObjectItf& player);
 #endif
 
-
     /**
      * Destructor.
      */

+ 0 - 2
gameplay/src/Base.h

@@ -168,7 +168,6 @@ extern void printError(const char* format, ...);
 #include <SLES/OpenSLES.h>
 #include <SLES/OpenSLES_Android.h>
 #else
-
 #ifdef __QNX__
 #include <AL/al.h>
 #include <AL/alc.h>
@@ -179,7 +178,6 @@ extern void printError(const char* format, ...);
 #include <OpenAL/al.h>
 #include <OpenAL/alc.h>
 #endif
-
 #include <vorbis/vorbisfile.h>
 #endif
 

+ 4 - 1
gameplay/src/Button.h

@@ -10,7 +10,7 @@ namespace gameplay
 {
 
 /**
- * Defines a button UI control.  This is essentially a label that can have a callback method set on it.
+ * Defines a button UI control. This is essentially a label that can have a callback method set on it.
  *
  * The following properties are available for buttons:
  *
@@ -64,6 +64,9 @@ protected:
 
 private:
 
+    /*
+     * Constructor.
+     */
     Button(const Button& copy);
 };
 

+ 0 - 1
gameplay/src/Camera.h

@@ -250,7 +250,6 @@ private:
      * Clones the camera and returns a new camera.
      * 
      * @param context The clone context.
-     * 
      * @return The newly created camera.
      */
     Camera* clone(NodeCloneContext &context) const;

+ 4 - 1
gameplay/src/CheckBox.h

@@ -16,7 +16,7 @@ namespace gameplay
  *
  * checkBox <checkBoxID>
  * {
- *      style       = <Style ID>
+ *      style       = <styleID>
  *      position    = <x, y>
  *      size        = <width, height>
  *      text        = <string>
@@ -121,6 +121,9 @@ protected:
 
 private:
 
+    /*
+     * Constructor.
+     */
     CheckBox(const CheckBox& copy);
 };
 

+ 24 - 0
gameplay/src/Container.cpp

@@ -202,6 +202,30 @@ namespace gameplay
         return _controls;
     }
 
+    Animation* Container::getAnimation(const char* id) const
+    {
+        std::vector<Control*>::const_iterator itr = _controls.begin();
+        std::vector<Control*>::const_iterator end = _controls.end();
+        
+        Control* control = NULL;
+        for (; itr != end; itr++)
+        {
+            control = *itr;
+            Animation* animation = control->getAnimation(id);
+            if (animation)
+                return animation;
+
+            if (control->isContainer())
+            {
+                animation = ((Container*)control)->getAnimation(id);
+                if (animation)
+                    return animation;
+            }
+        }
+
+        return NULL;
+    }
+
     void Container::update(const Rectangle& clip)
     {
         // Update this container's viewport.

+ 20 - 9
gameplay/src/Container.h

@@ -12,23 +12,26 @@ namespace gameplay
  *
  * The following properties are available for containers:
  *
- * container <Container ID>
+ * container <containerID>
  * {
  *      // Container properties.
- *      layout   = <Layout Type>        // A value from the Layout::Type enum.  E.g.: LAYOUT_VERTICAL
- *      style    = <Style ID>           // A style from the form's theme.
+ *      layout   = <Layout::Type>        // A value from the Layout::Type enum.  E.g.: LAYOUT_VERTICAL
+ *      style    = <styleID>           // A style from the form's theme.
  *      position = <x, y>               // Position of the container on-screen, measured in pixels.
  *      size     = <width, height>      // Size of the container, measured in pixels.
  *   
  *      // All the nested controls within this container.
- *      container { }
-
+ *      container 
+ *      { 
+ *          ...
+ *      }
+ * 
  *      label { }
  *      textBox { }
- *      button{}
- *      checkBox{}
- *      radioButton{}
- *      slider{}
+ *      button { }
+ *      checkBox { }
+ *      radioButton { }
+ *      slider { }
  * }
  */
 class Container : public Control
@@ -104,6 +107,14 @@ public:
      */
     std::vector<Control*> getControls() const;
 
+    /**
+     * Gets the first animation in the control with the specified ID.
+     *
+     * @param id The ID of the animation to get. Returns the first animation if ID is NULL.
+     * @return The first animation with the specified ID.
+     */
+    Animation* getAnimation(const char* id = NULL) const;
+
 protected:
 
     /**

+ 18 - 17
gameplay/src/Control.h

@@ -722,23 +722,35 @@ protected:
 
 private:
 
-    // Animation blending bits.
     static const char ANIMATION_POSITION_X_BIT = 0x01;
     static const char ANIMATION_POSITION_Y_BIT = 0x02;
     static const char ANIMATION_SIZE_WIDTH_BIT = 0x04;
     static const char ANIMATION_SIZE_HEIGHT_BIT = 0x08;
     static const char ANIMATION_OPACITY_BIT = 0x10;
 
-    bool _styleOverridden;
-
+    /*
+     * Constructor.
+     */    
+    Control(const Control& copy);
+    
     void applyAnimationValuePositionX(float x, float blendWeight);
+    
     void applyAnimationValuePositionY(float y, float blendWeight);
+    
     void applyAnimationValueSizeWidth(float width, float blendWeight);
+    
     void applyAnimationValueSizeHeight(float height, float blendWeight);
+    
     void applyAnimationValueOpacity();
 
-    Control(const Control& copy);
+    Theme::Style::Overlay** getOverlays(unsigned char overlayTypes, Theme::Style::Overlay** overlays);
 
+    Theme::Style::Overlay* getOverlay(Control::State state) const;
+
+    void overrideStyle();
+    
+    void addSpecificListener(Control::Listener* listener, Listener::EventType eventType);
+    
     /**
      * Draws the themed border and background of a control.
      *
@@ -746,19 +758,8 @@ private:
      * @param clip The clipping rectangle of this control's parent container.
      */
     virtual void drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip);
-
-    void addSpecificListener(Control::Listener* listener, Listener::EventType eventType);
-
-    // Gets the overlays requested in the overlayTypes bitflag.
-    Theme::Style::Overlay** getOverlays(unsigned char overlayTypes, Theme::Style::Overlay** overlays);
-
-    /**
-     * Gets an overlay from a control state.
-     */
-    Theme::Style::Overlay* getOverlay(Control::State state) const;
-
-    // Ensures that this control has a copy of its style so that it can override it without affecting other controls.
-    void overrideStyle();
+    
+    bool _styleOverridden;
 };
 
 }

+ 3 - 2
gameplay/src/Curve.cpp

@@ -119,7 +119,7 @@ void Curve::setPoint(unsigned int index, float time, float* value, Interpolation
 
 void Curve::setPoint(unsigned int index, float time, float* value, InterpolationType type, float* inValue, float* outValue)
 {
-    assert(index < _pointCount && time >= 0.0f && time <= 1.0f && !(index == 0 && time != 0.0f) && !(index == _pointCount - 1 && time != 1.0f));
+    //assert(index < _pointCount && time >= 0.0f && time <= 1.0f && !(index == 0 && time != 0.0f) && !(index == _pointCount - 1 && time != 1.0f));
 
     _points[index].time = time;
     _points[index].type = type;
@@ -151,8 +151,9 @@ void Curve::evaluate(float time, float* dst) const
 {
     assert(dst && time >= 0 && time <= 1.0f);
 
+    // Check if the point count is 1.
     // Check if we are at or beyond the bounds of the curve.
-    if (time <= _points[0].time)
+    if (_pointCount == 1 || time <= _points[0].time)
     {
         memcpy(dst, _points[0].value, _componentSize);
         return;

+ 3 - 2
gameplay/src/Curve.h

@@ -11,6 +11,7 @@ namespace gameplay
  */
 class Curve : public Ref
 {
+    friend class AnimationTarget;
     friend class Animation;
     friend class AnimationClip;
     friend class AnimationController;
@@ -400,7 +401,7 @@ private:
     Curve(unsigned int pointCount, unsigned int componentCount);
 
     /**
-     * Hidden copy constructor.
+     * Constructor.
      */
     Curve(const Curve& copy);
 
@@ -410,7 +411,7 @@ private:
     ~Curve();
 
     /**
-     * Hidden copy assignment operator.
+     * Copy assignment operator.
      */
     Curve& operator=(const Curve&);
 

+ 1 - 0
gameplay/src/DebugNew.h

@@ -90,6 +90,7 @@ T* bullet_new(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
 }
 
 #if defined(WIN32)
+
 /**
  * Sets whether stack traces are tracked on memory allocations or not.
  * 

+ 23 - 0
gameplay/src/FlowLayout.h

@@ -6,16 +6,39 @@
 namespace gameplay
 {
 
+/**
+ *  Defines a Layout for forms and containers that arranges controls 
+ * in a left-to-right(default) or right-to-left flow.
+ */
 class FlowLayout : public Layout
 {
 public:
+
+    /**
+     * Constructor.
+     */
     static FlowLayout* create();
 
+    /**
+     * Sets if the layout is left-to-right or right to left.
+     */
     void setRightToLeft(bool rightToLeft);
 
 private:
+    
+    /**
+     * Constructor.
+     */
     FlowLayout();
+    
+    /**
+     * Constructor.
+     */
     FlowLayout(const FlowLayout& copy);
+    
+    /**
+     * Destructor.
+     */
     virtual ~FlowLayout();
 };
 

+ 1 - 4
gameplay/src/Font.h

@@ -202,7 +202,7 @@ private:
     Font();
 
     /**
-     * Copy constructor.
+     * Constructor.
      */
     Font(const Font& copy);
 
@@ -211,16 +211,13 @@ private:
      */
     ~Font();
 
-    // Used by both getIndexAtLocation and getLocationAtIndex.
     unsigned int getIndexOrLocation(const char* text, const Rectangle& clip, unsigned int size, const Vector2& inLocation, Vector2* outLocation,
                                     const int destIndex = -1, Justify justify = ALIGN_TOP_LEFT, bool wrap = true, bool rightToLeft = false);
 
-    // Utilities
     unsigned int getTokenWidth(const char* token, unsigned int length, unsigned int size, float scale);
 
     unsigned int getReversedTokenLength(const char* token, const char* bufStart);
 
-    // Returns 0 if EOF was reached, 1 if delimiters were handles correctly, and 2 if the stopAtPosition was reached while handling delimiters.
     int handleDelimiters(const char** token, const unsigned int size, const int iteration, const int areaX, int* xPos, int* yPos, unsigned int* lineLength,
                          std::vector<int>::const_iterator* xPositionsIt, std::vector<int>::const_iterator xPositionsEnd, unsigned int* charIndex = NULL,
                          const Vector2* stopAtPosition = NULL, const int currentIndex = -1, const int destIndex = -1);

+ 11 - 8
gameplay/src/Form.h

@@ -27,17 +27,20 @@ public:
      * Create from properties file.
      * The top-most namespace in the file must be named 'form'.  The following properties are available for forms:
      *
-     * form <Form ID>
+     * form <formID>
      * {
      *      // Form properties.
-     *      theme    = <Path to Theme File> // See Theme.h.
-     *      layout   = <Layout Type>        // A value from the Layout::Type enum.  E.g.: LAYOUT_VERTICAL
-     *      style    = <Style ID>           // A style from the referenced theme.
-     *      position = <x, y>               // Position of the form on-screen, measured in pixels.
-     *      size     = <width, height>      // Size of the form, measured in pixels.
+     *      theme    = <Path to .theme File>    // See Theme.h.
+     *      layout   = <Layout::Type>           // A value from the Layout::Type enum.  e.g.: LAYOUT_VERTICAL
+     *      style    = <styleID>                // A style from the referenced theme.
+     *      position = <x, y>                   // Position of the form on-screen, measured in pixels.
+     *      size     = <width, height>          // Size of the form, measured in pixels.
      *   
-     *      // All the controls within this form.
-     *      container { }
+     *      // All the nested controls within this form.
+     *      container 
+     *      {
+     *          ...
+     *      }
      *      label { }
      *      textBox { }
      *      button { }

+ 4 - 1
gameplay/src/FrameBuffer.h

@@ -99,10 +99,13 @@ public:
      
 private:
  
+    /**
+     * Constructor.
+     */
     FrameBuffer(const char* id);
 
     /**
-     * Destructor.  Removes this FrameBuffer from the list of available FrameBuffers.
+     * Destructor.
      */
     ~FrameBuffer();
 

+ 2 - 2
gameplay/src/Joint.h

@@ -77,12 +77,12 @@ protected:
 private:
 
     /**
-     * Hidden copy constructor.
+     * Constructor.
      */
     Joint(const Joint& copy);
 
     /**
-     * Hidden copy assignment operator.
+     * Copy assignment operator.
      */
     Joint& operator=(const Joint&);
 

+ 5 - 2
gameplay/src/Label.h

@@ -12,9 +12,9 @@ namespace gameplay
  *
  * The following properties are available for labels:
  *
- * label <Label ID>
+ * label <labelID>
  * {
- *      style       = <Style ID>
+ *      style       = <styleID>
  *      position    = <x, y>
  *      size        = <width, height>
  *      text        = <string>
@@ -90,6 +90,9 @@ protected:
 
 private:
 
+    /**
+     * Constructor.
+     */
     Label(const Label& copy);
 };
 

+ 1 - 3
gameplay/src/Light.h

@@ -12,7 +12,6 @@ class NodeCloneContext;
 
 /**
  * Defines a light.
- *
  */
 class Light : public Ref
 {
@@ -30,7 +29,6 @@ public:
         SPOT = 3
     };
 
-
     /**
      * Creates a directional light.
      * 
@@ -158,7 +156,6 @@ public:
      */
     float getOuterAngleCos() const;
 
-
 private:
 
     /**
@@ -234,6 +231,7 @@ private:
     Light* clone(NodeCloneContext &context) const;
 
     Light::Type _type;
+    
     union
     {
         Directional* _directional;

+ 6 - 5
gameplay/src/Material.h

@@ -23,6 +23,7 @@ class Material : public RenderState
     friend class Technique;
     friend class Pass;
     friend class RenderState;
+    friend class Node;
 
 public:
 
@@ -133,14 +134,14 @@ private:
     Material();
 
     /**
-     * Destructor.
+     * Constructor.
      */
-    ~Material();
-
+    Material(const Material& m);
+    
     /**
-     * Hidden copy constructor.
+     * Destructor.
      */
-    Material(const Material& m);
+    ~Material();
 
     /**
      * Loads a technique from the given properties object into the specified material.

+ 18 - 23
gameplay/src/MaterialParameter.h

@@ -168,6 +168,18 @@ public:
 
 private:
 
+    static const char ANIMATION_UNIFORM_BIT = 0x01;
+    
+    /**
+     * Constructor.
+     */
+    MaterialParameter(const char* name);
+    
+    /**
+     * Destructor.
+     */
+    ~MaterialParameter();
+    
     /**
      * Interface implemented by templated method bindings for simple storage and iteration.
      */
@@ -218,20 +230,14 @@ private:
         CountMethod _countMethod;
     };
 
-    /**
-     * Constructor.
-     */
-    MaterialParameter(const char* name);
-
-    /**
-     * Destructor.
-     */
-    ~MaterialParameter();
-
     void clearValue();
 
     void bind(Effect* effect);
 
+    void applyAnimationValue(AnimationValue* value, float blendWeight, int components);
+
+    void cloneInto(MaterialParameter* materialParameter) const;
+    
     union
     {
         float floatValue;
@@ -241,7 +247,7 @@ private:
         const Texture::Sampler* samplerValue;
         MethodBinding* method;
     } _value;
-
+    
     enum
     {
         NONE,
@@ -254,18 +260,7 @@ private:
         SAMPLER,
         METHOD
     } _type;
-
-    static const char ANIMATION_UNIFORM_BIT = 0x01;
-
-    void applyAnimationValue(AnimationValue* value, float blendWeight, int components);
-
-    /**
-     * Copies the data from this MaterialParameter into the given MaterialParameter.
-     * 
-     * @param materialParameter The MaterialParameter to copy the data to.
-     */
-    void cloneInto(MaterialParameter* materialParameter) const;
-
+    
     unsigned int _count;
     bool _dynamic;
     std::string _name;

+ 0 - 2
gameplay/src/Mesh.h

@@ -299,8 +299,6 @@ private:
 
     /**
      * Constructor.
-     *
-     * @param copy The mesh to copy from.
      */
     Mesh(const Mesh& copy);
 

+ 6 - 0
gameplay/src/MeshBatch.h

@@ -111,8 +111,14 @@ public:
 
 private:
 
+    /**
+     * Constructor.
+     */
     MeshBatch(const VertexFormat& vertexFormat, Mesh::PrimitiveType primitiveType, Material* material, bool indexed, unsigned int initialCapacity, unsigned int growSize);
 
+    /**
+     * Constructor.
+     */
     MeshBatch(const MeshBatch& copy);
 
     void updateVertexAttributeBinding();

+ 3 - 2
gameplay/src/MeshSkin.h

@@ -117,7 +117,7 @@ private:
     MeshSkin();
 
     /**
-     * Hidden copy constructor.
+     * Constructor.
      */
     MeshSkin(const MeshSkin&);
 
@@ -127,7 +127,7 @@ private:
     ~MeshSkin();
     
     /**
-     * Hidden copy assignment operator.
+     * Copy assignment operator.
      */
     MeshSkin& operator=(const MeshSkin&);
 
@@ -169,6 +169,7 @@ private:
     Matrix _bindShape;
     std::vector<Joint*> _joints;
     Joint* _rootJoint;
+    
     // Pointer to the root node of the mesh skin.
     // The purpose is so that the joint hierarchy doesn't need to be in the scene.
     // If the joints are not in the scene then something has to hold a reference to it.

+ 0 - 1
gameplay/src/Model.h

@@ -182,7 +182,6 @@ private:
      * Clones the model and returns a new model.
      * 
      * @param context The clone context.
-     * 
      * @return The new cloned model.
      */
     Model* clone(NodeCloneContext &context);

+ 63 - 0
gameplay/src/Node.cpp

@@ -594,6 +594,69 @@ void Node::setBoundsDirty()
         _parent->setBoundsDirty();
 }
 
+Animation* Node::getAnimation(const char* id) const
+{
+    Animation* animation = ((AnimationTarget*)this)->getAnimation(id);
+    if (animation)
+        return animation;
+    
+    // See if this node has a model, then drill down.
+    Model* model = this->getModel();
+    if (model)
+    {
+        // Check to see if there's any animations with the ID on the joints.
+        MeshSkin* skin = model->getSkin();
+        if (skin)
+        {
+            Joint* rootJoint = skin->getRootJoint();
+            if (rootJoint)
+            {
+                animation = rootJoint->getAnimation(id);
+                if (animation)
+                    return animation;
+            }
+        }
+
+        // Check to see if any of the model's material parameter's has an animation
+        // with the given ID.
+        Material* material = model->getMaterial();
+        if (material)
+        {
+            // How to access material parameters? hidden on the Material::RenderState.
+            std::vector<MaterialParameter*>::iterator itr = material->_parameters.begin();
+            for (; itr != material->_parameters.end(); itr++)
+            {
+                animation = ((MaterialParameter*)(*itr))->getAnimation(id);
+                if (animation)
+                    return animation;
+            }
+        }
+    }
+
+    // look through form for animations.
+    Form* form = this->getForm();
+    if (form)
+    {
+        animation = form->getAnimation(id);
+        if (animation)
+            return animation;
+    }
+
+    // Look through this node's children for an animation with the specified ID.
+    unsigned int childCount = this->getChildCount();
+    Node* child = this->getFirstChild();
+    for (unsigned int i = 0; i < childCount; i++)
+    {
+        animation = child->getAnimation(id);
+        if (animation)
+            return animation;
+
+        child = child->getNextSibling();
+    }
+    
+    return NULL;
+}
+
 Camera* Node::getCamera() const
 {
     return _camera;

+ 8 - 0
gameplay/src/Node.h

@@ -343,6 +343,14 @@ public:
      */
     Vector3 getActiveCameraTranslationView() const;
 
+    /**
+     * Gets the first animation in the node hierarchy with the specified ID.
+     *
+     * @param id The ID of the animation to get. Returns the first animation if ID is NULL.
+     * @return The first animation with the specified ID.
+     */
+    Animation* getAnimation(const char* id = NULL) const;
+
     /**
      * Returns the pointer to this node's camera.
      *

+ 2 - 1
gameplay/src/Package.cpp

@@ -964,11 +964,12 @@ Animation* Package::readAnimationChannel(Scene* scene, Animation* animation, con
         if (animation == NULL)
         {
             // TODO: This code currently assumes LINEAR only
-            animation = controller->createAnimation(animationId, target, targetAttribute, keyTimesCount, &keyTimes[0], &values[0], Curve::LINEAR);
+            animation = target->createAnimation(animationId, targetAttribute, keyTimesCount, &keyTimes[0], &values[0], Curve::LINEAR);
         }
         else
         {
             animation->createChannel(target, targetAttribute, keyTimesCount, &keyTimes[0], &values[0], Curve::LINEAR);
+            animation->addRef();
         }
     }
 

+ 15 - 11
gameplay/src/PhysicsCharacter.cpp

@@ -17,15 +17,17 @@ class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexR
 {
 public:
 
-    ClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
+    ClosestNotMeConvexResultCallback(PhysicsCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
         : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), _me(me), _up(up), _minSlopeDot(minSlopeDot)
     {
     }
 
     btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
     {
-        if (convexResult.m_hitCollisionObject == _me)
-            return btScalar(1.0);
+        PhysicsCollisionObject* object = reinterpret_cast<PhysicsCollisionObject*>(convexResult.m_hitCollisionObject->getUserPointer());
+
+        if (object == _me || object->getType() == PhysicsCollisionObject::GHOST_OBJECT)
+            return 1.0f;
 
         /*
         btVector3 hitNormalWorld;
@@ -50,7 +52,7 @@ public:
 
 protected:
 
-    btCollisionObject* _me;
+    PhysicsCollisionObject* _me;
     const btVector3 _up;
     btScalar _minSlopeDot;
 };
@@ -64,7 +66,7 @@ PhysicsCharacter::PhysicsCharacter(Node* node, const PhysicsCollisionShape::Defi
     setMaxSlopeAngle(45.0f);
 
     // Set the collision flags on the ghost object to indicate it's a character
-    _ghostObject->setCollisionFlags(_ghostObject->getCollisionFlags() | btCollisionObject::CF_CHARACTER_OBJECT);
+    _ghostObject->setCollisionFlags(_ghostObject->getCollisionFlags() | btCollisionObject::CF_CHARACTER_OBJECT | btCollisionObject::CF_NO_CONTACT_RESPONSE);
 
     // Register ourselves as an action on the physics world so we are called back during physics ticks
     Game::getInstance()->getPhysicsController()->_world->addAction(this);
@@ -365,7 +367,6 @@ void PhysicsCharacter::updateAction(btCollisionWorld* collisionWorld, btScalar d
     // dynamic objects (i.e. objects that moved and now intersect the character).
     if (_physicsEnabled)
     {
-        //_colliding = fixCollision(collisionWorld);
         _colliding = false;
         int stepCount = 0;
         while (fixCollision(collisionWorld))
@@ -495,7 +496,7 @@ void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, fl
 
         btVector3 sweepDirNegative(_currentPosition - targetPosition);
 
-        ClosestNotMeConvexResultCallback callback(_ghostObject, sweepDirNegative, btScalar(0.0));
+        ClosestNotMeConvexResultCallback callback(this, sweepDirNegative, btScalar(0.0));
         callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
         callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
 
@@ -556,7 +557,7 @@ void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
     start.setOrigin(_currentPosition);
     end.setOrigin(targetPosition);
 
-    ClosestNotMeConvexResultCallback callback(_ghostObject, btVector3(0, 1, 0), _cosSlopeAngle);
+    ClosestNotMeConvexResultCallback callback(this, btVector3(0, 1, 0), _cosSlopeAngle);
     callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
     callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
 
@@ -661,6 +662,12 @@ bool PhysicsCharacter::fixCollision(btCollisionWorld* world)
             // Get the direction of the contact points (used to scale normal vector in the correct direction).
             btScalar directionSign = manifold->getBody0() == _ghostObject ? -1.0f : 1.0f;
 
+            // Skip ghost objects
+            PhysicsCollisionObject* object = Game::getInstance()->getPhysicsController()->getCollisionObject(
+                (btCollisionObject*)(manifold->getBody0() == _ghostObject ? manifold->getBody1() : manifold->getBody0()));
+            if (!object || object->getType() == PhysicsCollisionObject::GHOST_OBJECT)
+                continue;
+
             for (int p = 0, contactCount = manifold->getNumContacts(); p < contactCount; ++p)
             {
                 const btManifoldPoint& pt = manifold->getContactPoint(p);
@@ -678,14 +685,11 @@ bool PhysicsCharacter::fixCollision(btCollisionWorld* world)
                         _collisionNormal = pt.m_normalWorldOnB * directionSign;
                     }
 
-                    //Node* node = Game::getInstance()->getPhysicsController()->getCollisionObject((btCollisionObject*)(manifold->getBody0() == _ghostObject ? manifold->getBody1() : manifold->getBody0()))->getNode();
-
                     // Calculate new position for object, which is translated back along the collision normal
                     currentPosition += pt.m_normalWorldOnB * directionSign * dist * 0.2f;
                     collision = true;
                 }
             }
-            //manifold->clearManifold();
         }
     }
 

+ 8 - 1
gameplay/src/PhysicsCollisionObject.cpp

@@ -54,7 +54,14 @@ PhysicsMotionState* PhysicsCollisionObject::getMotionState() const
 
 bool PhysicsCollisionObject::isKinematic() const
 {
-    return getCollisionObject()->isKinematicObject();
+    switch (getType())
+    {
+    case GHOST_OBJECT:
+    case CHARACTER:
+        return true;
+    default:
+        return getCollisionObject()->isKinematicObject();
+    }
 }
 
 bool PhysicsCollisionObject::isDynamic() const

+ 0 - 1
gameplay/src/PhysicsCollisionShape.h

@@ -214,7 +214,6 @@ private:
      */
     ~PhysicsCollisionShape();
 
-
     // Shape type
     Type _type;
 

+ 85 - 7
gameplay/src/PhysicsController.cpp

@@ -134,22 +134,100 @@ void PhysicsController::drawDebug(const Matrix& viewProjection)
     _debugDrawer->end();
 }
 
-PhysicsCollisionObject* PhysicsController::rayTest(const Ray& ray, float distance, Vector3* hitPoint, float* hitFraction)
+bool PhysicsController::rayTest(const Ray& ray, float distance, PhysicsController::HitResult* result)
 {
     btCollisionWorld::ClosestRayResultCallback callback(BV(ray.getOrigin()), BV(distance * ray.getDirection()));
     _world->rayTest(BV(ray.getOrigin()), BV(distance * ray.getDirection()), callback);
     if (callback.hasHit())
     {
-        if (hitPoint)
-            hitPoint->set(callback.m_hitPointWorld.x(), callback.m_hitPointWorld.y(), callback.m_hitPointWorld.z());
+        if (result)
+        {
+            result->object = getCollisionObject(callback.m_collisionObject);
+            result->point.set(callback.m_hitPointWorld.x(), callback.m_hitPointWorld.y(), callback.m_hitPointWorld.z());
+            result->fraction = callback.m_closestHitFraction;
+            result->normal.set(callback.m_hitNormalWorld.x(), callback.m_hitNormalWorld.y(), callback.m_hitNormalWorld.z());
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+bool PhysicsController::sweepTest(PhysicsCollisionObject* object, const Vector3& endPosition, PhysicsController::HitResult* result)
+{
+    class SweepTestCallback : public btCollisionWorld::ClosestConvexResultCallback
+    {
+    public:
 
-        if (hitFraction)
-            *hitFraction = callback.m_closestHitFraction;
+	    SweepTestCallback(PhysicsCollisionObject* me)
+            : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), me(me)
+	    {
+	    }
+
+	    btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
+	    {
+            PhysicsCollisionObject* object = reinterpret_cast<PhysicsCollisionObject*>(convexResult.m_hitCollisionObject->getUserPointer());
+
+		    if (object == me)
+			    return 1.0f;
+
+		    return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
+	    }
+
+	    PhysicsCollisionObject* me;
+    };
+
+    PhysicsCollisionShape* shape = object->getCollisionShape();
+    PhysicsCollisionShape::Type type = shape->getType();
+    if (type != PhysicsCollisionShape::SHAPE_BOX && type != PhysicsCollisionShape::SHAPE_SPHERE && type != PhysicsCollisionShape::SHAPE_CAPSULE)
+        return false; // unsupported type
+
+    // Define the start transform
+    btTransform start;
+    if (object->getNode())
+        start.setFromOpenGLMatrix(object->getNode()->getWorldMatrix().m);
+    else
+        start.setIdentity();
+
+    // Define the end transform
+    btTransform end(start);
+    end.setOrigin(BV(endPosition));
+
+    // Perform bullet convex sweep test
+    SweepTestCallback callback(object);
+
+    // If the object is represented by a ghost object, use the ghost object's convex sweep test
+    // since it is much faster than the world's version.
+    /*switch (object->getType())
+    {
+    case PhysicsCollisionObject::GHOST_OBJECT:
+    case PhysicsCollisionObject::CHARACTER:
+        static_cast<PhysicsGhostObject*>(object)->_ghostObject->convexSweepTest(static_cast<btConvexShape*>(shape->getShape()), start, end, callback, _world->getDispatchInfo().m_allowedCcdPenetration);
+        break;
+
+    default:
+        _world->convexSweepTest(static_cast<btConvexShape*>(shape->getShape()), start, end, callback, _world->getDispatchInfo().m_allowedCcdPenetration);
+        break;
+    }
+    */
+    _world->convexSweepTest(static_cast<btConvexShape*>(shape->getShape()), start, end, callback, _world->getDispatchInfo().m_allowedCcdPenetration);
+
+    // Check for hits and store results
+    if (callback.hasHit())
+    {
+        if (result)
+        {
+            result->object = getCollisionObject(callback.m_hitCollisionObject);
+            result->point.set(callback.m_hitPointWorld.x(), callback.m_hitPointWorld.y(), callback.m_hitPointWorld.z());
+            result->fraction = callback.m_closestHitFraction;
+            result->normal.set(callback.m_hitNormalWorld.x(), callback.m_hitNormalWorld.y(), callback.m_hitNormalWorld.z());
+        }
 
-        return getCollisionObject(callback.m_collisionObject);
+        return true;
     }
 
-    return NULL;
+    return false;
 }
 
 btScalar PhysicsController::addSingleResult(btManifoldPoint& cp, const btCollisionObject* a, int partIdA, int indexA, 

+ 43 - 7
gameplay/src/PhysicsController.h

@@ -56,6 +56,32 @@ public:
         virtual void statusEvent(EventType type) = 0;
     };
 
+    /**
+     * Stucture that stores hit test results for ray and sweep tests.
+     */
+    struct HitResult
+    {
+        /**
+         * The collision object that was hit.
+         */
+        PhysicsCollisionObject* object;
+
+        /**
+         * The point where the collision occurred, in world space.
+         */
+        Vector3 point;
+
+        /**
+         * The fraction (0-1) of the test distance to the collision point.
+         */
+        float fraction;
+
+        /**
+         * The normal vector of the collision surface, in world space.
+         */
+        Vector3 normal;
+    };
+
     /**
      * Adds a listener to the physics controller.
      * 
@@ -185,7 +211,7 @@ public:
      * @param gravity The gravity vector.
      */
     void setGravity(const Vector3& gravity);
-   
+
     /**
      * Draws debugging information (rigid body outlines, etc.) using the given view projection matrix.
      * 
@@ -194,16 +220,26 @@ public:
     void drawDebug(const Matrix& viewProjection);
 
     /**
-     * Gets the first rigid body that the given ray intersects.
+     * Performs a ray test on the physics world.
      * 
      * @param ray The ray to test intersection with.
      * @param distance How far along the given ray to test for intersections.
-     * @param hitPoint Optional Vector3 point that is populated with the world-space point of intersection.
-     * @param hitFraction Optional float pointer that is populated with the distance along the ray
-     *      (as a fraction between 0-1) where the intersection occurred.
-     * @return The first rigid body that the ray intersects, or NULL if no intersection was found.
+     * @param result Optioanl pointer to a HitTest structure to store hit test result information in.
+     * @return True if the ray test collided with a physics object, false otherwise.
+     */
+    bool rayTest(const Ray& ray, float distance, PhysicsController::HitResult* result = NULL);
+
+    /**
+     * Performs a sweep test of the given collision object on the physics world.
+     *
+     * The start position of the sweep test is defined by the current world position
+     * of the specified collision object.
+     *
+     * @param object The collision object to test.
+     * @param endPosition The end position of the sweep test, in world space.
+     * @return True if the object intersects any other physics objects, false otherwise.
      */
-    PhysicsCollisionObject* rayTest(const Ray& ray, float distance, Vector3* hitPoint = NULL, float* hitFraction = NULL);
+    bool sweepTest(PhysicsCollisionObject* object, const Vector3& endPosition, PhysicsController::HitResult* result = NULL);
 
 protected:
 

+ 1 - 0
gameplay/src/PhysicsGhostObject.cpp

@@ -18,6 +18,7 @@ PhysicsGhostObject::PhysicsGhostObject(Node* node, const PhysicsCollisionShape::
     // Create the ghost object.
     _ghostObject = bullet_new<btPairCachingGhostObject>();
     _ghostObject->setCollisionShape(_collisionShape->getShape());
+    _ghostObject->setCollisionFlags(_ghostObject->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
 
     // Initialize a physics motion state object for syncing the transform.
     _motionState = new PhysicsMotionState(_node, &centerOfMassOffset);

+ 1 - 0
gameplay/src/PhysicsGhostObject.h

@@ -16,6 +16,7 @@ class PhysicsMotionState;
 class PhysicsGhostObject : public PhysicsCollisionObject, public Transform::Listener
 {
     friend class Node;
+    friend class PhysicsController;
 
 public:
 

+ 2 - 2
gameplay/src/PlatformQNX.cpp

@@ -962,7 +962,7 @@ int Platform::enterMessagePump()
                     _game->menu();
                     break;
                 case NAVIGATOR_EXIT:
-                    _game->exit();
+                    _game->end();
                     break;
                 }
             }
@@ -990,7 +990,7 @@ int Platform::enterMessagePump()
         rc = eglSwapBuffers(__eglDisplay, __eglSurface);
         if (rc != EGL_TRUE)
         {
-            _game->exit();
+            _game->end();
             perror("eglSwapBuffers");
             break;
         }

+ 1 - 1
gameplay/src/PlatformWin32.cpp

@@ -589,7 +589,7 @@ int Platform::enterMessagePump()
 
             if (msg.message == WM_QUIT)
             {
-                _game->exit();
+                _game->end();
                 break;
             }
         }

+ 1 - 1
gameplay/src/SceneLoader.cpp

@@ -668,7 +668,7 @@ void SceneLoader::createAnimations(const Scene* scene)
             }
         }
 
-        Game::getInstance()->getAnimationController()->createAnimation(_animations[i]._animationID, node, p);
+        node->createAnimation(_animations[i]._animationID, p);
     }
 }
 

+ 6 - 2
gameplay/src/Slider.h

@@ -16,15 +16,16 @@ namespace gameplay
  *
  *  slider
  *  {
- *      style       = <Style ID>                // A Style from the Theme.
+ *      style       = <styleID>                 // A Style from the Theme.
  *      position    = <x, y>                    // Position of the Control on-screen, measured in pixels.
  *      size        = <width, height>           // Size of the Control, measured in pixels.
- *      // TODO: orientation = <HORIZONTAL or VERTICAL>  // Determines whether a slider is stretched along its width or its height
  *      min         = <float>                   // The value of the left- / bottom-most point on the slider.
  *      max         = <float>                   // The value of the right- / top-most point on the slider.
  *      value       = <float>                   // The default position of the marker.
  *      step        = <float>                   // If greater than 0, force the marker to snap to discrete multiples of 'step'.
  *      text        = <string>                  // Text to display above, below or alongside the slider (depending on the style).
+ *
+*      // TODO: orientation = <HORIZONTAL or VERTICAL>  // Determines whether a slider is stretched along its width or its height
  *  }
  */
 class Slider : public Label
@@ -154,6 +155,9 @@ protected:
 
 private:
 
+    /**
+     * Constructor.
+     */
     Slider(const Slider& copy);
 };
 

+ 5 - 2
gameplay/src/TextBox.h

@@ -18,9 +18,9 @@ namespace gameplay
  *
  * The following properties are available for text boxes:
  *
- * label <Label ID>
+ * label <labelID>
  * {
- *      style       = <Style ID>
+ *      style       = <styleID>
  *      position    = <x, y>
  *      size        = <width, height>
  *      text        = <string>
@@ -121,6 +121,9 @@ protected:
 
 private:
 
+    /**
+     * Constructor.
+     */
     TextBox(const TextBox& copy);
 
     void setCaretLocation(int x, int y);

+ 5 - 5
gameplay/src/VertexFormat.h

@@ -90,7 +90,7 @@ public:
     };
 
     /**
-     * Constructs a new vertex format for the requested vertex element layout.
+     * Constructor.
      *
      * The passed in element array is copied into the new VertexFormat.
      *
@@ -105,21 +105,21 @@ public:
     ~VertexFormat();
 
     /**
-     * Returns the vertex element at the specified index.
+     * Gets the vertex element at the specified index.
      *
-     * index The index of the element to retreive.
+     * @param index The index of the element to retreive.
      */
     const Element& getElement(unsigned int index) const;
 
     /**
-     * Returns the number of elements in this VertexFormat.
+     * Gets the number of elements in this VertexFormat.
      *
      * @return The number of items in the elements array.
      */
     unsigned int getElementCount() const;
 
     /**
-     * Returns the size (in bytes) of a single vertex using this format.
+     * Gets the size (in bytes) of a single vertex using this format.
      */
     unsigned int getVertexSize() const;
 

+ 3 - 0
gameplay/src/VerticalLayout.h

@@ -73,6 +73,9 @@ protected:
 
 private:
 
+    /**
+     * Constructor.
+     */
     VerticalLayout(const VerticalLayout& copy);
 };
 

+ 1 - 1
gameplay/src/gameplay.h

@@ -7,7 +7,6 @@
 #include "Mouse.h"
 #include "FileSystem.h"
 #include "Package.h"
-#include "ScreenDisplayer.h"
 
 // Math
 #include "Rectangle.h"
@@ -45,6 +44,7 @@
 #include "FrameBuffer.h"
 #include "RenderTarget.h"
 #include "DepthStencilTarget.h"
+#include "ScreenDisplayer.h"
 
 // Audio
 #include "AudioController.h"