Ver Fonte

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

Conflicts:
	gameplay-samples/sample03-character/res/scene.dae
	gameplay-samples/sample03-character/res/scene.gpb
	gameplay-samples/sample03-character/res/scene.mb
	gameplay-samples/sample03-character/src/CharacterGame.cpp
Steve Grenier há 13 anos atrás
pai
commit
eebd7a7183

+ 7 - 7
gameplay.sln

@@ -20,7 +20,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample03-character", "gamep
 EndProject
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay-encoder", "gameplay-encoder\gameplay-encoder.vcxproj", "{9D69B743-4872-4DD1-8E30-0087C64298D7}"
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay-encoder", "gameplay-encoder\gameplay-encoder.vcxproj", "{9D69B743-4872-4DD1-8E30-0087C64298D7}"
 EndProject
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-particles", "gameplay-samples\sample04-particles\sample04-particles.vcxproj", "{F47B5740-3C0C-BACE-4C2B-EE23A358D499}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-particles", "gameplay-samples\sample04-particles\sample04-particles.vcxproj", "{BB38678F-2614-C502-956C-0FFD84566556}"
 	ProjectSection(ProjectDependencies) = postProject
 	ProjectSection(ProjectDependencies) = postProject
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 	EndProjectSection
 	EndProjectSection
@@ -67,12 +67,12 @@ Global
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.DebugMem|Win32.Build.0 = Debug|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.DebugMem|Win32.Build.0 = Debug|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.Release|Win32.ActiveCfg = Release|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.Release|Win32.ActiveCfg = Release|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.Release|Win32.Build.0 = Release|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.Release|Win32.Build.0 = Release|Win32
-		{F47B5740-3C0C-BACE-4C2B-EE23A358D499}.Debug|Win32.ActiveCfg = Debug|Win32
-		{F47B5740-3C0C-BACE-4C2B-EE23A358D499}.Debug|Win32.Build.0 = Debug|Win32
-		{F47B5740-3C0C-BACE-4C2B-EE23A358D499}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
-		{F47B5740-3C0C-BACE-4C2B-EE23A358D499}.DebugMem|Win32.Build.0 = DebugMem|Win32
-		{F47B5740-3C0C-BACE-4C2B-EE23A358D499}.Release|Win32.ActiveCfg = Release|Win32
-		{F47B5740-3C0C-BACE-4C2B-EE23A358D499}.Release|Win32.Build.0 = Release|Win32
+		{BB38678F-2614-C502-956C-0FFD84566556}.Debug|Win32.ActiveCfg = Debug|Win32
+		{BB38678F-2614-C502-956C-0FFD84566556}.Debug|Win32.Build.0 = Debug|Win32
+		{BB38678F-2614-C502-956C-0FFD84566556}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
+		{BB38678F-2614-C502-956C-0FFD84566556}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{BB38678F-2614-C502-956C-0FFD84566556}.Release|Win32.ActiveCfg = Release|Win32
+		{BB38678F-2614-C502-956C-0FFD84566556}.Release|Win32.Build.0 = Release|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|Win32.ActiveCfg = Debug|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|Win32.ActiveCfg = Debug|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|Win32.Build.0 = Debug|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|Win32.Build.0 = Debug|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|Win32.ActiveCfg = DebugMem|Win32

+ 15 - 1
gameplay/src/Animation.cpp

@@ -19,12 +19,18 @@ Animation::Animation(const char* id, AnimationTarget* target, int propertyId, un
     : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0), _defaultClip(NULL), _clips(NULL)
     : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0), _defaultClip(NULL), _clips(NULL)
 {
 {
     createChannel(target, propertyId, keyCount, keyTimes, keyValues, type);
     createChannel(target, propertyId, keyCount, keyTimes, keyValues, type);
+    // Release the animation because a newly created animation has a ref count of 1 and the channels hold the ref to animation.
+    release();
+    assert(getRefCount() == 1);
 }
 }
 
 
 Animation::Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type)
 Animation::Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type)
     : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0), _defaultClip(NULL), _clips(NULL)
     : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0), _defaultClip(NULL), _clips(NULL)
 {
 {
     createChannel(target, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
     createChannel(target, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
+    // Release the animation because a newly created animation has a ref count of 1 and the channels hold the ref to animation.
+    release();
+    assert(getRefCount() == 1);
 }
 }
 
 
 Animation::Animation(const char* id)
 Animation::Animation(const char* id)
@@ -67,6 +73,7 @@ Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int p
     assert(_target->getAnimationPropertyComponentCount(propertyId));
     assert(_target->getAnimationPropertyComponentCount(propertyId));
     _curve->addRef();
     _curve->addRef();
     _target->addChannel(this);
     _target->addChannel(this);
+    _animation->addRef();
 }
 }
 
 
 Animation::Channel::Channel(const Channel& copy, Animation* animation, AnimationTarget* target)
 Animation::Channel::Channel(const Channel& copy, Animation* animation, AnimationTarget* target)
@@ -74,6 +81,7 @@ Animation::Channel::Channel(const Channel& copy, Animation* animation, Animation
 {
 {
     _curve->addRef();
     _curve->addRef();
     _target->addChannel(this);
     _target->addChannel(this);
+    _animation->addRef();
 }
 }
 
 
 Animation::Channel::~Channel()
 Animation::Channel::~Channel()
@@ -388,9 +396,15 @@ void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId
     return;
     return;
 }
 }
 
 
