Jelajahi Sumber

Merge pull request #76 from blackberry-gaming/next

Next
Sean Paul Taylor 13 tahun lalu
induk
melakukan
784983e3fe

+ 6 - 7
gameplay-encoder/README.md

@@ -1,6 +1,6 @@
 ## gameplay-encoder
 Command-line tool for encoding games assets like true-type fonts and 3D scene files
-into a binary package file format for the gameplay 3D game framework runtime. 
+into a simple binary-based bundle file format for the gameplay 3D game framework runtime. 
 
 ## TrueType Font Support
 TrueType Fonts conversion is enabled/built-in by default into gameplay-encoder via freetype 2 library.
@@ -30,7 +30,7 @@ You must then rebuild gameplay-encoder with the follow platform/tooling instruct
   * Example: copy /Y "C:\Program Files\Autodesk\FBX\FbxSdk\2012.2\lib\vs2010\x86\fbxsdk-2012.2d.dll" "$(TargetDir)"
 - Build gameplay-encoder
 
-### Building FBX Support on Mac OS X using XCode 4
+### Building FBX Support on Mac OS X using XCode 4.3.2+
 - Download and install the FBX SDK for Mac OS X (http://www.autodesk.com/fbx)
 - Edit the project properties of target "gameplay-encoder".
 - Add Preprocessor Macro "USE_FBX" to both Debug/Release sections. (Build Settings)
@@ -41,12 +41,11 @@ You must then rebuild gameplay-encoder with the follow platform/tooling instruct
   * Example: libiconv.dylib, Cocoa.framework, SystemConfiguration.framework
 - Build gameplay-encoder
 
-## Binary Format
-The gameplay binary package format is well defined in the gameplay-encoder/gameplay-binary.txt file.
+## Bundle File Format
+The gameplay bundle file format is well defined in the gameplay-encoder/gameplay-bundle.txt file.
 
-## Binary Loading
-Binary package files can easily be loaded using the gameplay/Package.h which is part
-of the GamePlay runtime framework.
+## Bundle File Loading
+Bundle files can easily be loaded using the gameplay/Bundle.h which is part of the gameplay runtime framework.
 
 ## Disclaimer
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 

+ 10 - 10
gameplay-encoder/gameplay-binary.txt → gameplay-encoder/gameplay-bundle.txt

@@ -1,16 +1,16 @@
-gameplay Binary file format
+gameplay Bundle File Format (.gpb)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 File Description
 ================
-A sample binary file format supporting definition of primitve and builtin objects.
+A simple binary bundle file format supporting definition of primitve and builtin objects.
 
 File Extension and Mime Type
 ============================
-File extension is '.bbb' and the mime type is 'application/bbb'
+File extension is '.gpb' and the mime type is 'application/gpb'
 
 File Structure
-===============
+==============
 
 Section      Name            Type
 ------------------------------------------------------------------------------------------------------
@@ -22,31 +22,31 @@ Data
              Objects         Object[]
 
 Objects
-===========
+=======
 Supported object types are defined in the table below. Object with unique ids are included
 in the Reference table (see below).
 
 References
-===========
+==========
 A Reference is an Object that has a unique id. The Reference contains the unique id of the
 object, a uint for the TypeID a uint for the offset into the package for the object definition.
 
 ID's
-===========
+====
 Object ID's are represented as a string which is guaranteed to be unique per file.
 Any object which host an object id should be added to the header Reference table so that it can
 be consumed by reference internally and externally.
 
 Xrefs
-===========
+=====
 Xrefs are string with a specific format used for referencing objects internal and external to
 a package. An xref with the format "#id" references an object within the current package with
 the given ID. Xrefs can also have the format "file#id", where "file" is the name of package file
 (relative to the locaiton of the current package) and "id" is the unique identifier of an object
-in that package.
+in that bundle.
 
 Primitives
-===========
+==========
 
 Name            Description
 ------------------------------------------------------------------------------------------------------

+ 3 - 0
gameplay.sln

@@ -26,6 +26,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-particles", "gamep
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample00-mesh", "gameplay-samples\sample00-mesh\sample00-mesh.vcxproj", "{D672DC66-3CE0-4878-B0D2-813CA731012F}"
+	ProjectSection(ProjectDependencies) = postProject
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
+	EndProjectSection
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+ 2 - 3
gameplay/gameplay.vcxproj

@@ -60,7 +60,7 @@
     <ClCompile Include="src\MeshSkin.cpp" />
     <ClCompile Include="src\Model.cpp" />
     <ClCompile Include="src\Node.cpp" />
-    <ClCompile Include="src\Package.cpp" />
+    <ClCompile Include="src\Bundle.cpp" />
     <ClCompile Include="src\ParticleEmitter.cpp" />
     <ClCompile Include="src\PhysicsCharacter.cpp" />
     <ClCompile Include="src\PhysicsCollisionObject.cpp" />
@@ -151,7 +151,7 @@
     <ClInclude Include="src\MeshSkin.h" />
     <ClInclude Include="src\Model.h" />
     <ClInclude Include="src\Node.h" />
-    <ClInclude Include="src\Package.h" />
+    <ClInclude Include="src\Bundle.h" />
     <ClInclude Include="src\ParticleEmitter.h" />
     <ClInclude Include="src\PhysicsCharacter.h" />
     <ClInclude Include="src\PhysicsCollisionObject.h" />
@@ -221,7 +221,6 @@
     <None Include="res\shaders\solid.vsh" />
     <None Include="res\shaders\textured.fsh" />
     <None Include="res\shaders\textured.vsh" />
-    <None Include="res\textures\particle-default.png" />
     <None Include="src\BoundingBox.inl" />
     <None Include="src\BoundingSphere.inl" />
     <None Include="src\Curve.inl" />

+ 6 - 12
gameplay/gameplay.vcxproj.filters

@@ -10,9 +10,6 @@
     <Filter Include="res\shaders">
       <UniqueIdentifier>{be0b36f1-49ed-4a06-9f1f-57c654a554fe}</UniqueIdentifier>
     </Filter>
-    <Filter Include="res\textures">
-      <UniqueIdentifier>{7c4ef2fb-63f2-4d5a-b31e-0dc78329abfd}</UniqueIdentifier>
-    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\Animation.cpp">
@@ -75,9 +72,6 @@
     <ClCompile Include="src\Node.cpp">
       <Filter>src</Filter>
     </ClCompile>
-    <ClCompile Include="src\Package.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
     <ClCompile Include="src\Plane.cpp">
       <Filter>src</Filter>
     </ClCompile>
@@ -279,6 +273,9 @@
     <ClCompile Include="src\Layout.cpp">
       <Filter>src</Filter>
     </ClCompile>
+    <ClCompile Include="src\Bundle.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -350,9 +347,6 @@
     <ClInclude Include="src\Node.h">
       <Filter>src</Filter>
     </ClInclude>
-    <ClInclude Include="src\Package.h">
-      <Filter>src</Filter>
-    </ClInclude>
     <ClInclude Include="src\Plane.h">
       <Filter>src</Filter>
     </ClInclude>
@@ -551,6 +545,9 @@
     <ClInclude Include="src\ThemeStyle.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="src\Bundle.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="res\shaders\bumped-specular.vsh">
@@ -619,9 +616,6 @@
     <None Include="src\PlatformMacOSX.mm">
       <Filter>src</Filter>
     </None>
-    <None Include="res\textures\particle-default.png">
-      <Filter>res\textures</Filter>
-    </None>
     <None Include="src\Curve.inl">
       <Filter>src</Filter>
     </None>

+ 12 - 12
gameplay/gameplay.xcodeproj/project.pbxproj

@@ -13,6 +13,10 @@
 		4208DEEA14A4079F00D3C511 /* Image.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEE714A4079F00D3C511 /* Image.h */; };
 		4208DEEC14A407B900D3C511 /* Keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEEB14A407B900D3C511 /* Keyboard.h */; };
 		4208DEEE14A407D500D3C511 /* Touch.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEED14A407D500D3C511 /* Touch.h */; };
+		422260D61537790F0011E3AB /* Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 422260D41537790F0011E3AB /* Bundle.cpp */; };
+		422260D71537790F0011E3AB /* Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 422260D41537790F0011E3AB /* Bundle.cpp */; };
+		422260D81537790F0011E3AB /* Bundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 422260D51537790F0011E3AB /* Bundle.h */; };
+		422260D91537790F0011E3AB /* Bundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 422260D51537790F0011E3AB /* Bundle.h */; };
 		4234D99E14686C52003031B3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4234D99D14686C52003031B3 /* Cocoa.framework */; };
 		4251B131152D049B002F6199 /* ScreenDisplayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4251B12E152D049B002F6199 /* ScreenDisplayer.h */; };
 		4251B132152D049B002F6199 /* ScreenDisplayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4251B12E152D049B002F6199 /* ScreenDisplayer.h */; };
@@ -99,8 +103,6 @@
 		42CD0E88147D8FF60000361E /* Model.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF6147D8FF50000361E /* Model.h */; };
 		42CD0E89147D8FF60000361E /* Node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF7147D8FF50000361E /* Node.cpp */; };
 		42CD0E8A147D8FF60000361E /* Node.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF8147D8FF50000361E /* Node.h */; };
-		42CD0E8B147D8FF60000361E /* Package.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF9147D8FF50000361E /* Package.cpp */; };
-		42CD0E8C147D8FF60000361E /* Package.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DFA147D8FF50000361E /* Package.h */; };
 		42CD0E8D147D8FF60000361E /* ParticleEmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DFB147D8FF50000361E /* ParticleEmitter.cpp */; };
 		42CD0E8E147D8FF60000361E /* ParticleEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DFC147D8FF50000361E /* ParticleEmitter.h */; };
 		42CD0E8F147D8FF60000361E /* Pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DFD147D8FF50000361E /* Pass.cpp */; };