-Animation* Animation::clone()
+Animation* Animation::clone(Channel* channel, AnimationTarget* target)
 {
 {
     Animation* animation = new Animation(getId());
     Animation* animation = new Animation(getId());
+
+    Animation::Channel* channelCopy = new Animation::Channel(*channel, animation, target);
+    animation->addChannel(channelCopy);
+    // Release the animation because a newly created animation has a ref count of 1 and the channels hold the ref to animation.
+    animation->release();
+    assert(animation->getRefCount() == 1);
     return animation;
     return animation;
 }
 }
 
 

+ 4 - 1
gameplay/src/Animation.h

@@ -201,9 +201,12 @@ private:
     /**
     /**
      * Clones this animation.
      * Clones this animation.
      * 
      * 
+     * @param channel The channel to clone and add to the animation.
+     * @param target The target of the animation.
+     * 
      * @return The newly created animation.
      * @return The newly created animation.
      */
      */
-    Animation* clone();
+    Animation* clone(Channel* channel, AnimationTarget* target);
     
     
     AnimationController* _controller;       // The AnimationController that this Animation will run on.
     AnimationController* _controller;       // The AnimationController that this Animation will run on.
     std::string _id;                        // The Animation's ID.
     std::string _id;                        // The Animation's ID.

+ 9 - 12
gameplay/src/AnimationTarget.cpp

@@ -397,21 +397,18 @@ void AnimationTarget::cloneInto(AnimationTarget* target, NodeCloneContext &conte
             Animation::Channel* channel = *it;
             Animation::Channel* channel = *it;
             assert(channel->_animation);
             assert(channel->_animation);
 
 
-            bool animationCloned = false;
-
-            // Don't clone the Animaton if it is already in the clone context.
             Animation* animation = context.findClonedAnimation(channel->_animation);
             Animation* animation = context.findClonedAnimation(channel->_animation);
-            if (animation == NULL)
+            if (animation != NULL)
             {
             {
-                animation = channel->_animation->clone();
-                animationCloned = true;
+                Animation::Channel* channelCopy = new Animation::Channel(*channel, animation, target);
+                animation->addChannel(channelCopy);
+            }
+            else
+            {
+                // Clone the animation and register it with the context so that it only gets cloned once.
+                animation = channel->_animation->clone(channel, target);
+                context.registerClonedAnimation(channel->_animation, animation);
             }
             }
-            assert(animation);
-
-            context.registerClonedAnimation(channel->_animation, animation);
-            
-            Animation::Channel* channelCopy = new Animation::Channel(*channel, animation, target);
-            animation->addChannel(channelCopy);
         }
         }
     }
     }
 }
 }

+ 3 - 3
gameplay/src/CheckBox.cpp

@@ -23,7 +23,7 @@ CheckBox* CheckBox::create(Theme::Style* style, Properties* properties)
 {
 {
     CheckBox* checkBox = new CheckBox();
     CheckBox* checkBox = new CheckBox();
     checkBox->initialize(style, properties);
     checkBox->initialize(style, properties);
-    properties->getVector2("iconSize", &checkBox->_imageSize);
+    properties->getVector2("imageSize", &checkBox->_imageSize);
     checkBox->_checked = properties->getBool("checked");
     checkBox->_checked = properties->getBool("checked");
 
 
     return checkBox;
     return checkBox;
@@ -123,8 +123,8 @@ void CheckBox::update(const Rectangle& clip)
     }
     }
     float iconWidth = size.x;
     float iconWidth = size.x;
 
 
-    _textBounds.x += iconWidth;
-    _textBounds.width -= iconWidth;
+    _textBounds.x += iconWidth + 5;
+    _textBounds.width -= iconWidth + 5;
 }
 }
 
 
 void CheckBox::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
 void CheckBox::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)

+ 3 - 12
gameplay/src/Control.cpp

@@ -614,16 +614,12 @@ namespace gameplay
         float clipX2 = clip.x + clip.width;
         float clipX2 = clip.x + clip.width;
         float x2 = x + width;
         float x2 = x + width;
         if (x2 > clipX2)
         if (x2 > clipX2)
-        {
             width = clipX2 - x;
             width = clipX2 - x;
-        }
 
 
         float clipY2 = clip.y + clip.height;
         float clipY2 = clip.y + clip.height;
         float y2 = y + height;
         float y2 = y + height;
         if (y2 > clipY2)
         if (y2 > clipY2)
-        {
             height = clipY2 - y;
             height = clipY2 - y;
-        }
 
 
         _clipBounds.set(_bounds.x, _bounds.y, width, height);
         _clipBounds.set(_bounds.x, _bounds.y, width, height);
 
 
@@ -641,32 +637,27 @@ namespace gameplay
         clipX2 = clip.x + clip.width;
         clipX2 = clip.x + clip.width;
         x2 = x + width;
         x2 = x + width;
         if (x2 > clipX2)
         if (x2 > clipX2)
-        {
             width = clipX2 - x;
             width = clipX2 - x;
-        }
 
 
         clipY2 = clip.y + clip.height;
         clipY2 = clip.y + clip.height;
         y2 = y + height;
         y2 = y + height;
         if (y2 > clipY2)
         if (y2 > clipY2)