@@ -192,7 +194,6 @@
 		5B04C54C14BFCFE100EB0071 /* MeshSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF3147D8FF50000361E /* MeshSkin.cpp */; };
 		5B04C54D14BFCFE100EB0071 /* Model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF5147D8FF50000361E /* Model.cpp */; };
 		5B04C54E14BFCFE100EB0071 /* Node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF7147D8FF50000361E /* Node.cpp */; };
-		5B04C54F14BFCFE100EB0071 /* Package.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF9147D8FF50000361E /* Package.cpp */; };
 		5B04C55014BFCFE100EB0071 /* ParticleEmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DFB147D8FF50000361E /* ParticleEmitter.cpp */; };
 		5B04C55114BFCFE100EB0071 /* Pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DFD147D8FF50000361E /* Pass.cpp */; };
 		5B04C55214BFCFE100EB0071 /* PhysicsConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DFF147D8FF50000361E /* PhysicsConstraint.cpp */; };
@@ -264,7 +265,6 @@
 		5B04C59F14BFCFE100EB0071 /* MeshSkin.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF4147D8FF50000361E /* MeshSkin.h */; };
 		5B04C5A014BFCFE100EB0071 /* Model.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF6147D8FF50000361E /* Model.h */; };
 		5B04C5A114BFCFE100EB0071 /* Node.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF8147D8FF50000361E /* Node.h */; };
-		5B04C5A214BFCFE100EB0071 /* Package.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DFA147D8FF50000361E /* Package.h */; };
 		5B04C5A314BFCFE100EB0071 /* ParticleEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DFC147D8FF50000361E /* ParticleEmitter.h */; };
 		5B04C5A414BFCFE100EB0071 /* Pass.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DFE147D8FF50000361E /* Pass.h */; };
 		5B04C5A514BFCFE100EB0071 /* PhysicsConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E00147D8FF50000361E /* PhysicsConstraint.h */; };
@@ -391,6 +391,8 @@
 		4208DEE814A4079F00D3C511 /* Image.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Image.inl; path = src/Image.inl; sourceTree = SOURCE_ROOT; };
 		4208DEEB14A407B900D3C511 /* Keyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Keyboard.h; path = src/Keyboard.h; sourceTree = SOURCE_ROOT; };
 		4208DEED14A407D500D3C511 /* Touch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Touch.h; path = src/Touch.h; sourceTree = SOURCE_ROOT; };
+		422260D41537790F0011E3AB /* Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Bundle.cpp; path = src/Bundle.cpp; sourceTree = SOURCE_ROOT; };
+		422260D51537790F0011E3AB /* Bundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Bundle.h; path = src/Bundle.h; sourceTree = SOURCE_ROOT; };
 		4234D99A14686C52003031B3 /* libgameplay.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgameplay.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		4234D99D14686C52003031B3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
 		4251B12E152D049B002F6199 /* ScreenDisplayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScreenDisplayer.h; path = src/ScreenDisplayer.h; sourceTree = SOURCE_ROOT; };
@@ -478,8 +480,6 @@
 		42CD0DF6147D8FF50000361E /* Model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Model.h; path = src/Model.h; sourceTree = SOURCE_ROOT; };
 		42CD0DF7147D8FF50000361E /* Node.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Node.cpp; path = src/Node.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0DF8147D8FF50000361E /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Node.h; path = src/Node.h; sourceTree = SOURCE_ROOT; };
-		42CD0DF9147D8FF50000361E /* Package.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Package.cpp; path = src/Package.cpp; sourceTree = SOURCE_ROOT; };
-		42CD0DFA147D8FF50000361E /* Package.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Package.h; path = src/Package.h; sourceTree = SOURCE_ROOT; };
 		42CD0DFB147D8FF50000361E /* ParticleEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ParticleEmitter.cpp; path = src/ParticleEmitter.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0DFC147D8FF50000361E /* ParticleEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParticleEmitter.h; path = src/ParticleEmitter.h; sourceTree = SOURCE_ROOT; };
 		42CD0DFD147D8FF50000361E /* Pass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Pass.cpp; path = src/Pass.cpp; sourceTree = SOURCE_ROOT; };
@@ -707,6 +707,8 @@
 				42CD0DC7147D8FF50000361E /* BoundingSphere.cpp */,
 				42CD0DC8147D8FF50000361E /* BoundingSphere.h */,
 				42CD0DC9147D8FF50000361E /* BoundingSphere.inl */,
+				422260D41537790F0011E3AB /* Bundle.cpp */,
+				422260D51537790F0011E3AB /* Bundle.h */,
 				5BD52636150F822A004C9099 /* Button.cpp */,
 				5BD52637150F822A004C9099 /* Button.h */,
 				42CD0DCA147D8FF50000361E /* Camera.cpp */,
@@ -779,8 +781,6 @@
 				5BB0823C14C6FEC40019975F /* Mouse.h */,
 				42CD0DF7147D8FF50000361E /* Node.cpp */,
 				42CD0DF8147D8FF50000361E /* Node.h */,
-				42CD0DF9147D8FF50000361E /* Package.cpp */,
-				42CD0DFA147D8FF50000361E /* Package.h */,
 				42CD0DFB147D8FF50000361E /* ParticleEmitter.cpp */,
 				42CD0DFC147D8FF50000361E /* ParticleEmitter.h */,
 				42CD0DFD147D8FF50000361E /* Pass.cpp */,
@@ -998,7 +998,6 @@
 				42CD0E86147D8FF60000361E /* MeshSkin.h in Headers */,
 				42CD0E88147D8FF60000361E /* Model.h in Headers */,
 				42CD0E8A147D8FF60000361E /* Node.h in Headers */,
-				42CD0E8C147D8FF60000361E /* Package.h in Headers */,
 				42CD0E8E147D8FF60000361E /* ParticleEmitter.h in Headers */,
 				42CD0E90147D8FF60000361E /* Pass.h in Headers */,
 				42CD0E92147D8FF60000361E /* PhysicsConstraint.h in Headers */,
@@ -1055,6 +1054,7 @@
 				42554EA3152BC35C000ED910 /* PhysicsCollisionShape.h in Headers */,
 				4251B131152D049B002F6199 /* ScreenDisplayer.h in Headers */,
 				4251B135152D049B002F6199 /* ThemeStyle.h in Headers */,
+				422260D81537790F0011E3AB /* Bundle.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1095,7 +1095,6 @@
 				5B04C59F14BFCFE100EB0071 /* MeshSkin.h in Headers */,
 				5B04C5A014BFCFE100EB0071 /* Model.h in Headers */,
 				5B04C5A114BFCFE100EB0071 /* Node.h in Headers */,
-				5B04C5A214BFCFE100EB0071 /* Package.h in Headers */,
 				5B04C5A314BFCFE100EB0071 /* ParticleEmitter.h in Headers */,
 				5B04C5A414BFCFE100EB0071 /* Pass.h in Headers */,
 				5B04C5A514BFCFE100EB0071 /* PhysicsConstraint.h in Headers */,
@@ -1151,6 +1150,7 @@
 				42554EA4152BC35C000ED910 /* PhysicsCollisionShape.h in Headers */,
 				4251B132152D049B002F6199 /* ScreenDisplayer.h in Headers */,
 				4251B136152D049B002F6199 /* ThemeStyle.h in Headers */,
+				422260D91537790F0011E3AB /* Bundle.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1254,7 +1254,6 @@
 				42CD0E85147D8FF60000361E /* MeshSkin.cpp in Sources */,
 				42CD0E87147D8FF60000361E /* Model.cpp in Sources */,
 				42CD0E89147D8FF60000361E /* Node.cpp in Sources */,
-				42CD0E8B147D8FF60000361E /* Package.cpp in Sources */,
 				42CD0E8D147D8FF60000361E /* ParticleEmitter.cpp in Sources */,
 				42CD0E8F147D8FF60000361E /* Pass.cpp in Sources */,
 				42CD0E91147D8FF60000361E /* PhysicsConstraint.cpp in Sources */,
@@ -1306,6 +1305,7 @@
 				42554EA1152BC35C000ED910 /* PhysicsCollisionShape.cpp in Sources */,
 				4251B133152D049B002F6199 /* ThemeStyle.cpp in Sources */,
 				4271C08E15337C8200B89DA7 /* Layout.cpp in Sources */,
+				422260D61537790F0011E3AB /* Bundle.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1344,7 +1344,6 @@
 				5B04C54C14BFCFE100EB0071 /* MeshSkin.cpp in Sources */,
 				5B04C54D14BFCFE100EB0071 /* Model.cpp in Sources */,
 				5B04C54E14BFCFE100EB0071 /* Node.cpp in Sources */,
-				5B04C54F14BFCFE100EB0071 /* Package.cpp in Sources */,
 				5B04C55014BFCFE100EB0071 /* ParticleEmitter.cpp in Sources */,
 				5B04C55114BFCFE100EB0071 /* Pass.cpp in Sources */,
 				5B04C55214BFCFE100EB0071 /* PhysicsConstraint.cpp in Sources */,
@@ -1397,6 +1396,7 @@
 				42554EA2152BC35C000ED910 /* PhysicsCollisionShape.cpp in Sources */,
 				4251B134152D049B002F6199 /* ThemeStyle.cpp in Sources */,
 				4271C08F15337C8200B89DA7 /* Layout.cpp in Sources */,
+				422260D71537790F0011E3AB /* Bundle.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 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)
 {
     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)
     : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0), _defaultClip(NULL), _clips(NULL)
 {
     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)
@@ -67,6 +73,7 @@ Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int p
     assert(_target->getAnimationPropertyComponentCount(propertyId));
     _curve->addRef();
     _target->addChannel(this);
+    _animation->addRef();
 }
 
 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();
     _target->addChannel(this);
+    _animation->addRef();
 }
 
 Animation::Channel::~Channel()
@@ -388,9 +396,15 @@ void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId
     return;
 }
 
-Animation* Animation::clone()
+Animation* Animation::clone(Channel* channel, AnimationTarget* target)
 {
     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;
 }
 

+ 5 - 2
gameplay/src/Animation.h

@@ -24,7 +24,7 @@ class Animation : public Ref
 {
     friend class AnimationClip;
     friend class AnimationTarget;
-    friend class Package;
+    friend class Bundle;
 
 public:
     
@@ -201,9 +201,12 @@ private:
     /**
      * 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.
      */