-        {
             height = clipY2 - y;
             height = clipY2 - y;
-        }
 
 
         if (x < clip.x)
         if (x < clip.x)
-        {
             x = clip.x;
             x = clip.x;
-        }
 
 
         if (y < clip.y)
         if (y < clip.y)
-        {
             y = clip.y;
             y = clip.y;
-        }
 
 
         _clip.set(x, y, width, height);
         _clip.set(x, y, width, height);
     }
     }
 
 
     void Control::drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip)
     void Control::drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip)
     {
     {
+        if (_bounds.width <= 0 || _bounds.height <= 0)
+            return;
+
         Vector2 pos(clip.x + _bounds.x, clip.y + _bounds.y);
         Vector2 pos(clip.x + _bounds.x, clip.y + _bounds.y);
 
 
         // Get the border and background images for this control's current state.
         // Get the border and background images for this control's current state.

+ 24 - 14
gameplay/src/Form.cpp

@@ -201,36 +201,46 @@ namespace gameplay
     {
     {
         std::vector<Control*>::const_iterator it;
         std::vector<Control*>::const_iterator it;
 
 
-        // Batch all themed border and background sprites.
+        // Batch for all themed border and background sprites.
         spriteBatch->begin();
         spriteBatch->begin();
 
 
+        // Batch each font individually.
+        std::set<Font*>::const_iterator fontIter;
+        for (fontIter = _theme->_fonts.begin(); fontIter != _theme->_fonts.end(); fontIter++)
+        {
+            Font* font = *fontIter;
+            if (font)
+            {
+                font->begin();
+            }
+        }
+
         // Draw the form's border and background.
         // Draw the form's border and background.
         // We don't pass the form's position to itself or it will be applied twice!
         // We don't pass the form's position to itself or it will be applied twice!
         Control::drawBorder(spriteBatch, Rectangle(0, 0, _bounds.width, _bounds.height));
         Control::drawBorder(spriteBatch, Rectangle(0, 0, _bounds.width, _bounds.height));
 
 
-        // Draw each control's border and background.
         for (it = _controls.begin(); it < _controls.end(); it++)
         for (it = _controls.begin(); it < _controls.end(); it++)
         {
         {
             Control* control = *it;
             Control* control = *it;
 
 
-            //if (!_node || (*it)->isDirty())
-            {
-                control->drawBorder(spriteBatch, clip);
+            // Draw this control's border and background.
+            control->drawBorder(spriteBatch, clip);
 
 
-                // Add all themed foreground sprites (checkboxes etc.) to the same batch.
-                control->drawImages(spriteBatch, clip);
-            }
+            // Add all themed foreground sprites (checkboxes etc.) to the same batch.
+            control->drawImages(spriteBatch, clip);
+
+            control->drawText(clip);
         }
         }
+
+        // Done all batching.
         spriteBatch->end();
         spriteBatch->end();
 
 
-        // Draw all control foregrounds / text.
-        for (it = _controls.begin(); it < _controls.end(); it++)
+        for (fontIter = _theme->_fonts.begin(); fontIter != _theme->_fonts.end(); fontIter++)
         {
         {
-            Control* control = *it;
-
-            //if (!_node || (*it)->isDirty())
+            Font* font = *fontIter;
+            if (font)
             {
             {
-                control->drawText(clip);
+                font->end();
             }
             }
         }
         }
 
 

+ 0 - 2
gameplay/src/Label.cpp

@@ -74,9 +74,7 @@ namespace gameplay
         textColor.w *= getOpacity(_state);
         textColor.w *= getOpacity(_state);
 
 
         // Draw the text.
         // Draw the text.
-        font->begin();
         font->drawText(_text.c_str(), _textBounds, textColor, getFontSize(_state), getTextAlignment(_state), true, getTextRightToLeft(_state), &_clip);
         font->drawText(_text.c_str(), _textBounds, textColor, getFontSize(_state), getTextAlignment(_state), true, getTextRightToLeft(_state), &_clip);
-        font->end();
 
 
         _dirty = false;
         _dirty = false;
     }
     }

+ 10 - 7
gameplay/src/Layout.cpp

@@ -11,38 +11,41 @@ namespace gameplay
             control->_autoWidth || control->_autoHeight)
             control->_autoWidth || control->_autoHeight)
         {
         {
             Rectangle controlBounds = control->getBounds();
             Rectangle controlBounds = control->getBounds();
-            const Rectangle& containerBounds = container->getClip();
+            const Rectangle& containerBounds = container->getClipBounds();
             const Theme::Border& containerBorder = container->getBorder(container->getState());
             const Theme::Border& containerBorder = container->getBorder(container->getState());
             const Theme::Padding& containerPadding = container->getPadding();
             const Theme::Padding& containerPadding = container->getPadding();
 
 
+            float clipWidth = containerBounds.width - containerBorder.left - containerBorder.right - containerPadding.left - containerPadding.right;
+            float clipHeight = containerBounds.height - containerBorder.top - containerBorder.bottom - containerPadding.top - containerPadding.bottom;
+
             if (control->_autoWidth)
             if (control->_autoWidth)
             {
             {
-                controlBounds.width = containerBounds.width;
+                controlBounds.width = clipWidth;
             }
             }
 
 
             if (control->_autoHeight)
             if (control->_autoHeight)
             {
             {
-                controlBounds.height = containerBounds.height;
+                controlBounds.height = clipHeight;
             }
             }
 
 
             // Vertical alignment
             // Vertical alignment
             if ((control->_alignment & Control::ALIGN_BOTTOM) == Control::ALIGN_BOTTOM)
             if ((control->_alignment & Control::ALIGN_BOTTOM) == Control::ALIGN_BOTTOM)
             {
             {
-                controlBounds.y = containerBounds.height - controlBounds.height;
+                controlBounds.y = clipHeight - controlBounds.height;
             }
             }
             else if ((control->_alignment & Control::ALIGN_VCENTER) == Control::ALIGN_VCENTER)
             else if ((control->_alignment & Control::ALIGN_VCENTER) == Control::ALIGN_VCENTER)
             {
             {
-                controlBounds.y = containerBounds.height * 0.5f - controlBounds.height * 0.5f;
+                controlBounds.y = clipHeight * 0.5f - controlBounds.height * 0.5f;
             }
             }
 
 
             // Horizontal alignment
             // Horizontal alignment
             if ((control->_alignment & Control::ALIGN_RIGHT) == Control::ALIGN_RIGHT)
             if ((control->_alignment & Control::ALIGN_RIGHT) == Control::ALIGN_RIGHT)
             {
             {
-                controlBounds.x = containerBounds.width - controlBounds.width;
+                controlBounds.x = clipWidth - controlBounds.width;
             }
             }
             else if ((control->_alignment & Control::ALIGN_HCENTER) == Control::ALIGN_HCENTER)
             else if ((control->_alignment & Control::ALIGN_HCENTER) == Control::ALIGN_HCENTER)
             {
             {
-                controlBounds.x = containerBounds.width * 0.5f - controlBounds.width * 0.5f;
+                controlBounds.x = clipWidth * 0.5f - controlBounds.width * 0.5f;
             }
             }
 
 
             control->setBounds(controlBounds);
             control->setBounds(controlBounds);

+ 0 - 1
gameplay/src/Package.cpp

@@ -969,7 +969,6 @@ Animation* Package::readAnimationChannel(Scene* scene, Animation* animation, con
         else
         else
         {
         {
             animation->createChannel(target, targetAttribute, keyTimesCount, &keyTimes[0], &values[0], Curve::LINEAR);
             animation->createChannel(target, targetAttribute, keyTimesCount, &keyTimes[0], &values[0], Curve::LINEAR);
-            animation->addRef();
         }
         }
     }
     }
 
 

+ 6 - 22
gameplay/src/PlatformQNX.cpp

@@ -804,14 +804,9 @@ int Platform::enterMessagePump()
                 {
                 {
                     case SCREEN_EVENT_MTOUCH_TOUCH:
                     case SCREEN_EVENT_MTOUCH_TOUCH:
                     {
                     {
-                        if (!__multiTouch)
+                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
+                        if (__multiTouch || touchEvent.contact_id == 0)
                         {
                         {
-                            screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_POSITION, position);
-                           gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, position[0], position[1], 0);
-                        }
-                        else
-                        {
-                            screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
                             gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, touchEvent.x, touchEvent.y, touchEvent.contact_id);
                             gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, touchEvent.x, touchEvent.y, touchEvent.contact_id);
                         }
                         }
                         break;
                         break;
@@ -819,14 +814,9 @@ int Platform::enterMessagePump()
 
 
                     case SCREEN_EVENT_MTOUCH_RELEASE:
                     case SCREEN_EVENT_MTOUCH_RELEASE:
                     {
                     {
-                        if (!__multiTouch)
-                        {
-                            screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_POSITION, position);
-                           gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, position[0], position[1], 0);
-                        }
-                        else
+                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
+                        if (__multiTouch || touchEvent.contact_id == 0)
                         {
                         {
-                            screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
                             gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, touchEvent.x, touchEvent.y, touchEvent.contact_id);
                             gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, touchEvent.x, touchEvent.y, touchEvent.contact_id);
                         }
                         }
                         break;
                         break;