-    Animation* clone();
+    Animation* clone(Channel* channel, AnimationTarget* target);
     
     AnimationController* _controller;       // The AnimationController that this Animation will run on.
     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;
             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);
-            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);
         }
     }
 }

+ 111 - 112
gameplay/src/Package.cpp → gameplay/src/Bundle.cpp

@@ -1,50 +1,50 @@
 #include "Base.h"
-#include "Package.h"
+#include "Bundle.h"
 #include "FileSystem.h"
 #include "MeshPart.h"
 #include "Scene.h"
 #include "Joint.h"
 
-#define GPB_PACKAGE_VERSION_MAJOR 1
-#define GPB_PACKAGE_VERSION_MINOR 1
-
-#define PACKAGE_TYPE_SCENE 1
-#define PACKAGE_TYPE_NODE 2
-#define PACKAGE_TYPE_ANIMATIONS 3
-#define PACKAGE_TYPE_ANIMATION 4
-#define PACKAGE_TYPE_ANIMATION_CHANNEL 5
-#define PACKAGE_TYPE_MMODEL 10
-#define PACKAGE_TYPE_MATERIAL 16
-#define PACKAGE_TYPE_EFFECT 18
-#define PACKAGE_TYPE_CAMERA 32
-#define PACKAGE_TYPE_LIGHT 33
-#define PACKAGE_TYPE_MESH 34
-#define PACKAGE_TYPE_MESHPART 35
-#define PACKAGE_TYPE_MESHSKIN 36
-#define PACKAGE_TYPE_FONT 128
+#define BUNDLE_VERSION_MAJOR            1
+#define BUNDLE_VERSION_MINOR            1
+
+#define BUNDLE_TYPE_SCENE               1
+#define BUNDLE_TYPE_NODE                2
+#define BUNDLE_TYPE_ANIMATIONS          3
+#define BUNDLE_TYPE_ANIMATION           4
+#define BUNDLE_TYPE_ANIMATION_CHANNEL   5
+#define BUNDLE_TYPE_MODEL               10
+#define BUNDLE_TYPE_MATERIAL            16
+#define BUNDLE_TYPE_EFFECT              18
+#define BUNDLE_TYPE_CAMERA              32
+#define BUNDLE_TYPE_LIGHT               33
+#define BUNDLE_TYPE_MESH                34
+#define BUNDLE_TYPE_MESHPART            35
+#define BUNDLE_TYPE_MESHSKIN            36
+#define BUNDLE_TYPE_FONT                128
 
 // For sanity checking string reads