@@ -834,18 +824,12 @@ int Platform::enterMessagePump()
 
 
                     case SCREEN_EVENT_MTOUCH_MOVE:
                     case SCREEN_EVENT_MTOUCH_MOVE:
                     {
                     {
-                        if (!__multiTouch)
+                        screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
+                        if (__multiTouch ||touchEvent.contact_id == 0)
                         {
                         {
-                            screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_POSITION, position);
-                           gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, position[0], position[1], 0);
-                        }
-                        else
-                        {
-                            screen_get_mtouch_event(__screenEvent, &touchEvent, 0);
                             gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, touchEvent.x, touchEvent.y, touchEvent.contact_id);
                             gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, touchEvent.x, touchEvent.y, touchEvent.contact_id);
                         }
                         }
                         break;
                         break;
-                        break;
                     }
                     }
 
 
                     case SCREEN_EVENT_POINTER:
                     case SCREEN_EVENT_POINTER:

+ 2 - 2
gameplay/src/RadioButton.cpp

@@ -198,8 +198,8 @@ void RadioButton::update(const Rectangle& clip)
     }
     }
     float iconWidth = size.x;
     float iconWidth = size.x;
 
 
-    _textBounds.x += iconWidth;
-    _textBounds.width -= iconWidth;
+    _textBounds.x += iconWidth + 5;
+    _textBounds.width -= iconWidth + 5;
 }
 }
 
 
 }
 }