-#define PACKAGE_MAX_STRING_LENGTH 5000
+#define BUNDLE_MAX_STRING_LENGTH        5000
 
 namespace gameplay
 {
 
-static std::vector<Package*> __packageCache;
+static std::vector<Bundle*> __bundleCache;
 
-Package::Package(const char* path) :
+Bundle::Bundle(const char* path) :
     _path(path), _referenceCount(0), _references(NULL), _file(NULL)
 {
 }
 
-Package::~Package()
+Bundle::~Bundle()
 {
     clearLoadSession();
 
-    // Remove this Package from the cache
-    std::vector<Package*>::iterator itr = std::find(__packageCache.begin(), __packageCache.end(), this);
-    if (itr != __packageCache.end())
+    // Remove this Bundle from the cache
+    std::vector<Bundle*>::iterator itr = std::find(__bundleCache.begin(), __bundleCache.end(), this);
+    if (itr != __bundleCache.end())
     {
-        __packageCache.erase(itr);
+        __bundleCache.erase(itr);
     }
 
     SAFE_DELETE_ARRAY(_references);
@@ -57,7 +57,7 @@ Package::~Package()
 }
 
 template <class T>
-bool Package::readArray(unsigned int* length, T** ptr)
+bool Bundle::readArray(unsigned int* length, T** ptr)
 {
     if (!read(length))
     {
@@ -76,7 +76,7 @@ bool Package::readArray(unsigned int* length, T** ptr)
 }
 
 template <class T>
-bool Package::readArray(unsigned int* length, std::vector<T>* values)
+bool Bundle::readArray(unsigned int* length, std::vector<T>* values)
 {
     if (!read(length))
     {
@@ -94,7 +94,7 @@ bool Package::readArray(unsigned int* length, std::vector<T>* values)
 }
 
 template <class T>
-bool Package::readArray(unsigned int* length, std::vector<T>* values, unsigned int readSize)
+bool Bundle::readArray(unsigned int* length, std::vector<T>* values, unsigned int readSize)
 {
     assert(sizeof(T) >= readSize);
 
@@ -122,7 +122,7 @@ std::string readString(FILE* fp)
     }
 
     // Sanity check to detect if string length is far too big
-    assert(length < PACKAGE_MAX_STRING_LENGTH);
+    assert(length < BUNDLE_MAX_STRING_LENGTH);
 
     std::string str;
     if (length > 0)
@@ -136,12 +136,12 @@ std::string readString(FILE* fp)
     return str;
 }
 
-Package* Package::create(const char* path)
+Bundle* Bundle::create(const char* path)
 {
-    // Search the cache for this package
-    for (unsigned int i = 0, count = __packageCache.size(); i < count; ++i)
+    // Search the cache for this bundle
+    for (unsigned int i = 0, count = __bundleCache.size(); i < count; ++i)
     {
-        Package* p = __packageCache[i];
+        Bundle* p = __bundleCache[i];
         if (p->_path == path)
         {
             // Found a match
@@ -150,7 +150,7 @@ Package* Package::create(const char* path)
         }
     }
 
-    // Open the package
+    // Open the bundle
     FILE* fp = FileSystem::openFile(path, "rb");
     if (!fp)
     {
@@ -162,16 +162,16 @@ Package* Package::create(const char* path)
     char sig[9];
     if (fread(sig, 1, 9, fp) != 9 || memcmp(sig, "«GPB»\r\n\x1A\n", 9) != 0)
     {
-        LOG_ERROR_VARG("Invalid package header: %s", path);
+        LOG_ERROR_VARG("Invalid bundle header: %s", path);
         fclose(fp);
         return NULL;
     }
 
     // Read version
     unsigned char ver[2];
-    if (fread(ver, 1, 2, fp) != 2 || ver[0] != GPB_PACKAGE_VERSION_MAJOR || ver[1] != GPB_PACKAGE_VERSION_MINOR)
+    if (fread(ver, 1, 2, fp) != 2 || ver[0] != BUNDLE_VERSION_MAJOR || ver[1] != BUNDLE_VERSION_MINOR)
     {
-        LOG_ERROR_VARG("Unsupported version (%d.%d) for package: %s (expected %d.%d)", (int)ver[0], (int)ver[1], path, GPB_PACKAGE_VERSION_MAJOR, GPB_PACKAGE_VERSION_MINOR);
+        LOG_ERROR_VARG("Unsupported version (%d.%d) for bundle: %s (expected %d.%d)", (int)ver[0], (int)ver[1], path, BUNDLE_VERSION_MAJOR, BUNDLE_VERSION_MINOR);
         fclose(fp);
         return NULL;
     }
@@ -199,7 +199,7 @@ Package* Package::create(const char* path)
     }
 
     // Keep file open for faster reading later
-    Package* pkg = new Package(path);
+    Bundle* pkg = new Bundle(path);
     pkg->_referenceCount = refCount;
     pkg->_references = refs;
     pkg->_file = fp;
@@ -207,7 +207,7 @@ Package* Package::create(const char* path)
     return pkg;
 }
 
-Package::Reference* Package::find(const char* id) const
+Bundle::Reference* Bundle::find(const char* id) const
 {
     // Search the ref table for the given id (case-sensitive)
     for (unsigned int i = 0; i < _referenceCount; ++i)
@@ -222,7 +222,7 @@ Package::Reference* Package::find(const char* id) const
     return NULL;
 }
 
-void Package::clearLoadSession()
+void Bundle::clearLoadSession()
 {
     for (unsigned int i = 0, count = _meshSkins.size(); i < count; ++i)
     {
@@ -231,12 +231,12 @@ void Package::clearLoadSession()
     _meshSkins.clear();
 }
 
-const char* Package::getIdFromOffset() const
+const char* Bundle::getIdFromOffset() const
 {
     return getIdFromOffset((unsigned int) ftell(_file));
 }
 
-const char* Package::getIdFromOffset(unsigned int offset) const
+const char* Bundle::getIdFromOffset(unsigned int offset) const
 {
     // Search the ref table for the given offset
     if (offset > 0)
@@ -252,32 +252,32 @@ const char* Package::getIdFromOffset(unsigned int offset) const
     return NULL;
 }
 
-Package::Reference* Package::seekTo(const char* id, unsigned int type)
+Bundle::Reference* Bundle::seekTo(const char* id, unsigned int type)
 {
     Reference* ref = find(id);
     if (ref == NULL)
     {
-        LOG_ERROR_VARG("No object with name '%s' in package '%s'.", id, _path.c_str());
+        LOG_ERROR_VARG("No object with name '%s' in bundle '%s'.", id, _path.c_str());
         return NULL;
     }
 
     if (ref->type != type)
     {
-        LOG_ERROR_VARG("Object '%s' in package '%s' has type %d (expected type %d).", id, _path.c_str(), (int)ref->type, (int)type);
+        LOG_ERROR_VARG("Object '%s' in bundle '%s' has type %d (expected type %d).", id, _path.c_str(), (int)ref->type, (int)type);
         return NULL;
     }
 
     // Seek to the offset of this object
     if (fseek(_file, ref->offset, SEEK_SET) != 0)
     {
-        LOG_ERROR_VARG("Failed to seek to object '%s' in package '%s'.", id, _path.c_str());
+        LOG_ERROR_VARG("Failed to seek to object '%s' in bundle '%s'.", id, _path.c_str());
         return NULL;
     }
 
     return ref;
 }
 
-Package::Reference* Package::seekToFirstType(unsigned int type)
+Bundle::Reference* Bundle::seekToFirstType(unsigned int type)
 {
     // for each Reference
     for (unsigned int i = 0; i < _referenceCount; ++i)
@@ -288,7 +288,7 @@ Package::Reference* Package::seekToFirstType(unsigned int type)
             // Found a match
             if (fseek(_file, ref->offset, SEEK_SET) != 0)
             {
-                LOG_ERROR_VARG("Failed to seek to object '%s' in package '%s'.", ref->id.c_str(), _path.c_str());
+                LOG_ERROR_VARG("Failed to seek to object '%s' in bundle '%s'.", ref->id.c_str(), _path.c_str());
                 return NULL;
             }
             return ref;
@@ -297,38 +297,38 @@ Package::Reference* Package::seekToFirstType(unsigned int type)
     return NULL;
 }
 
-bool Package::read(unsigned int* ptr)
+bool Bundle::read(unsigned int* ptr)
 {
     return fread(ptr, sizeof(unsigned int), 1, _file) == 1;
 }
 
-bool Package::read(unsigned char* ptr)
+bool Bundle::read(unsigned char* ptr)
 {
     return fread(ptr, sizeof(unsigned char), 1, _file) == 1;
 }
 
-bool Package::read(float* ptr)
+bool Bundle::read(float* ptr)
 {
     return fread(ptr, sizeof(float), 1, _file) == 1;
 }
 
-bool Package::readMatrix(float* m)
+bool Bundle::readMatrix(float* m)
 {
     return (fread(m, sizeof(float), 16, _file) == 16);
 }
 
-Scene* Package::loadScene(const char* id)
+Scene* Bundle::loadScene(const char* id)
 {
     clearLoadSession();
 
     Reference* ref = NULL;
     if (id)
     {
-        ref = seekTo(id, PACKAGE_TYPE_SCENE);
+        ref = seekTo(id, BUNDLE_TYPE_SCENE);
     }
     else
     {
-        ref = seekToFirstType(PACKAGE_TYPE_SCENE);
+        ref = seekToFirstType(BUNDLE_TYPE_SCENE);
     }
     if (!ref)
     {
@@ -393,12 +393,12 @@ Scene* Package::loadScene(const char* id)
     for (unsigned int i = 0; i < _referenceCount; ++i)
     {
         Reference* ref = &_references[i];
-        if (ref->type == PACKAGE_TYPE_ANIMATIONS)
+        if (ref->type == BUNDLE_TYPE_ANIMATIONS)
         {
             // Found a match
             if (fseek(_file, ref->offset, SEEK_SET) != 0)
             {
-                LOG_ERROR_VARG("Failed to seek to object '%s' in package '%s'.", ref->id.c_str(), _path.c_str());
+                LOG_ERROR_VARG("Failed to seek to object '%s' in bundle '%s'.", ref->id.c_str(), _path.c_str());
                 return NULL;
             }
             readAnimations(scene);
@@ -410,7 +410,7 @@ Scene* Package::loadScene(const char* id)
     return scene;
 }
 
-Node* Package::loadNode(const char* id)
+Node* Bundle::loadNode(const char* id)
 {
     assert(id);
 
@@ -426,7 +426,7 @@ Node* Package::loadNode(const char* id)
     return node;
 }
 
-Node* Package::loadNode(const char* id, Scene* sceneContext, Node* nodeContext)
+Node* Bundle::loadNode(const char* id, Scene* sceneContext, Node* nodeContext)
 {
     assert(id);
 
@@ -446,7 +446,7 @@ Node* Package::loadNode(const char* id, Scene* sceneContext, Node* nodeContext)
     if (node == NULL)
     {
         // If not yet found, search the ref table and read
-        Reference* ref = seekTo(id, PACKAGE_TYPE_NODE);
+        Reference* ref = seekTo(id, BUNDLE_TYPE_NODE);
         if (ref == NULL)
         {
             return NULL;
@@ -458,7 +458,7 @@ Node* Package::loadNode(const char* id, Scene* sceneContext, Node* nodeContext)
     return node;
 }
 
-Node* Package::readNode(Scene* sceneContext, Node* nodeContext)
+Node* Bundle::readNode(Scene* sceneContext, Node* nodeContext)
 {
     const char* id = getIdFromOffset();
 
@@ -545,12 +545,12 @@ Node* Package::readNode(Scene* sceneContext, Node* nodeContext)
     return node;
 }
 
-Camera* Package::readCamera()
+Camera* Bundle::readCamera()
 {
     unsigned char cameraType;
     if (!read(&cameraType))
     {
-        LOG_ERROR_VARG("Failed to load camera type in package '%s'.", _path.c_str());
+        LOG_ERROR_VARG("Failed to load camera type in bundle '%s'.", _path.c_str());
     }
 
     if (cameraType == 0)
@@ -562,21 +562,21 @@ Camera* Package::readCamera()
     float aspectRatio;
     if (!read(&aspectRatio))
     {
-        LOG_ERROR_VARG("Failed to load camera aspectRatio in package '%s'.", _path.c_str());
+        LOG_ERROR_VARG("Failed to load camera aspectRatio in bundle '%s'.", _path.c_str());
     }
 
     // near plane
     float nearPlane;
     if (!read(&nearPlane))
     {
-        LOG_ERROR_VARG("Failed to load camera near plane in package '%s'.", _path.c_str());
+        LOG_ERROR_VARG("Failed to load camera near plane in bundle '%s'.", _path.c_str());
     }
 
     // far plane
     float farPlane;
     if (!read(&farPlane))
     {
-        LOG_ERROR_VARG("Failed to load camera far plane in package '%s'.", _path.c_str());
+        LOG_ERROR_VARG("Failed to load camera far plane in bundle '%s'.", _path.c_str());
     }
 
     Camera* camera = NULL;
@@ -586,7 +586,7 @@ Camera* Package::readCamera()
         float fieldOfView;
         if (!read(&fieldOfView))
         {
-            LOG_ERROR_VARG("Failed to load camera field of view in package '%s'.", _path.c_str());
+            LOG_ERROR_VARG("Failed to load camera field of view in bundle '%s'.", _path.c_str());
         }
 
         camera = Camera::createPerspective(fieldOfView, aspectRatio, nearPlane, farPlane);
@@ -597,30 +597,30 @@ Camera* Package::readCamera()
         float zoomX;
         if (!read(&zoomX))
         {
-            LOG_ERROR_VARG("Failed to load camera zoomX in package '%s'.", _path.c_str());
+            LOG_ERROR_VARG("Failed to load camera zoomX in bundle '%s'.", _path.c_str());
         }
 
         float zoomY;
         if (!read(&zoomY))
         {
-            LOG_ERROR_VARG("Failed to load camera zoomY in package '%s'.", _path.c_str());
+            LOG_ERROR_VARG("Failed to load camera zoomY in bundle '%s'.", _path.c_str());
         }
 
         camera = Camera::createOrthographic(zoomX, zoomY, aspectRatio, nearPlane, farPlane);
     }
     else
     {
-        LOG_ERROR_VARG("Failed to load camera type in package '%s'. Invalid camera type.", _path.c_str());
+        LOG_ERROR_VARG("Failed to load camera type in bundle '%s'. Invalid camera type.", _path.c_str());
     }
     return camera;
 }
 
-Light* Package::readLight()
+Light* Bundle::readLight()
 {
     unsigned char type;
     if (!read(&type))
     {
-        LOG_ERROR_VARG("Failed to load light %s in package '%s'.", "type", _path.c_str());
+        LOG_ERROR_VARG("Failed to load light %s in bundle '%s'.", "type", _path.c_str());
     }
 
     if (type == 0)
@@ -632,7 +632,7 @@ Light* Package::readLight()
     float red, blue, green;
     if (!read(&red) || !read(&blue) || !read(&green))
     {
-        LOG_ERROR_VARG("Failed to load light %s in package '%s'.", "color", _path.c_str());
+        LOG_ERROR_VARG("Failed to load light %s in bundle '%s'.", "color", _path.c_str());
     }
     Vector3 color(red, blue, green);
 
@@ -646,7 +646,7 @@ Light* Package::readLight()
         float range;
         if (!read(&range))
         {
-            LOG_ERROR_VARG("Failed to load point light %s in package '%s'.", "point", _path.c_str());
+            LOG_ERROR_VARG("Failed to load point light %s in bundle '%s'.", "point", _path.c_str());
         }
         light = Light::createPoint(color, range);
     }
@@ -655,18 +655,18 @@ Light* Package::readLight()
         float range, innerAngle, outerAngle;
         if (!read(&range) || !read(&innerAngle) || !read(&outerAngle))
         {
-            LOG_ERROR_VARG("Failed to load spot light %s in package '%s'.", "spot", _path.c_str());
+            LOG_ERROR_VARG("Failed to load spot light %s in bundle '%s'.", "spot", _path.c_str());
         }
         light = Light::createSpot(color, range, innerAngle, outerAngle);
     }
     else
     {
-        LOG_ERROR_VARG("Failed to load light %s in package '%s'.", "type", _path.c_str());
+        LOG_ERROR_VARG("Failed to load light %s in bundle '%s'.", "type", _path.c_str());
     }
     return light;
 }
 
-Model* Package::readModel(Scene* sceneContext, Node* nodeContext, const char* nodeId)
+Model* Bundle::readModel(Scene* sceneContext, Node* nodeContext, const char* nodeId)
 {
     // Read mesh
     Mesh* mesh = NULL;
@@ -683,7 +683,7 @@ Model* Package::readModel(Scene* sceneContext, Node* nodeContext, const char* no
             unsigned char hasSkin;
             if (!read(&hasSkin))
             {
-                LOG_ERROR_VARG("Failed to load hasSkin in package '%s'.", _path.c_str());
+                LOG_ERROR_VARG("Failed to load hasSkin in bundle '%s'.", _path.c_str());
                 return NULL;
             }
             if (hasSkin)
@@ -698,7 +698,7 @@ Model* Package::readModel(Scene* sceneContext, Node* nodeContext, const char* no
             unsigned int materialCount;
             if (!read(&materialCount))
             {
-                LOG_ERROR_VARG("Failed to load materialCount in package '%s'.", _path.c_str());
+                LOG_ERROR_VARG("Failed to load materialCount in bundle '%s'.", _path.c_str());
                 return NULL;
             }
             if (materialCount > 0)
@@ -712,7 +712,7 @@ Model* Package::readModel(Scene* sceneContext, Node* nodeContext, const char* no
     return NULL;
 }
 
-MeshSkin* Package::readMeshSkin(Scene* sceneContext, Node* nodeContext)
+MeshSkin* Bundle::readMeshSkin(Scene* sceneContext, Node* nodeContext)
 {
     MeshSkin* meshSkin = new MeshSkin();
 
@@ -720,7 +720,7 @@ MeshSkin* Package::readMeshSkin(Scene* sceneContext, Node* nodeContext)
     float bindShape[16];
     if (!readMatrix(bindShape))
     {
-        LOG_ERROR_VARG("Failed to load MeshSkin in package '%s'.", _path.c_str());
+        LOG_ERROR_VARG("Failed to load MeshSkin in bundle '%s'.", _path.c_str());
         SAFE_DELETE(meshSkin);
         return NULL;
     }
@@ -733,7 +733,7 @@ MeshSkin* Package::readMeshSkin(Scene* sceneContext, Node* nodeContext)
     unsigned int jointCount;
     if (!read(&jointCount))
     {
-        LOG_ERROR_VARG("Failed to load MeshSkin in package '%s'.", _path.c_str());
+        LOG_ERROR_VARG("Failed to load MeshSkin in bundle '%s'.", _path.c_str());
         SAFE_DELETE(meshSkin);
         SAFE_DELETE(skinData);
         return NULL;
@@ -756,7 +756,7 @@ MeshSkin* Package::readMeshSkin(Scene* sceneContext, Node* nodeContext)
     unsigned int jointsBindPosesCount;
     if (!read(&jointsBindPosesCount))
     {
-        LOG_ERROR_VARG("Failed to load MeshSkin in package '%s'.", _path.c_str());
+        LOG_ERROR_VARG("Failed to load MeshSkin in bundle '%s'.", _path.c_str());
         SAFE_DELETE(meshSkin);
         SAFE_DELETE(skinData);
         return NULL;
@@ -769,7 +769,7 @@ MeshSkin* Package::readMeshSkin(Scene* sceneContext, Node* nodeContext)
         {
             if (!readMatrix(m))
             {
-                LOG_ERROR_VARG("Failed to load MeshSkin in package '%s'.", _path.c_str());
+                LOG_ERROR_VARG("Failed to load MeshSkin in bundle '%s'.", _path.c_str());
                 SAFE_DELETE(meshSkin);
                 SAFE_DELETE(skinData);
                 return NULL;
@@ -784,7 +784,7 @@ MeshSkin* Package::readMeshSkin(Scene* sceneContext, Node* nodeContext)
     return meshSkin;
 }
 
-void Package::resolveJointReferences(Scene* sceneContext, Node* nodeContext)
+void Bundle::resolveJointReferences(Scene* sceneContext, Node* nodeContext)
 {
     const unsigned int skinCount = _meshSkins.size();
     for (unsigned int i = 0; i < skinCount; ++i)
@@ -834,7 +834,7 @@ void Package::resolveJointReferences(Scene* sceneContext, Node* nodeContext)
     _meshSkins.clear();
 }
 
-void Package::readAnimation(Scene* scene)
+void Bundle::readAnimation(Scene* scene)
 {
     const std::string animationId = readString(_file);
 
@@ -854,7 +854,7 @@ void Package::readAnimation(Scene* scene)
     }
 }
 
-void Package::readAnimations(Scene* scene)
+void Bundle::readAnimations(Scene* scene)
 {
     // read the number of animations in this object
     unsigned int animationCount;
@@ -870,7 +870,7 @@ void Package::readAnimations(Scene* scene)
     }
 }
 
-Animation* Package::readAnimationChannel(Scene* scene, Animation* animation, const char* animationId)
+Animation* Bundle::readAnimationChannel(Scene* scene, Animation* animation, const char* animationId)
 {
     const char* id = animationId;
 
@@ -969,25 +969,24 @@ Animation* Package::readAnimationChannel(Scene* scene, Animation* animation, con
         else
         {
             animation->createChannel(target, targetAttribute, keyTimesCount, &keyTimes[0], &values[0], Curve::LINEAR);
-            animation->addRef();
         }
     }
 
     return animation;
 }
 
-Mesh* Package::loadMesh(const char* id)
+Mesh* Bundle::loadMesh(const char* id)
 {
     return loadMesh(id, false);
 }
 
-Mesh* Package::loadMesh(const char* id, const char* nodeId)
+Mesh* Bundle::loadMesh(const char* id, const char* nodeId)
 {
     // Save the file position
     long position = ftell(_file);
 
     // Seek to the specified Mesh
-    Reference* ref = seekTo(id, PACKAGE_TYPE_MESH);
+    Reference* ref = seekTo(id, BUNDLE_TYPE_MESH);
     if (ref == NULL)
     {
         return NULL;
@@ -1041,7 +1040,7 @@ Mesh* Package::loadMesh(const char* id, const char* nodeId)
     return mesh;
 }
 
-Package::MeshData* Package::readMeshData()
+Bundle::MeshData* Bundle::readMeshData()
 {
     // Read vertex format/elements
     unsigned int vertexElementCount;
@@ -1146,7 +1145,7 @@ Package::MeshData* Package::readMeshData()
     return meshData;
 }
 
-Package::MeshData* Package::readMeshData(const char* url)
+Bundle::MeshData* Bundle::readMeshData(const char* url)
 {
     assert(url);
 
@@ -1154,7 +1153,7 @@ Package::MeshData* Package::readMeshData(const char* url)
     if (len == 0)
         return NULL;
 
-    // Parse URL (formatted as 'package#id')
+    // Parse URL (formatted as 'bundle#id')
     std::string urlstring(url);
     unsigned int pos = urlstring.find('#');
     if (pos == std::string::npos)
@@ -1163,13 +1162,13 @@ Package::MeshData* Package::readMeshData(const char* url)
     std::string file = urlstring.substr(0, pos);
     std::string id = urlstring.substr(pos + 1);
 
-    // Load package
-    Package* pkg = Package::create(file.c_str());
+    // Load bundle
+    Bundle* pkg = Bundle::create(file.c_str());
     if (pkg == NULL)
         return NULL;
 
-    // Seek to mesh with specified ID in package
-    Reference* ref = pkg->seekTo(id.c_str(), PACKAGE_TYPE_MESH);
+    // Seek to mesh with specified ID in bundle
+    Reference* ref = pkg->seekTo(id.c_str(), BUNDLE_TYPE_MESH);
     if (ref == NULL)
         return NULL;
 
@@ -1181,10 +1180,10 @@ Package::MeshData* Package::readMeshData(const char* url)
     return meshData;
 }
 
-Font* Package::loadFont(const char* id)
+Font* Bundle::loadFont(const char* id)
 {
     // Seek to the specified Font
-    Reference* ref = seekTo(id, PACKAGE_TYPE_FONT);
+    Reference* ref = seekTo(id, BUNDLE_TYPE_FONT);
     if (ref == NULL)
     {
         return NULL;
@@ -1281,7 +1280,7 @@ Font* Package::loadFont(const char* id)
     return font;
 }
 
-void Package::setTransform(const float* values, Transform* transform)
+void Bundle::setTransform(const float* values, Transform* transform)
 {
     // Load array into transform
     Matrix matrix(values);
@@ -1293,46 +1292,46 @@ void Package::setTransform(const float* values, Transform* transform)
     transform->setRotation(rotation);
 }
 
-bool Package::contains(const char* id) const
+bool Bundle::contains(const char* id) const
 {
     return (find(id) != NULL);
 }
 
-unsigned int Package::getObjectCount() const
+unsigned int Bundle::getObjectCount() const
 {
     return _referenceCount;
 }
 
-const char* Package::getObjectID(unsigned int index) const
+const char* Bundle::getObjectID(unsigned int index) const
 {
     return (index >= _referenceCount ? NULL : _references[index].id.c_str());
 }
 
-Package::Reference::Reference()
+Bundle::Reference::Reference()
     : type(0), offset(0)
 {
 }
 
-Package::Reference::~Reference()
+Bundle::Reference::~Reference()
 {
 }
 
-Package::MeshPartData::MeshPartData() :
+Bundle::MeshPartData::MeshPartData() :
     indexCount(0), indexData(NULL)
 {
 }
 
-Package::MeshPartData::~MeshPartData()
+Bundle::MeshPartData::~MeshPartData()
 {
     SAFE_DELETE_ARRAY(indexData);
 }
 
-Package::MeshData::MeshData(const VertexFormat& vertexFormat)
+Bundle::MeshData::MeshData(const VertexFormat& vertexFormat)
     : vertexFormat(vertexFormat), vertexCount(0), vertexData(NULL)
 {
 }
 
-Package::MeshData::~MeshData()
+Bundle::MeshData::~MeshData()
 {
     SAFE_DELETE_ARRAY(vertexData);
 

+ 24 - 24
gameplay/src/Package.h → gameplay/src/Bundle.h

@@ -1,5 +1,5 @@
-#ifndef PACKAGE_H_
-#define PACKAGE_H_
+#ifndef BUNDLE_H_
+#define BUNDLE_H_
 
 #include "Mesh.h"
 #include "Font.h"
@@ -10,29 +10,29 @@ namespace gameplay
 {
 
 /**
- * Represents a gameplay binary package file (.gpb) that contains a
- * collection of game resources that can be loaded.
+ * Represents a gameplay bundle file (.gpb) that contains a
+ * collection of binary game assets that can be loaded.
  */
-class Package : public Ref
+class Bundle : public Ref
 {
     friend class PhysicsController;
 
 public:
 
     /**
-     * Returns a Package for the given resource path.
+     * Returns a Bundle for the given resource path.
      *
-     * The specified path must reference a valid gameplay binary file.
-     * If the package is already loaded, the existing package is returned
+     * The specified path must reference a valid gameplay bundle file.
+     * If the bundle is already loaded, the existing bundle is returned
      * with its reference count incremented. When no longer needed, the
      * release() method must be called. Note that calling release() does
-     * NOT free any actual game objects created/returned from the Package
+     * NOT free any actual game objects created/returned from the Bundle
      * instance and those objects must be released separately.
      */
-    static Package* create(const char* path);
+    static Bundle* create(const char* path);
 
     /**
-     * Loads the scene with the specified ID from the package.
+     * Loads the scene with the specified ID from the bundle.
      * If id is NULL then the first scene found is loaded.
      * 
      * @param id The ID of the scene to load (NULL to load the first scene).
@@ -42,16 +42,16 @@ public:
     Scene* loadScene(const char* id = NULL);
 
     /**
-     * Loads a node with the specified ID from the package.
+     * Loads a node with the specified ID from the bundle.
      *
-     * @param id The ID of the node to load in the package.
+     * @param id The ID of the node to load in the bundle.
      * 
      * @return The loaded node, or NULL if the node could not be loaded.
      */
     Node* loadNode(const char* id);
 
     /**
-     * Loads a mesh with the specified ID from the package.
+     * Loads a mesh with the specified ID from the bundle.
      *
      * @param id The ID of the mesh to load.
      * 
@@ -60,7 +60,7 @@ public:
     Mesh* loadMesh(const char* id);
 
     /**
-     * Loads a font with the specified ID from the package.
+     * Loads a font with the specified ID from the bundle.
      *
      * @param id The ID of the font to load.
      * 
@@ -69,7 +69,7 @@ public:
     Font* loadFont(const char* id);
 
     /**
-     * Determines if this package contains a top-level object with the given ID.
+     * Determines if this bundle contains a top-level object with the given ID.
      *
      * This method performs a case-sensitive comparison.
      *
@@ -78,12 +78,12 @@ public:
     bool contains(const char* id) const;
 
     /**
-     * Returns the number of top-level objects in this package.
+     * Returns the number of top-level objects in this bundle.
      */
     unsigned int getObjectCount() const;
 
     /**
-     * Returns the unique identifier of the top-level object at the specified index in this package.
+     * Returns the unique identifier of the top-level object at the specified index in this bundle.
      *
      * @param index The index of the object.
      * 
@@ -143,12 +143,12 @@ private:
         std::vector<MeshPartData*> parts;
     };
 
-    Package(const char* path);
+    Bundle(const char* path);
 
     /**
      * Destructor.
      */
-    ~Package();
+    ~Bundle();
 
     /**
      * Finds a reference by ID.
@@ -156,7 +156,7 @@ private:
     Reference* find(const char* id) const;
 
     /**
-     * Resets any load session specific state for the package.
+     * Resets any load session specific state for the bundle.
      */
     void clearLoadSession();
 
@@ -206,7 +206,7 @@ private:
     Node* loadNode(const char* id, Scene* sceneContext, Node* nodeContext);
 
     /**
-     * Loads a mesh with the specified ID from the package.
+     * Loads a mesh with the specified ID from the bundle.
      *
      * @param id The ID of the mesh to load.
      * @param nodeId The id of the mesh's model's parent node.
@@ -331,8 +331,8 @@ private:
     /**
      * Reads mesh data for the specified URL.
      *
-     * The specified URL should be formatted as 'package#id', where
-     * 'package' is the package file containing the mesh and 'id' is the ID
+     * The specified URL should be formatted as 'bundle#id', where
+     * 'bundle' is the bundle file containing the mesh and 'id' is the ID
      * of the mesh to read data for.
      *
      * @param url The URL to read mesh data from.

+ 3 - 3
gameplay/src/CheckBox.cpp

@@ -23,7 +23,7 @@ CheckBox* CheckBox::create(Theme::Style* style, Properties* properties)
 {
     CheckBox* checkBox = new CheckBox();
     checkBox->initialize(style, properties);
-    properties->getVector2("iconSize", &checkBox->_imageSize);
+    properties->getVector2("imageSize", &checkBox->_imageSize);
     checkBox->_checked = properties->getBool("checked");
 
     return checkBox;
@@ -123,8 +123,8 @@ void CheckBox::update(const Rectangle& clip)
     }
     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)

+ 3 - 12
gameplay/src/Control.cpp

@@ -614,16 +614,12 @@ namespace gameplay
         float clipX2 = clip.x + clip.width;
         float x2 = x + width;
         if (x2 > clipX2)
-        {
             width = clipX2 - x;
-        }
 
         float clipY2 = clip.y + clip.height;
         float y2 = y + height;
         if (y2 > clipY2)
-        {
             height = clipY2 - y;
-        }
 
         _clipBounds.set(_bounds.x, _bounds.y, width, height);
 
@@ -641,32 +637,27 @@ namespace gameplay
         clipX2 = clip.x + clip.width;
         x2 = x + width;
         if (x2 > clipX2)
-        {
             width = clipX2 - x;
-        }
 
         clipY2 = clip.y + clip.height;
         y2 = y + height;
         if (y2 > clipY2)
-        {
             height = clipY2 - y;
-        }
 
         if (x < clip.x)
-        {
             x = clip.x;
-        }
 
         if (y < clip.y)
-        {
             y = clip.y;
-        }
 
         _clip.set(x, y, width, height);
     }
 
     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);
 
         // Get the border and background images for this control's current state.

+ 5 - 5
gameplay/src/Font.cpp

@@ -2,7 +2,7 @@
 #include "Font.h"
 #include "Game.h"
 #include "FileSystem.h"
-#include "Package.h"
+#include "Bundle.h"
 
 // Default font vertex shader
 #define FONT_VSH \
@@ -78,8 +78,8 @@ Font* Font::create(const char* path, const char* id)
         }
     }
 
-    // Load the package.
-    Package* pkg = Package::create(path);
+    // Load the bundle.
+    Bundle* pkg = Bundle::create(path);
     if (pkg == NULL)
     {
         return NULL;
@@ -89,14 +89,14 @@ Font* Font::create(const char* path, const char* id)
 
     if (id == NULL)
     {
-        // Get the ID of the first/only object in the package (assume it's a Font).
+        // Get the ID of the first/only object in the bundle (assume it's a Font).
         const char* id;
         if (pkg->getObjectCount() != 1 || (id = pkg->getObjectID(0)) == NULL)
         {
             return NULL;
         }
 
-        // Load the font using the ID of the first object in the package.
+        // Load the font using the ID of the first object in the bundle.
         font = pkg->loadFont(pkg->getObjectID(0));
     }
     else

+ 6 - 6
gameplay/src/Font.h

@@ -11,7 +11,7 @@ namespace gameplay
  */
 class Font : public Ref
 {
-    friend class Package;
+    friend class Bundle;
     friend class TextBox;
 
 public:
@@ -77,17 +77,17 @@ public:
     };
 
     /**
-     * Creates a font from the given package.
+     * Creates a font from the given bundle.
      *
-     * If the 'id' parameter is NULL, it is assumed that the Package at 'path'
-     * contains exactly one Font resource. If the Package does not meet this criteria,
+     * If the 'id' parameter is NULL, it is assumed that the Bundle at 'path'
+     * contains exactly one Font resource. If the Bundle does not meet this criteria,
      * NULL is returned.
      *
      * If a font for the given path has already been loaded, the existing font will be
      * returned with its reference count increased.
      *
-     * @param path The path to a package file containing a font resource.
-     * @param id An optional ID of the font resource within the package (NULL for the first/only resource).
+     * @param path The path to a bundle file containing a font resource.
+     * @param id An optional ID of the font resource within the bundle (NULL for the first/only resource).
      * 
      * @return The specified font.
      */

+ 24 - 14
gameplay/src/Form.cpp

@@ -201,36 +201,46 @@ namespace gameplay
     {
         std::vector<Control*>::const_iterator it;
 
-        // Batch all themed border and background sprites.
+        // Batch for all themed border and background sprites.
         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.
         // 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));
 
-        // Draw each control's border and background.
         for (it = _controls.begin(); it < _controls.end(); 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();
 
-        // 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();
             }
         }
 

+ 2 - 2
gameplay/src/Joint.h

@@ -7,7 +7,7 @@ namespace gameplay
 {
 
 class MeshSkin;
-class Package;
+class Bundle;
 
 /**
  * Defines a basic hierachial structure of transformation spaces.
@@ -16,7 +16,7 @@ class Joint : public Node
 {
     friend class Node;
     friend class MeshSkin;
-    friend class Package;
+    friend class Bundle;
 
 public:
 

+ 0 - 2
gameplay/src/Label.cpp

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

+ 10 - 7
gameplay/src/Layout.cpp

@@ -11,38 +11,41 @@ namespace gameplay
             control->_autoWidth || control->_autoHeight)
         {
             Rectangle controlBounds = control->getBounds();
-            const Rectangle& containerBounds = container->getClip();
+            const Rectangle& containerBounds = container->getClipBounds();
             const Theme::Border& containerBorder = container->getBorder(container->getState());
             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)
             {
-                controlBounds.width = containerBounds.width;
+                controlBounds.width = clipWidth;
             }
 
             if (control->_autoHeight)
             {
-                controlBounds.height = containerBounds.height;
+                controlBounds.height = clipHeight;
             }
 
             // Vertical alignment
             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)
             {
-                controlBounds.y = containerBounds.height * 0.5f - controlBounds.height * 0.5f;
+                controlBounds.y = clipHeight * 0.5f - controlBounds.height * 0.5f;
             }
 
             // Horizontal alignment
             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)
             {
-                controlBounds.x = containerBounds.width * 0.5f - controlBounds.width * 0.5f;
+                controlBounds.x = clipWidth * 0.5f - controlBounds.width * 0.5f;
             }
 
             control->setBounds(controlBounds);

+ 5 - 5
gameplay/src/Mesh.h

@@ -21,7 +21,7 @@ class Model;
 class Mesh : public Ref
 {
     friend class Model;
-    friend class Package;
+    friend class Bundle;
 
 public:
 
@@ -126,8 +126,8 @@ public:
     /**
      * Returns a URL from which the mesh was loaded from.
      *
-     * For meshes loaded from a Package, this URL will point
-     * to the file and ID of the mesh within the package. For
+     * For meshes loaded from a Bundle, this URL will point
+     * to the file and ID of the mesh within the bundle. For
      * all other meshes, an empty string will be returned.
      */
     const char* getUrl() const;
@@ -230,7 +230,7 @@ public:
     /**
      * Returns the bounding box for the points in this mesh.
      * 
-     * Only meshes loaded from package files are imported with valid
+     * Only meshes loaded from bundle files are imported with valid
      * bounding volumes. Programmatically created meshes will contain
      * empty bounding volumes until the setBoundingBox and/or
      * setBoundingSphere methods are called to specify the mesh's
@@ -259,7 +259,7 @@ public:
     /**
      * Returns the bounding sphere for the points in the mesh.
      *
-     * Only meshes loaded from package files are imported with valid
+     * Only meshes loaded from bundle files are imported with valid
      * bounding volumes. Programmatically created meshes will contain
      * empty bounding volumes until the setBoundingBox and/or
      * setBoundingSphere methods are called to specify the mesh's

+ 2 - 1
gameplay/src/MeshBatch.cpp

@@ -151,7 +151,7 @@ bool MeshBatch::resize(unsigned int capacity)
 
     return true;
 }
-
+    
 void MeshBatch::begin()
 {
     _vertexCount = 0;
@@ -193,5 +193,6 @@ void MeshBatch::draw()
         pass->unbind();
     }
 }
+    
 
 }

+ 6 - 6
gameplay/src/MeshBatch.inl

@@ -12,12 +12,12 @@ template <class T>
 void MeshBatch::add(T* vertices, unsigned int vertexCount, unsigned short* indices, unsigned int indexCount)
 {
     assert(sizeof(T) == _vertexFormat.getVertexSize());
-
+    
     unsigned int newVertexCount = _vertexCount + vertexCount;
     unsigned int newIndexCount = _indexCount + indexCount;
     if (_primitiveType == Mesh::TRIANGLE_STRIP && _vertexCount > 0)
         newIndexCount += 2; // need an extra 2 indices for connecting strips with degenerate triangles
-
+    
     // Do we need to grow the batch?
     while (newVertexCount > _vertexCapacity || (_indexed && newIndexCount > _indexCapacity))
     {
@@ -26,11 +26,11 @@ void MeshBatch::add(T* vertices, unsigned int vertexCount, unsigned short* indic
         if (!resize(_capacity + _growSize))
             return; // failed to grow
     }
-
+    
     // Copy vertex data
     unsigned int vBytes = vertexCount * _vertexFormat.getVertexSize();
     memcpy(_verticesPtr, vertices, vBytes);
-
+    
     // Copy index data
     if (_indexed)
     {
@@ -49,7 +49,7 @@ void MeshBatch::add(T* vertices, unsigned int vertexCount, unsigned short* indic
                 _indicesPtr[1] = _vertexCount;
                 _indicesPtr += 2;
             }
-
+            
             // Loop through all indices and insert them, their their value offset by
             // 'vertexCount' so that they are relative to the first newly insertted vertex
             for (unsigned int i = 0; i < indexCount; ++i)
@@ -60,7 +60,7 @@ void MeshBatch::add(T* vertices, unsigned int vertexCount, unsigned short* indic
         _indicesPtr += indexCount;
         _indexCount = newIndexCount;
     }
-
+    
     _verticesPtr += vBytes;
     _vertexCount = newVertexCount;
 }

+ 2 - 2
gameplay/src/MeshSkin.h

@@ -7,7 +7,7 @@
 namespace gameplay
 {
 
-class Package;
+class Bundle;
 class Model;
 class Joint;
 class Node;
@@ -17,7 +17,7 @@ class Node;
  */
 class MeshSkin : public Transform::Listener
 {
-    friend class Package;
+    friend class Bundle;
     friend class Model;
     friend class Joint;
 

+ 2 - 2
gameplay/src/Model.h

@@ -8,7 +8,7 @@
 namespace gameplay
 {
 
-class Package;
+class Bundle;
 class MeshSkin;
 class Node;
 class NodeCloneContext;
@@ -21,7 +21,7 @@ class Model : public Ref
 {
     friend class Node;
     friend class Mesh;
-    friend class Package;
+    friend class Bundle;
 
 public:
 

+ 2 - 2
gameplay/src/Node.h

@@ -16,7 +16,7 @@
 namespace gameplay
 {
 
-class Package;
+class Bundle;
 class Scene;
 class Form;
 
@@ -26,7 +26,7 @@ class Form;
 class Node : public Transform, public Ref
 {
     friend class Scene;
-    friend class Package;
+    friend class Bundle;
     friend class MeshSkin;
 
 public:

+ 4 - 4
gameplay/src/PhysicsController.cpp

@@ -5,7 +5,7 @@
 #include "PhysicsMotionState.h"
 #include "Game.h"
 #include "MeshPart.h"
-#include "Package.h"
+#include "Bundle.h"
 
 #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
 
@@ -927,7 +927,7 @@ PhysicsCollisionShape* PhysicsController::createMesh(Mesh* mesh, const Vector3&
         return NULL;
     }
 
-    // The mesh must have a valid URL (i.e. it must have been loaded from a Package)
+    // The mesh must have a valid URL (i.e. it must have been loaded from a Bundle)
     // in order to fetch mesh data for computing mesh rigid body.
     if (strlen(mesh->getUrl()) == 0)
     {
@@ -935,7 +935,7 @@ PhysicsCollisionShape* PhysicsController::createMesh(Mesh* mesh, const Vector3&
         return NULL;
     }
 
-    Package::MeshData* data = Package::readMeshData(mesh->getUrl());
+    Bundle::MeshData* data = Bundle::readMeshData(mesh->getUrl());
     if (data == NULL)
     {
         return NULL;
@@ -968,7 +968,7 @@ PhysicsCollisionShape* PhysicsController::createMesh(Mesh* mesh, const Vector3&
     {
         PHY_ScalarType indexType = PHY_UCHAR;
         int indexStride = 0;
-        Package::MeshPartData* meshPart = NULL;
+        Bundle::MeshPartData* meshPart = NULL;
         for (unsigned int i = 0; i < partCount; i++)
         {
             meshPart = data->parts[i];

+ 6 - 22
gameplay/src/PlatformQNX.cpp

@@ -804,14 +804,9 @@ int Platform::enterMessagePump()
                 {
                     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);
                         }
                         break;
@@ -819,14 +814,9 @@ int Platform::enterMessagePump()
 
                     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);
                         }
                         break;
@@ -834,18 +824,12 @@ int Platform::enterMessagePump()
 
                     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);
                         }
                         break;
-                        break;
                     }
 
                     case SCREEN_EVENT_POINTER:

+ 1 - 1
gameplay/src/Quaternion.h

@@ -16,7 +16,7 @@ class Matrix;
  * Quaternions are typically used as a replacement for euler angles and rotation matrices as a way to achieve smooth interpolation and avoid gimbal lock.
  *
  * Note that this quaternion class does not automatically keep the quaternion normalized. Therefore, care must be taken to normalize the quaternion when neccessary, by calling the normalize method.
- * The package provides three methods for doing quaternion interpolation: lerp, slerp, and squad.
+ * This class provides three methods for doing quaternion interpolation: lerp, slerp, and squad.
  *
  * lerp (linear interpolation): the interpolation curve gives a straight line in quaternion space. It is simple and fast to compute. The only problem is that it does not provide constant angular velocity. Note that a constant velocity is not necessarily a requirement for a curve;
  * slerp (spherical linear interpolation): the interpolation curve forms a great arc on the quaternion unit sphere. Slerp provides constant angular velocity;

+ 2 - 2
gameplay/src/RadioButton.cpp

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

+ 10 - 9
gameplay/src/SceneLoader.cpp

@@ -1,6 +1,6 @@
 #include "Base.h"
 #include "Game.h"
-#include "Package.h"
+#include "Bundle.h"
 #include "SceneLoader.h"
 
 namespace gameplay
@@ -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.
                             Model* model = node->getModel();
+                            assert(model);
                         
                             // Up ref count to prevent node from releasing the model when we swap it.
                             model->addRef(); 
@@ -437,10 +438,10 @@ void SceneLoader::applyNodeUrls(Scene* scene)
             {
                 // An external file was referenced, so load the node from file and then insert it into the scene with the new ID.
 
-                // TODO: Revisit this to determine if we should cache Package objects for the duration of the scene
+                // TODO: Revisit this to determine if we should cache Bundle objects for the duration of the scene
                 // load to prevent constantly creating/destroying the same externally referenced packages each time
                 // a url with a file is encountered.
-                Package* tmpPackage = Package::create(snp._file.c_str());
+                Bundle* tmpPackage = Bundle::create(snp._file.c_str());
                 if (tmpPackage)
                 {
                     if (sceneNode._exactMatch)
@@ -459,7 +460,7 @@ void SceneLoader::applyNodeUrls(Scene* scene)
                     }
                     else
                     {
-                        // Search for nodes in the package using a partial match
+                        // Search for nodes in the bundle using a partial match
                         std::string partialMatch = snp._id;
                         unsigned int objectCount = tmpPackage->getObjectCount();
                         unsigned int matchCount = 0;
@@ -754,19 +755,19 @@ PhysicsConstraint* SceneLoader::loadHingeConstraint(const Properties* constraint
 Scene* SceneLoader::loadMainSceneData(const Properties* sceneProperties)
 {
     // Load the main scene from the specified path.
-    Package* package = Package::create(_path.c_str());
-    if (!package)
+    Bundle* bundle = Bundle::create(_path.c_str());
+    if (!bundle)
     {
         WARN_VARG("Failed to load scene GPB file '%s'.", _path.c_str());
         return NULL;
     }
 
     const char* sceneID = strlen(sceneProperties->getId()) == 0 ? NULL : sceneProperties->getId();
-    Scene* scene = package->loadScene(sceneID);
+    Scene* scene = bundle->loadScene(sceneID);
     if (!scene)
     {
         WARN_VARG("Failed to load scene from '%s'.", _path.c_str());
-        SAFE_RELEASE(package);
+        SAFE_RELEASE(bundle);
         return NULL;
     }
 
@@ -779,7 +780,7 @@ Scene* SceneLoader::loadMainSceneData(const Properties* sceneProperties)
             scene->setActiveCamera(camera->getCamera());
     }
 
-    SAFE_RELEASE(package);
+    SAFE_RELEASE(bundle);
     return scene;
 }
 

+ 1 - 1
gameplay/src/SpriteBatch.h

@@ -24,7 +24,7 @@ namespace gameplay
  */
 class SpriteBatch
 {
-    friend class Package;
+    friend class Bundle;
 
 public:
 

+ 32 - 1
gameplay/src/TextBox.cpp

@@ -222,9 +222,40 @@ void TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         // Insert character into string.
                         _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,
                             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;
                         break;

+ 60 - 51
gameplay/src/Transform.cpp

@@ -7,28 +7,28 @@ namespace gameplay
 {
 
 Transform::Transform()
-    : _matrixDirty(false), _listeners(NULL)
+    : _matrixDirtyBits(0), _listeners(NULL)
 {
     _targetType = AnimationTarget::TRANSFORM;
     _scale.set(Vector3::one());
 }
 
 Transform::Transform(const Vector3& scale, const Quaternion& rotation, const Vector3& translation)
-    : _matrixDirty(false), _listeners(NULL)
+    : _matrixDirtyBits(0), _listeners(NULL)
 {
     _targetType = AnimationTarget::TRANSFORM;
     set(scale, rotation, translation);
 }
 
 Transform::Transform(const Vector3& scale, const Matrix& rotation, const Vector3& translation)
-    : _matrixDirty(false), _listeners(NULL)
+    : _matrixDirtyBits(0), _listeners(NULL)
 {
     _targetType = AnimationTarget::TRANSFORM;
     set(scale, rotation, translation);
 }
 
 Transform::Transform(const Transform& copy)
-    : _matrixDirty(false), _listeners(NULL)
+    : _matrixDirtyBits(0), _listeners(NULL)
 {
     _targetType = AnimationTarget::TRANSFORM;
     set(copy);
@@ -41,40 +41,40 @@ Transform::~Transform()
 
 const Matrix& Transform::getMatrix() const
 {
-    if (_matrixDirty)
+    if (_matrixDirtyBits)
     {
-        _matrixDirty = false;
-
         bool hasTranslation = !_translation.isZero();
         bool hasScale = !_scale.isOne();
         bool hasRotation = !_rotation.isIdentity();
 
         // 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).
-        if (hasTranslation)
+        if (hasTranslation || (_matrixDirtyBits & DIRTY_TRANSLATION) == DIRTY_TRANSLATION)
         {
             Matrix::createTranslation(_translation, &_matrix);
-            if (hasRotation)
+            if (hasRotation || (_matrixDirtyBits & DIRTY_ROTATION) == DIRTY_ROTATION)
             {
                 _matrix.rotate(_rotation);
             }
-            if (hasScale)
+            if (hasScale || (_matrixDirtyBits & DIRTY_SCALE) == DIRTY_SCALE)
             {
                 _matrix.scale(_scale);
             }
         }
-        else if (hasRotation)
+        else if (hasRotation || (_matrixDirtyBits & DIRTY_ROTATION) == DIRTY_ROTATION)
         {
             Matrix::createRotation(_rotation, &_matrix);
-            if (hasScale)
+            if (hasScale || (_matrixDirtyBits & DIRTY_SCALE) == DIRTY_SCALE)
             {
                 _matrix.scale(_scale);
             }
         }
-        else if (hasScale)
+        else if (hasScale || (_matrixDirtyBits & DIRTY_SCALE) == DIRTY_SCALE)
         {
             Matrix::createScale(_scale, &_matrix);
         }
+
+        _matrixDirtyBits = 0;
     }
 
     return _matrix;
@@ -231,13 +231,13 @@ void Transform::rotate(float qx, float qy, float qz, float qw)
 {
     Quaternion q(qx, qy, qz, qw);
     _rotation.multiply(q);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::rotate(const Quaternion& rotation)
 {
     _rotation.multiply(rotation);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 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);
     _rotation.multiply(rotationQuat);
     _rotation.normalize();
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::rotate(const Matrix& rotation)
@@ -254,7 +254,7 @@ void Transform::rotate(const Matrix& rotation)
     Quaternion rotationQuat;
     Quaternion::createFromRotationMatrix(rotation, &rotationQuat);
     _rotation.multiply(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::rotateX(float angle)
@@ -262,7 +262,7 @@ void Transform::rotateX(float angle)
     Quaternion rotationQuat;
     Quaternion::createFromAxisAngle(Vector3::unitX(), angle, &rotationQuat);
     _rotation.multiply(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::rotateY(float angle)
@@ -270,7 +270,7 @@ void Transform::rotateY(float angle)
     Quaternion rotationQuat;
     Quaternion::createFromAxisAngle(Vector3::unitY(), angle, &rotationQuat);
     _rotation.multiply(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::rotateZ(float angle)
@@ -278,13 +278,13 @@ void Transform::rotateZ(float angle)
     Quaternion rotationQuat;
     Quaternion::createFromAxisAngle(Vector3::unitZ(), angle, &rotationQuat);
     _rotation.multiply(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::scale(float scale)
 {
     _scale.scale(scale);
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 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.y *= sy;
     _scale.z *= sz;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::scale(const Vector3& scale)
@@ -300,25 +300,25 @@ void Transform::scale(const Vector3& scale)
     _scale.x *= scale.x;
     _scale.y *= scale.y;
     _scale.z *= scale.z;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::scaleX(float sx)
 {
     _scale.x *= sx;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::scaleY(float sy)
 {
     _scale.y *= sy;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::scaleZ(float sz)
 {
     _scale.z *= sz;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 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);
     _rotation.set(rotation);
     _translation.set(translation);
-    dirty();
+    dirty(DIRTY_TRANSLATION | DIRTY_ROTATION | DIRTY_SCALE);
 }
 
 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);
     _rotation.set(rotationQuat);
     _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)
@@ -344,6 +344,7 @@ void Transform::set(const Vector3& scale, const Vector3& axis, float angle, cons
     _scale.set(scale);
     _rotation.set(axis, angle);
     _translation.set(translation);
+    dirty(DIRTY_TRANSLATION | DIRTY_ROTATION | DIRTY_SCALE);
 }
 
 void Transform::set(const Transform& transform)
@@ -351,55 +352,63 @@ void Transform::set(const Transform& transform)
     _scale.set(transform._scale);
     _rotation.set(transform._rotation);
     _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)
 {
     _scale.set(scale, scale, scale);
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::setScale(float sx, float sy, float sz)
 {
     _scale.set(sx, sy, sz);
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::setScale(const Vector3& scale)
 {
     _scale.set(scale);
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::setScaleX(float sx)
 {
     _scale.x = sx;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::setScaleY(float sy)
 {
     _scale.y = sy;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::setScaleZ(float sz)
 {
     _scale.z = sz;
-    dirty();
+    dirty(DIRTY_SCALE);
 }
 
 void Transform::setRotation(const Quaternion& rotation)
 {
     _rotation.set(rotation);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::setRotation(float qx, float qy, float qz, float qw)
 {
     _rotation.set(qx, qy, qz, qw);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::setRotation(const Matrix& rotation)
@@ -407,43 +416,43 @@ void Transform::setRotation(const Matrix& rotation)
     Quaternion rotationQuat;
     Quaternion::createFromRotationMatrix(rotation, &rotationQuat);
     _rotation.set(rotationQuat);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::setRotation(const Vector3& axis, float angle)
 {
     _rotation.set(axis, angle);
-    dirty();
+    dirty(DIRTY_ROTATION);
 }
 
 void Transform::setTranslation(const Vector3& translation)
 {
     _translation.set(translation);
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 void Transform::setTranslation(float tx, float ty, float tz)
 {
     _translation.set(tx, ty, tz);
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 void Transform::setTranslationX(float tx)
 {
     _translation.x = tx;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 void Transform::setTranslationY(float ty)
 {
     _translation.y = ty;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 void Transform::setTranslationZ(float tz)
 {
     _translation.z = tz;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 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.y += ty;
     _translation.z += tz;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 void Transform::translate(const Vector3& translation)
@@ -459,25 +468,25 @@ void Transform::translate(const Vector3& translation)
     _translation.x += translation.x;
     _translation.y += translation.y;
     _translation.z += translation.z;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 void Transform::translateX(float tx)
 {
     _translation.x += tx;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 void Transform::translateY(float ty)
 {
     _translation.y += ty;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 void Transform::translateZ(float tz)
 {
     _translation.z += tz;
-    dirty();
+    dirty(DIRTY_TRANSLATION);
 }
 
 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();
 }
 

+ 14 - 2
gameplay/src/Transform.h

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

+ 1 - 1
gameplay/src/gameplay.h

@@ -6,7 +6,7 @@
 #include "Touch.h"
 #include "Mouse.h"
 #include "FileSystem.h"
-#include "Package.h"
+#include "Bundle.h"
 
 // Math
 #include "Rectangle.h"