+ 1 - 0
gameplay/src/SceneLoader.cpp

@@ -309,6 +309,7 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
                         {
                         {
                             // Temporarily set rigidbody model on model so it's used during collision object creation.
                             // Temporarily set rigidbody model on model so it's used during collision object creation.
                             Model* model = node->getModel();
                             Model* model = node->getModel();
+                            assert(model);
                         
                         
                             // Up ref count to prevent node from releasing the model when we swap it.
                             // Up ref count to prevent node from releasing the model when we swap it.
                             model->addRef(); 
                             model->addRef(); 

+ 32 - 1
gameplay/src/TextBox.cpp

@@ -222,9 +222,40 @@ void TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         // Insert character into string.
                         // Insert character into string.
                         _text.insert(textIndex, 1, (char)key);
                         _text.insert(textIndex, 1, (char)key);
 
 
-                        // Get new location of cursor.
+                        // Get new location of caret.
                         font->getLocationAtIndex(_text.c_str(), _clip, fontSize, &_caretLocation, textIndex + 1,
                         font->getLocationAtIndex(_text.c_str(), _clip, fontSize, &_caretLocation, textIndex + 1,
                             textAlignment, true, rightToLeft);
                             textAlignment, true, rightToLeft);
+
+                        if (key == ' ')
+                        {
+                            // If a space was entered, check that caret is still within bounds.
+                            if (_caretLocation.x >= _clip.x + _clip.width ||
+                                _caretLocation.y >= _clip.y + _clip.height)
+                            {
+                                // If not, undo the character insertion.
+                                _text.erase(textIndex, 1);
+                                font->getLocationAtIndex(_text.c_str(), _clip, fontSize, &_caretLocation, textIndex,
+                                    textAlignment, true, rightToLeft);
+
+                                // No need to check again.
+                                break;
+                            }
+                        }
+
+                        // Always check that the text still fits within the clip region.
+                        Rectangle textBounds;
+                        font->measureText(_text.c_str(), _clip, fontSize, &textBounds, textAlignment, true, true);
+                        if (textBounds.x <= _clip.x || textBounds.y <= _clip.y ||
+                            textBounds.width >= _clip.width || textBounds.height >= _clip.height)
+                        {
+                            // If not, undo the character insertion.
+                            _text.erase(textIndex, 1);
+                            font->getLocationAtIndex(_text.c_str(), _clip, fontSize, &_caretLocation, textIndex,
+                                textAlignment, true, rightToLeft);
+
+                            // TextBox is not dirty.
+                            break;
+                        }
                 
                 
                         _dirty = true;
                         _dirty = true;
                         break;
                         break;

+ 60 - 51
gameplay/src/Transform.cpp

@@ -7,28 +7,28 @@ namespace gameplay
 {
 {
 
 
 Transform::Transform()
 Transform::Transform()
-    : _matrixDirty(false), _listeners(NULL)
+    : _matrixDirtyBits(0), _listeners(NULL)
 {
 {
     _targetType = AnimationTarget::TRANSFORM;
     _targetType = AnimationTarget::TRANSFORM;
     _scale.set(Vector3::one());
     _scale.set(Vector3::one());
 }
 }
 
 
 Transform::Transform(const Vector3& scale, const Quaternion& rotation, const Vector3& translation)
 Transform::Transform(const Vector3& scale, const Quaternion& rotation, const Vector3& translation)
-    : _matrixDirty(false), _listeners(NULL)
+    : _matrixDirtyBits(0), _listeners(NULL)
 {
 {
     _targetType = AnimationTarget::TRANSFORM;
     _targetType = AnimationTarget::TRANSFORM;
     set(scale, rotation, translation);
     set(scale, rotation, translation);
 }
 }
 
 
 Transform::Transform(const Vector3& scale, const Matrix& rotation, const Vector3& translation)
 Transform::Transform(const Vector3& scale, const Matrix& rotation, const Vector3& translation)
-    : _matrixDirty(false), _listeners(NULL)
+    : _matrixDirtyBits(0), _listeners(NULL)
 {
 {
     _targetType = AnimationTarget::TRANSFORM;
     _targetType = AnimationTarget::TRANSFORM;
     set(scale, rotation, translation);
     set(scale, rotation, translation);
 }
 }
 
 
 Transform::Transform(const Transform& copy)
 Transform::Transform(const Transform& copy)
-    : _matrixDirty(false), _listeners(NULL)
+    : _matrixDirtyBits(0), _listeners(NULL)
 {
 {
     _targetType = AnimationTarget::TRANSFORM;
     _targetType = AnimationTarget::TRANSFORM;
     set(copy);
     set(copy);
@@ -41,40 +41,40 @@ Transform::~Transform()
 
 
 const Matrix& Transform::getMatrix() const
 const Matrix& Transform::getMatrix() const
 {
 {
-    if (_matrixDirty)
+    if (_matrixDirtyBits)
     {
     {
-        _matrixDirty = false;
-
         bool hasTranslation = !_translation.isZero();
         bool hasTranslation = !_translation.isZero();
         bool hasScale = !_scale.isOne();
         bool hasScale = !_scale.isOne();
         bool hasRotation = !_rotation.isIdentity();
         bool hasRotation = !_rotation.isIdentity();
 
 
         // Compose the matrix in TRS order since we use column-major matrices with column vectors and
         // Compose the matrix in TRS order since we use column-major matrices with column vectors and
         // multiply M*v (as opposed to XNA and DirectX that use row-major matrices with row vectors and multiply v*M).
         // multiply M*v (as opposed to XNA and DirectX that use row-major matrices with row vectors and multiply v*M).
-        if (hasTranslation)
+        if (hasTranslation || (_matrixDirtyBits & DIRTY_TRANSLATION) == DIRTY_TRANSLATION)
         {
         {
             Matrix::createTranslation(_translation, &_matrix);
             Matrix::createTranslation(_translation, &_matrix);
-            if (hasRotation)
+            if (hasRotation || (_matrixDirtyBits & DIRTY_ROTATION) == DIRTY_ROTATION)
             {
             {
                 _matrix.rotate(_rotation);
                 _matrix.rotate(_rotation);
             }
             }
-            if (hasScale)
+            if (hasScale || (_matrixDirtyBits & DIRTY_SCALE) == DIRTY_SCALE)
             {
             {
                 _matrix.scale(_scale);
                 _matrix.scale(_scale);
             }
             }
         }
         }
-        else if (hasRotation)
+        else if (hasRotation || (_matrixDirtyBits & DIRTY_ROTATION) == DIRTY_ROTATION)
         {
         {
             Matrix::createRotation(_rotation, &_matrix);
             Matrix::createRotation(_rotation, &_matrix);
-            if (hasScale)
+            if (hasScale || (_matrixDirtyBits & DIRTY_SCALE) == DIRTY_SCALE)
             {
             {
                 _matrix.scale(_scale);
                 _matrix.scale(_scale);
             }
             }
         }
         }
-        else if (hasScale)
+        else if (hasScale || (_matrixDirtyBits & DIRTY_SCALE) == DIRTY_SCALE)
         {
         {
             Matrix::createScale(_scale, &_matrix);
             Matrix::createScale(_scale, &_matrix);
         }
         }
+
+        _matrixDirtyBits = 0;
     }
     }
 
 
     return _matrix;
     return _matrix;
@@ -231,13 +231,13 @@ void Transform::rotate(float qx, float qy, float qz, float qw)
 {
 {
     Quaternion q(qx, qy, qz, qw);
     Quaternion q(qx, qy, qz, qw);
     _rotation.multiply(q);
     _rotation.multiply(q);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::rotate(const Quaternion& rotation)
 void Transform::rotate(const Quaternion& rotation)
 {
 {
     _rotation.multiply(rotation);
     _rotation.multiply(rotation);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::rotate(const Vector3& axis, float angle)
 void Transform::rotate(const Vector3& axis, float angle)
@@ -246,7 +246,7 @@ void Transform::rotate(const Vector3& axis, float angle)
     Quaternion::createFromAxisAngle(axis, angle, &rotationQuat);
     Quaternion::createFromAxisAngle(axis, angle, &rotationQuat);
     _rotation.multiply(rotationQuat);
     _rotation.multiply(rotationQuat);
     _rotation.normalize();
     _rotation.normalize();
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::rotate(const Matrix& rotation)
 void Transform::rotate(const Matrix& rotation)
@@ -254,7 +254,7 @@ void Transform::rotate(const Matrix& rotation)
     Quaternion rotationQuat;
     Quaternion rotationQuat;
     Quaternion::createFromRotationMatrix(rotation, &rotationQuat);
     Quaternion::createFromRotationMatrix(rotation, &rotationQuat);
     _rotation.multiply(rotationQuat);
     _rotation.multiply(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::rotateX(float angle)
 void Transform::rotateX(float angle)
@@ -262,7 +262,7 @@ void Transform::rotateX(float angle)
     Quaternion rotationQuat;
     Quaternion rotationQuat;
     Quaternion::createFromAxisAngle(Vector3::unitX(), angle, &rotationQuat);
     Quaternion::createFromAxisAngle(Vector3::unitX(), angle, &rotationQuat);
     _rotation.multiply(rotationQuat);
     _rotation.multiply(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::rotateY(float angle)
 void Transform::rotateY(float angle)
@@ -270,7 +270,7 @@ void Transform::rotateY(float angle)
     Quaternion rotationQuat;
     Quaternion rotationQuat;
     Quaternion::createFromAxisAngle(Vector3::unitY(), angle, &rotationQuat);
     Quaternion::createFromAxisAngle(Vector3::unitY(), angle, &rotationQuat);
     _rotation.multiply(rotationQuat);
     _rotation.multiply(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::rotateZ(float angle)
 void Transform::rotateZ(float angle)
@@ -278,13 +278,13 @@ void Transform::rotateZ(float angle)
     Quaternion rotationQuat;
     Quaternion rotationQuat;
     Quaternion::createFromAxisAngle(Vector3::unitZ(), angle, &rotationQuat);
     Quaternion::createFromAxisAngle(Vector3::unitZ(), angle, &rotationQuat);
     _rotation.multiply(rotationQuat);
     _rotation.multiply(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::scale(float scale)
 void Transform::scale(float scale)
 {
 {
     _scale.scale(scale);
     _scale.scale(scale);
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::scale(float sx, float sy, float sz)
 void Transform::scale(float sx, float sy, float sz)
@@ -292,7 +292,7 @@ void Transform::scale(float sx, float sy, float sz)
     _scale.x *= sx;
     _scale.x *= sx;
     _scale.y *= sy;
     _scale.y *= sy;
     _scale.z *= sz;
     _scale.z *= sz;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::scale(const Vector3& scale)
 void Transform::scale(const Vector3& scale)
@@ -300,25 +300,25 @@ void Transform::scale(const Vector3& scale)
     _scale.x *= scale.x;
     _scale.x *= scale.x;
     _scale.y *= scale.y;
     _scale.y *= scale.y;
     _scale.z *= scale.z;
     _scale.z *= scale.z;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::scaleX(float sx)
 void Transform::scaleX(float sx)
 {
 {
     _scale.x *= sx;
     _scale.x *= sx;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::scaleY(float sy)
 void Transform::scaleY(float sy)
 {
 {
     _scale.y *= sy;
     _scale.y *= sy;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::scaleZ(float sz)
 void Transform::scaleZ(float sz)
 {
 {
     _scale.z *= sz;
     _scale.z *= sz;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::set(const Vector3& scale, const Quaternion& rotation, const Vector3& translation)
 void Transform::set(const Vector3& scale, const Quaternion& rotation, const Vector3& translation)
@@ -326,7 +326,7 @@ void Transform::set(const Vector3& scale, const Quaternion& rotation, const Vect
     _scale.set(scale);
     _scale.set(scale);
     _rotation.set(rotation);
     _rotation.set(rotation);
     _translation.set(translation);
     _translation.set(translation);
-    dirty();
+    dirty(DIRTY_TRANSLATION | DIRTY_ROTATION | DIRTY_SCALE);
 }
 }
 
 
 void Transform::set(const Vector3& scale, const Matrix& rotation, const Vector3& translation)
 void Transform::set(const Vector3& scale, const Matrix& rotation, const Vector3& translation)
@@ -336,7 +336,7 @@ void Transform::set(const Vector3& scale, const Matrix& rotation, const Vector3&
     Quaternion::createFromRotationMatrix(rotation, &rotationQuat);
     Quaternion::createFromRotationMatrix(rotation, &rotationQuat);
     _rotation.set(rotationQuat);
     _rotation.set(rotationQuat);
     _translation.set(translation);
     _translation.set(translation);
-    dirty();
+    dirty(DIRTY_TRANSLATION | DIRTY_ROTATION | DIRTY_SCALE);
 }
 }
 
 
 void Transform::set(const Vector3& scale, const Vector3& axis, float angle, const Vector3& translation)
 void Transform::set(const Vector3& scale, const Vector3& axis, float angle, const Vector3& translation)
@@ -344,6 +344,7 @@ void Transform::set(const Vector3& scale, const Vector3& axis, float angle, cons
     _scale.set(scale);
     _scale.set(scale);
     _rotation.set(axis, angle);
     _rotation.set(axis, angle);
     _translation.set(translation);
     _translation.set(translation);
+    dirty(DIRTY_TRANSLATION | DIRTY_ROTATION | DIRTY_SCALE);
 }
 }
 
 
 void Transform::set(const Transform& transform)
 void Transform::set(const Transform& transform)
@@ -351,55 +352,63 @@ void Transform::set(const Transform& transform)
     _scale.set(transform._scale);
     _scale.set(transform._scale);
     _rotation.set(transform._rotation);
     _rotation.set(transform._rotation);
     _translation.set(transform._translation);
     _translation.set(transform._translation);
-    dirty();
+    dirty(DIRTY_TRANSLATION | DIRTY_ROTATION | DIRTY_SCALE);
+}
+
+void Transform::setIdentity()
+{
+    _scale.set(1.0f, 1.0f, 1.0f);
+    _rotation.setIdentity();
+    _translation.set(0.0f, 0.0f, 0.0f);
+    dirty(DIRTY_TRANSLATION | DIRTY_ROTATION | DIRTY_SCALE);
 }
 }
 
 
 void Transform::setScale(float scale)
 void Transform::setScale(float scale)
 {
 {
     _scale.set(scale, scale, scale);
     _scale.set(scale, scale, scale);
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::setScale(float sx, float sy, float sz)
 void Transform::setScale(float sx, float sy, float sz)
 {
 {
     _scale.set(sx, sy, sz);
     _scale.set(sx, sy, sz);
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::setScale(const Vector3& scale)
 void Transform::setScale(const Vector3& scale)
 {
 {
     _scale.set(scale);
     _scale.set(scale);
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::setScaleX(float sx)
 void Transform::setScaleX(float sx)
 {
 {
     _scale.x = sx;
     _scale.x = sx;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::setScaleY(float sy)
 void Transform::setScaleY(float sy)
 {
 {
     _scale.y = sy;
     _scale.y = sy;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::setScaleZ(float sz)
 void Transform::setScaleZ(float sz)
 {
 {
     _scale.z = sz;
     _scale.z = sz;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 }
 
 
 void Transform::setRotation(const Quaternion& rotation)
 void Transform::setRotation(const Quaternion& rotation)
 {
 {
     _rotation.set(rotation);
     _rotation.set(rotation);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::setRotation(float qx, float qy, float qz, float qw)
 void Transform::setRotation(float qx, float qy, float qz, float qw)
 {
 {
     _rotation.set(qx, qy, qz, qw);
     _rotation.set(qx, qy, qz, qw);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::setRotation(const Matrix& rotation)
 void Transform::setRotation(const Matrix& rotation)
@@ -407,43 +416,43 @@ void Transform::setRotation(const Matrix& rotation)
     Quaternion rotationQuat;
     Quaternion rotationQuat;
     Quaternion::createFromRotationMatrix(rotation, &rotationQuat);
     Quaternion::createFromRotationMatrix(rotation, &rotationQuat);
     _rotation.set(rotationQuat);
     _rotation.set(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::setRotation(const Vector3& axis, float angle)
 void Transform::setRotation(const Vector3& axis, float angle)
 {
 {
     _rotation.set(axis, angle);
     _rotation.set(axis, angle);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 }
 
 
 void Transform::setTranslation(const Vector3& translation)
 void Transform::setTranslation(const Vector3& translation)
 {
 {
     _translation.set(translation);
     _translation.set(translation);
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::setTranslation(float tx, float ty, float tz)
 void Transform::setTranslation(float tx, float ty, float tz)
 {
 {
     _translation.set(tx, ty, tz);
     _translation.set(tx, ty, tz);
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::setTranslationX(float tx)
 void Transform::setTranslationX(float tx)
 {
 {
     _translation.x = tx;
     _translation.x = tx;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::setTranslationY(float ty)
 void Transform::setTranslationY(float ty)
 {
 {
     _translation.y = ty;
     _translation.y = ty;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::setTranslationZ(float tz)
 void Transform::setTranslationZ(float tz)
 {
 {
     _translation.z = tz;
     _translation.z = tz;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::translate(float tx, float ty, float tz)
 void Transform::translate(float tx, float ty, float tz)
@@ -451,7 +460,7 @@ void Transform::translate(float tx, float ty, float tz)
     _translation.x += tx;
     _translation.x += tx;
     _translation.y += ty;
     _translation.y += ty;
     _translation.z += tz;
     _translation.z += tz;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::translate(const Vector3& translation)
 void Transform::translate(const Vector3& translation)
@@ -459,25 +468,25 @@ void Transform::translate(const Vector3& translation)
     _translation.x += translation.x;
     _translation.x += translation.x;
     _translation.y += translation.y;
     _translation.y += translation.y;
     _translation.z += translation.z;
     _translation.z += translation.z;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::translateX(float tx)
 void Transform::translateX(float tx)
 {
 {
     _translation.x += tx;
     _translation.x += tx;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::translateY(float ty)
 void Transform::translateY(float ty)
 {
 {
     _translation.y += ty;
     _translation.y += ty;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::translateZ(float tz)
 void Transform::translateZ(float tz)
 {
 {
     _translation.z += tz;
     _translation.z += tz;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 }
 
 
 void Transform::translateLeft(float amount)
 void Transform::translateLeft(float amount)
@@ -737,9 +746,9 @@ void Transform::setAnimationPropertyValue(int propertyId, AnimationValue* value,
     }
     }
 }
 }
 
 
-void Transform::dirty()
+void Transform::dirty(char matrixDirtyBits)
 {
 {
-    _matrixDirty = true;
+    _matrixDirtyBits |= matrixDirtyBits;
     transformChanged();
     transformChanged();
 }
 }
 
 

+ 14 - 2
gameplay/src/Transform.h

@@ -464,6 +464,11 @@ public:
      */
      */
     void set(const Transform& transform);
     void set(const Transform& transform);
 
 
+    /**
+     * Sets this transform to the identity transform.
+     */
+    void setIdentity();
+
     /**
     /**
      * Sets the scale factor along all axes for this transform
      * Sets the scale factor along all axes for this transform
      * to the specified value.
      * to the specified value.
@@ -736,10 +741,17 @@ protected:
         long cookie;
         long cookie;
     };
     };
 
 
+    enum MatrixDirtyBits
+    {
+        DIRTY_TRANSLATION = 0x01,
+        DIRTY_SCALE = 0x02,
+        DIRTY_ROTATION = 0x04,
+    };
+
     /**
     /**
      * Marks this transform as dirty and fires transformChanged().
      * Marks this transform as dirty and fires transformChanged().
      */
      */
-    void dirty();
+    void dirty(char matrixDirtyBits);
 
 
     /**
     /**
      * Called when the transform changes.
      * Called when the transform changes.
@@ -758,7 +770,7 @@ protected:
     Quaternion _rotation;
     Quaternion _rotation;
     Vector3 _translation;
     Vector3 _translation;
     mutable Matrix _matrix;
     mutable Matrix _matrix;
-    mutable bool _matrixDirty;
+    mutable char _matrixDirtyBits;
     std::list<TransformListener>* _listeners;
     std::list<TransformListener>* _listeners;
 
 
 private:
 private: