Parcourir la source

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

Steve Grenier il y a 13 ans
Parent
commit
ec0b03aa87
100 fichiers modifiés avec 4831 ajouts et 1471 suppressions
  1. 17 0
      .gitignore
  2. 7 8
      README.md
  3. BIN
      gameplay-api/gameplay.png
  4. 5 5
      gameplay-encoder/README.md
  5. 3 2
      gameplay-encoder/gameplay-encoder.vcxproj
  6. 9 6
      gameplay-encoder/gameplay-encoder.vcxproj.filters
  7. 30 36
      gameplay-encoder/gameplay-encoder.xcodeproj/project.pbxproj
  8. 1 0
      gameplay-encoder/src/Camera.h
  9. 1346 0
      gameplay-encoder/src/Curve.cpp
  10. 484 0
      gameplay-encoder/src/Curve.h
  11. 36 0
      gameplay-encoder/src/Curve.inl
  12. 1 0
      gameplay-encoder/src/DAEChannelTarget.h
  13. 3 1
      gameplay-encoder/src/DAESceneEncoder.h
  14. 1 0
      gameplay-encoder/src/Effect.h
  15. 55 10
      gameplay-encoder/src/FBXSceneEncoder.cpp
  16. 3 0
      gameplay-encoder/src/FileIO.h
  17. 15 13
      gameplay-encoder/src/MeshSkin.cpp
  18. 2 2
      gameplay-encoder/src/Reference.h
  19. 3 3
      gameplay-newproject.bat
  20. 3 3
      gameplay-newproject.sh
  21. 0 0
      gameplay-template/TEMPLATE_PROJECT-macosx.plist
  22. 74 77
      gameplay-template/gameplay-template.xcodeproj/project.pbxproj
  23. 82 39
      gameplay.doxyfile
  24. 22 11
      gameplay.sln
  25. 3 0
      gameplay.xcworkspace/contents.xcworkspacedata
  26. 1 1
      gameplay/android/jni/Android.mk
  27. 6 6
      gameplay/gameplay.vcxproj
  28. 10 10
      gameplay/gameplay.vcxproj.filters
  29. 98 81
      gameplay/gameplay.xcodeproj/project.pbxproj
  30. BIN
      gameplay/res/icon_black.psd
  31. BIN
      gameplay/res/icon_black128.ico
  32. BIN
      gameplay/res/icon_black16.ico
  33. BIN
      gameplay/res/icon_black32.ico
  34. BIN
      gameplay/res/icon_black64.ico
  35. BIN
      gameplay/res/icon_black_transparent.psd
  36. BIN
      gameplay/res/icon_black_transparent128.ico
  37. BIN
      gameplay/res/icon_black_transparent16.ico
  38. BIN
      gameplay/res/icon_black_transparent32.ico
  39. BIN
      gameplay/res/icon_black_transparent64.ico
  40. BIN
      gameplay/res/icon_white_transparent.psd
  41. BIN
      gameplay/res/icon_white_transparent128.ico
  42. BIN
      gameplay/res/icon_white_transparent16.ico
  43. BIN
      gameplay/res/icon_white_transparent32.ico
  44. BIN
      gameplay/res/icon_white_transparent64.ico
  45. 27 0
      gameplay/res/logo.ai
  46. 7 0
      gameplay/res/shaders/bumped-specular.fsh
  47. 7 0
      gameplay/res/shaders/bumped.fsh
  48. 7 0
      gameplay/res/shaders/colored-specular.fsh
  49. 7 0
      gameplay/res/shaders/colored.fsh
  50. 7 0
      gameplay/res/shaders/diffuse-specular.fsh
  51. 7 0
      gameplay/res/shaders/diffuse.fsh
  52. 7 0
      gameplay/res/shaders/parallax-specular.fsh
  53. 7 0
      gameplay/res/shaders/parallax.fsh
  54. 7 0
      gameplay/res/shaders/solid.fsh
  55. 7 0
      gameplay/res/shaders/textured.fsh
  56. 6 2
      gameplay/src/AbsoluteLayout.cpp
  57. 14 0
      gameplay/src/AbsoluteLayout.h
  58. 13 39
      gameplay/src/Animation.cpp
  59. 4 26
      gameplay/src/Animation.h
  60. 4 3
      gameplay/src/AnimationClip.h
  61. 1 303
      gameplay/src/AnimationController.cpp
  62. 5 119
      gameplay/src/AnimationController.h
  63. 278 8
      gameplay/src/AnimationTarget.cpp
  64. 111 7
      gameplay/src/AnimationTarget.h
  65. 2 1
      gameplay/src/AudioBuffer.h
  66. 3 3
      gameplay/src/AudioController.cpp
  67. 7 3
      gameplay/src/AudioSource.cpp
  68. 2 4
      gameplay/src/AudioSource.h
  69. 1 3
      gameplay/src/Base.h
  70. 3 3
      gameplay/src/BoundingBox.cpp
  71. 1 1
      gameplay/src/BoundingBox.h
  72. 1 1
      gameplay/src/Button.cpp
  73. 23 6
      gameplay/src/Button.h
  74. 12 34
      gameplay/src/Camera.cpp
  75. 9 9
      gameplay/src/Camera.h
  76. 79 43
      gameplay/src/CheckBox.cpp
  77. 28 8
      gameplay/src/CheckBox.h
  78. 0 38
      gameplay/src/CloneContext.cpp
  79. 0 86
      gameplay/src/CloneContext.h
  80. 31 20
      gameplay/src/Container.cpp
  81. 42 15
      gameplay/src/Container.h
  82. 724 101
      gameplay/src/Control.cpp
  83. 592 50
      gameplay/src/Control.h
  84. 8 2
      gameplay/src/Curve.cpp
  85. 25 10
      gameplay/src/Curve.h
  86. 148 1
      gameplay/src/DebugNew.cpp
  87. 15 0
      gameplay/src/DebugNew.h
  88. 19 19
      gameplay/src/FileSystem.cpp
  89. 0 24
      gameplay/src/FlowLayout.h
  90. 25 25
      gameplay/src/Font.cpp
  91. 27 13
      gameplay/src/Font.h
  92. 45 39
      gameplay/src/Form.cpp
  93. 39 22
      gameplay/src/Form.h
  94. 4 1
      gameplay/src/FrameBuffer.h
  95. 17 7
      gameplay/src/Game.cpp
  96. 21 33
      gameplay/src/Game.h
  97. 5 14
      gameplay/src/Game.inl
  98. 1 1
      gameplay/src/Joint.cpp
  99. 12 3
      gameplay/src/Joint.h
  100. 7 7
      gameplay/src/Label.cpp

+ 17 - 0
.gitignore

@@ -85,6 +85,19 @@ Thumbs.db
 /gameplay-samples/sample03-character/res/shaders
 /gameplay-samples/sample03-character/res/shaders
 /gameplay-samples/sample03-character/res/logo_powered_white.png
 /gameplay-samples/sample03-character/res/logo_powered_white.png
 /gameplay-samples/sample03-character/sample03-character.xcodeproj/xcuserdata
 /gameplay-samples/sample03-character/sample03-character.xcodeproj/xcuserdata
+/gameplay-samples/sample04-particles/Debug
+/gameplay-samples/sample04-particles/DebugMem
+/gameplay-samples/sample04-particles/Release
+/gameplay-samples/sample04-particles/Simulator
+/gameplay-samples/sample04-particles/Simulator-Coverage
+/gameplay-samples/sample04-particles/Simulator-Profile
+/gameplay-samples/sample04-particles/Device-Debug
+/gameplay-samples/sample04-particles/Device-Coverage
+/gameplay-samples/sample04-particles/Device-Profile
+/gameplay-samples/sample04-particles/Device-Release
+/gameplay-samples/sample04-particles/res/shaders
+/gameplay-samples/sample04-particles/res/logo_powered_white.png
+/gameplay-samples/sample04-particles/sample04-particles.xcodeproj/xcuserdata
 
 
 /gameplay-android/obj
 /gameplay-android/obj
 /gameplay-android/NUL
 /gameplay-android/NUL
@@ -139,3 +152,7 @@ Thumbs.db
 /gameplay-samples/sample03-character/android/NUL
 /gameplay-samples/sample03-character/android/NUL
 /gameplay-samples/sample01-longboard/NUL
 /gameplay-samples/sample01-longboard/NUL
 
 
+
+/gameplay-samples/sample04-particles/Device-Debug
+/gameplay-samples/sample04-particles/Debug
+/gameplay-samples/sample04-particles/DebugMem

+ 7 - 8
README.md

@@ -1,19 +1,18 @@
-## GamePlay v1.2.0
-GamePlay is a open-source, cross-platform 3D native gaming framework making it easy to learn and write mobile and desktop games. 
+## gameplay v1.2.0
+An open-source, cross-platform 3D native game framework making it easy to learn and write mobile and desktop games. 
 
 
 ## Supported Mobile Platforms
 ## Supported Mobile Platforms
 - BlackBerry PlayBook 2 (using BlackBerry Native SDK 2)
 - BlackBerry PlayBook 2 (using BlackBerry Native SDK 2)
-- Google Android 4 (using Google Android NDK 7)
-- Apple iOS 5 (using Apple XCode 4.3)
+- Google Android 2.3 (using Google Android NDK 7)
+- Apple iOS 5.1 (using Apple XCode 4.3.2)
 
 
 ## Supported Desktop Platforms
 ## Supported Desktop Platforms
 - Microsoft Windows 7 (using Microsoft Visual Studio 2010)
 - Microsoft Windows 7 (using Microsoft Visual Studio 2010)
-- Apple MacOS X (using Apple XCode 4.3)
+- Apple MacOS X (using Apple XCode 4.3.2)
 
 
 ## Roadmap for 'next' branch
 ## Roadmap for 'next' branch
-- Lua script bindings
-- Terrain and Water
-- Lighting enhancements
+- Lua Scripting
+- Terrain
 - Editor
 - Editor
 
 
 ## Licence
 ## Licence

BIN
gameplay-api/gameplay.png


+ 5 - 5
gameplay-encoder/README.md

@@ -1,6 +1,6 @@
-## GamePlay Encoder
-GamePlay Encoder is a command-line tool for encoding/packaging games assets like fonts and 3D scene files
-into a binary package file format for the GamePlay runtime framework. 
+## 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. 
 
 
 ## TrueType Font Support
 ## TrueType Font Support
 TrueType Fonts conversion is enabled/built-in by default into gameplay-encoder via freetype 2 library.
 TrueType Fonts conversion is enabled/built-in by default into gameplay-encoder via freetype 2 library.
@@ -42,10 +42,10 @@ You must then rebuild gameplay-encoder with the follow platform/tooling instruct
 - Build gameplay-encoder
 - Build gameplay-encoder
 
 
 ## Binary Format
 ## Binary Format
-The GamePlay binary package format is well defined in the gameplay-encoder/gameplay-binary.txt file.
+The gameplay binary package format is well defined in the gameplay-encoder/gameplay-binary.txt file.
 
 
 ## Binary Loading
 ## Binary Loading
-GamePlay binary package files can easily be loaded using the gameplay/Package.h which is part
+Binary package files can easily be loaded using the gameplay/Package.h which is part
 of the GamePlay runtime framework.
 of the GamePlay runtime framework.
 
 
 ## Disclaimer
 ## Disclaimer

+ 3 - 2
gameplay-encoder/gameplay-encoder.vcxproj

@@ -11,12 +11,12 @@
     </ProjectConfiguration>
     </ProjectConfiguration>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\gameplay\src\Curve.cpp" />
     <ClCompile Include="src\Animation.cpp" />
     <ClCompile Include="src\Animation.cpp" />
     <ClCompile Include="src\AnimationChannel.cpp" />
     <ClCompile Include="src\AnimationChannel.cpp" />
     <ClCompile Include="src\Base.cpp" />
     <ClCompile Include="src\Base.cpp" />
     <ClCompile Include="src\BoundingVolume.cpp" />
     <ClCompile Include="src\BoundingVolume.cpp" />
     <ClCompile Include="src\Camera.cpp" />
     <ClCompile Include="src\Camera.cpp" />
+    <ClCompile Include="src\Curve.cpp" />
     <ClCompile Include="src\EncoderArguments.cpp" />
     <ClCompile Include="src\EncoderArguments.cpp" />
     <ClCompile Include="src\DAEChannelTarget.cpp" />
     <ClCompile Include="src\DAEChannelTarget.cpp" />
     <ClCompile Include="src\DAEOptimizer.cpp" />
     <ClCompile Include="src\DAEOptimizer.cpp" />
@@ -55,12 +55,12 @@
     <ClCompile Include="src\VertexElement.cpp" />
     <ClCompile Include="src\VertexElement.cpp" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\gameplay\src\Curve.h" />
     <ClInclude Include="src\Animation.h" />
     <ClInclude Include="src\Animation.h" />
     <ClInclude Include="src\AnimationChannel.h" />
     <ClInclude Include="src\AnimationChannel.h" />
     <ClInclude Include="src\Base.h" />
     <ClInclude Include="src\Base.h" />
     <ClInclude Include="src\BoundingVolume.h" />
     <ClInclude Include="src\BoundingVolume.h" />
     <ClInclude Include="src\Camera.h" />
     <ClInclude Include="src\Camera.h" />
+    <ClInclude Include="src\Curve.h" />
     <ClInclude Include="src\EncoderArguments.h" />
     <ClInclude Include="src\EncoderArguments.h" />
     <ClInclude Include="src\DAEChannelTarget.h" />
     <ClInclude Include="src\DAEChannelTarget.h" />
     <ClInclude Include="src\DAEOptimizer.h" />
     <ClInclude Include="src\DAEOptimizer.h" />
@@ -98,6 +98,7 @@
     <ClInclude Include="src\VertexElement.h" />
     <ClInclude Include="src\VertexElement.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
+    <None Include="src\Curve.inl" />
     <None Include="src\Quaternion.inl" />
     <None Include="src\Quaternion.inl" />
     <None Include="src\Vector2.inl" />
     <None Include="src\Vector2.inl" />
     <None Include="src\Vector3.inl" />
     <None Include="src\Vector3.inl" />

+ 9 - 6
gameplay-encoder/gameplay-encoder.vcxproj.filters

@@ -19,9 +19,6 @@
     <ClCompile Include="src\Camera.cpp">
     <ClCompile Include="src\Camera.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\gameplay\src\Curve.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
     <ClCompile Include="src\DAEChannelTarget.cpp">
     <ClCompile Include="src\DAEChannelTarget.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
@@ -127,6 +124,9 @@
     <ClCompile Include="src\VertexElement.cpp">
     <ClCompile Include="src\VertexElement.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="src\Curve.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\VertexElement.h">
     <ClInclude Include="src\VertexElement.h">
@@ -150,9 +150,6 @@
     <ClInclude Include="src\Camera.h">
     <ClInclude Include="src\Camera.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\gameplay\src\Curve.h">
-      <Filter>src</Filter>
-    </ClInclude>
     <ClInclude Include="src\DAEChannelTarget.h">
     <ClInclude Include="src\DAEChannelTarget.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
@@ -252,6 +249,9 @@
     <ClInclude Include="src\Vertex.h">
     <ClInclude Include="src\Vertex.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="src\Curve.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <None Include="src\Vector2.inl">
     <None Include="src\Vector2.inl">
@@ -266,6 +266,9 @@
     <None Include="src\Quaternion.inl">
     <None Include="src\Quaternion.inl">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </None>
     </None>
+    <None Include="src\Curve.inl">
+      <Filter>src</Filter>
+    </None>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Filter Include="src">
     <Filter Include="src">

+ 30 - 36
gameplay-encoder/gameplay-encoder.xcodeproj/project.pbxproj

@@ -8,9 +8,9 @@
 
 
 /* Begin PBXBuildFile section */
 /* Begin PBXBuildFile section */
 		42475D7C14720ECE00610A6A /* libdom.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42475D7B14720ECE00610A6A /* libdom.a */; };
 		42475D7C14720ECE00610A6A /* libdom.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42475D7B14720ECE00610A6A /* libdom.a */; };
+		4251B12C152D044B002F6199 /* Curve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4251B128152D044B002F6199 /* Curve.cpp */; };
 		42783423148D6F7500A6E27F /* FBXSceneEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4278341E148D6F7500A6E27F /* FBXSceneEncoder.cpp */; };
 		42783423148D6F7500A6E27F /* FBXSceneEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4278341E148D6F7500A6E27F /* FBXSceneEncoder.cpp */; };
 		4283905914896E6C00E2B2F5 /* BoundingVolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4283905714896E6C00E2B2F5 /* BoundingVolume.cpp */; };
 		4283905914896E6C00E2B2F5 /* BoundingVolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4283905714896E6C00E2B2F5 /* BoundingVolume.cpp */; };
-		4283906314896F1600E2B2F5 /* Curve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4283906114896F1600E2B2F5 /* Curve.cpp */; };
 		42C8EE0A14724CD700E43619 /* Animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDB714724CD700E43619 /* Animation.cpp */; };
 		42C8EE0A14724CD700E43619 /* Animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDB714724CD700E43619 /* Animation.cpp */; };
 		42C8EE0B14724CD700E43619 /* AnimationChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDB914724CD700E43619 /* AnimationChannel.cpp */; };
 		42C8EE0B14724CD700E43619 /* AnimationChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDB914724CD700E43619 /* AnimationChannel.cpp */; };
 		42C8EE0C14724CD700E43619 /* Animations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDBB14724CD700E43619 /* Animations.cpp */; };
 		42C8EE0C14724CD700E43619 /* Animations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDBB14724CD700E43619 /* Animations.cpp */; };
@@ -57,7 +57,7 @@
 		42C8EE3B1472DAAE00E43619 /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C8EE3A1472DAAE00E43619 /* libbz2.dylib */; };
 		42C8EE3B1472DAAE00E43619 /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C8EE3A1472DAAE00E43619 /* libbz2.dylib */; };
 		42D277591472EFA700D867A4 /* libpcre.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42D277571472EFA700D867A4 /* libpcre.a */; };
 		42D277591472EFA700D867A4 /* libpcre.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42D277571472EFA700D867A4 /* libpcre.a */; };
 		42D2775A1472EFA700D867A4 /* libpcrecpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42D277581472EFA700D867A4 /* libpcrecpp.a */; };
 		42D2775A1472EFA700D867A4 /* libpcrecpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42D277581472EFA700D867A4 /* libpcrecpp.a */; };
-		42DDE88515191CDA00D9B550 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42DDE88415191CDA00D9B550 /* libpng.a */; };
+		5BCD0643152CFC3C0071FAB5 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BCD0642152CFC3C0071FAB5 /* libpng.a */; };
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
 /* Begin PBXCopyFilesBuildPhase section */
 /* Begin PBXCopyFilesBuildPhase section */
@@ -74,7 +74,11 @@
 
 
 /* Begin PBXFileReference section */
 /* Begin PBXFileReference section */
 		42475CE6147208A000610A6A /* gameplay-encoder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "gameplay-encoder"; sourceTree = BUILT_PRODUCTS_DIR; };
 		42475CE6147208A000610A6A /* gameplay-encoder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "gameplay-encoder"; sourceTree = BUILT_PRODUCTS_DIR; };
-		42475D7B14720ECE00610A6A /* libdom.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdom.a; path = "../external-deps/collada-dom/lib/macos/libdom.a"; sourceTree = "<group>"; };
+		42475D7B14720ECE00610A6A /* libdom.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdom.a; path = "../external-deps/collada-dom/lib/macosx/libdom.a"; sourceTree = "<group>"; };
+		4251B128152D044B002F6199 /* Curve.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Curve.cpp; path = src/Curve.cpp; sourceTree = SOURCE_ROOT; };
+		4251B129152D044B002F6199 /* Curve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Curve.h; path = src/Curve.h; sourceTree = SOURCE_ROOT; };
+		4251B12A152D044B002F6199 /* Curve.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Curve.inl; path = src/Curve.inl; sourceTree = SOURCE_ROOT; };
+		4251B12B152D044B002F6199 /* Quaternion.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Quaternion.inl; path = src/Quaternion.inl; sourceTree = SOURCE_ROOT; };
 		4278341E148D6F7500A6E27F /* FBXSceneEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXSceneEncoder.cpp; path = src/FBXSceneEncoder.cpp; sourceTree = SOURCE_ROOT; };
 		4278341E148D6F7500A6E27F /* FBXSceneEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXSceneEncoder.cpp; path = src/FBXSceneEncoder.cpp; sourceTree = SOURCE_ROOT; };
 		4278341F148D6F7500A6E27F /* FBXSceneEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FBXSceneEncoder.h; path = src/FBXSceneEncoder.h; sourceTree = SOURCE_ROOT; };
 		4278341F148D6F7500A6E27F /* FBXSceneEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FBXSceneEncoder.h; path = src/FBXSceneEncoder.h; sourceTree = SOURCE_ROOT; };
 		42783420148D6F7500A6E27F /* Vector2.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Vector2.inl; path = src/Vector2.inl; sourceTree = SOURCE_ROOT; };
 		42783420148D6F7500A6E27F /* Vector2.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Vector2.inl; path = src/Vector2.inl; sourceTree = SOURCE_ROOT; };
@@ -82,8 +86,6 @@
 		42783422148D6F7500A6E27F /* Vector4.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Vector4.inl; path = src/Vector4.inl; sourceTree = SOURCE_ROOT; };
 		42783422148D6F7500A6E27F /* Vector4.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Vector4.inl; path = src/Vector4.inl; sourceTree = SOURCE_ROOT; };
 		4283905714896E6C00E2B2F5 /* BoundingVolume.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BoundingVolume.cpp; path = src/BoundingVolume.cpp; sourceTree = SOURCE_ROOT; };
 		4283905714896E6C00E2B2F5 /* BoundingVolume.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BoundingVolume.cpp; path = src/BoundingVolume.cpp; sourceTree = SOURCE_ROOT; };
 		4283905814896E6C00E2B2F5 /* BoundingVolume.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BoundingVolume.h; path = src/BoundingVolume.h; sourceTree = SOURCE_ROOT; };
 		4283905814896E6C00E2B2F5 /* BoundingVolume.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BoundingVolume.h; path = src/BoundingVolume.h; sourceTree = SOURCE_ROOT; };
-		4283906114896F1600E2B2F5 /* Curve.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Curve.cpp; path = ../gameplay/src/Curve.cpp; sourceTree = "<group>"; };
-		4283906214896F1600E2B2F5 /* Curve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Curve.h; path = ../gameplay/src/Curve.h; sourceTree = "<group>"; };
 		42C8EDB714724CD700E43619 /* Animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Animation.cpp; path = src/Animation.cpp; sourceTree = SOURCE_ROOT; };
 		42C8EDB714724CD700E43619 /* Animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Animation.cpp; path = src/Animation.cpp; sourceTree = SOURCE_ROOT; };
 		42C8EDB814724CD700E43619 /* Animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Animation.h; path = src/Animation.h; sourceTree = SOURCE_ROOT; };
 		42C8EDB814724CD700E43619 /* Animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Animation.h; path = src/Animation.h; sourceTree = SOURCE_ROOT; };
 		42C8EDB914724CD700E43619 /* AnimationChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnimationChannel.cpp; path = src/AnimationChannel.cpp; sourceTree = SOURCE_ROOT; };
 		42C8EDB914724CD700E43619 /* AnimationChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnimationChannel.cpp; path = src/AnimationChannel.cpp; sourceTree = SOURCE_ROOT; };
@@ -163,13 +165,13 @@
 		42C8EE0714724CD700E43619 /* Vertex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Vertex.h; path = src/Vertex.h; sourceTree = SOURCE_ROOT; };
 		42C8EE0714724CD700E43619 /* Vertex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Vertex.h; path = src/Vertex.h; sourceTree = SOURCE_ROOT; };
 		42C8EE0814724CD700E43619 /* VertexElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VertexElement.cpp; path = src/VertexElement.cpp; sourceTree = SOURCE_ROOT; };
 		42C8EE0814724CD700E43619 /* VertexElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VertexElement.cpp; path = src/VertexElement.cpp; sourceTree = SOURCE_ROOT; };
 		42C8EE0914724CD700E43619 /* VertexElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VertexElement.h; path = src/VertexElement.h; sourceTree = SOURCE_ROOT; };
 		42C8EE0914724CD700E43619 /* VertexElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VertexElement.h; path = src/VertexElement.h; sourceTree = SOURCE_ROOT; };
-		42C8EE341472B60100E43619 /* libfreetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfreetype.a; path = "../external-deps/freetype2/lib/macos/libfreetype.a"; sourceTree = "<group>"; };
+		42C8EE341472B60100E43619 /* libfreetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfreetype.a; path = "../external-deps/freetype2/lib/macosx/libfreetype.a"; sourceTree = "<group>"; };
 		42C8EE361472D7E700E43619 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; };
 		42C8EE361472D7E700E43619 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; };
 		42C8EE381472DAA300E43619 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
 		42C8EE381472DAA300E43619 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
 		42C8EE3A1472DAAE00E43619 /* libbz2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbz2.dylib; path = usr/lib/libbz2.dylib; sourceTree = SDKROOT; };
 		42C8EE3A1472DAAE00E43619 /* libbz2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbz2.dylib; path = usr/lib/libbz2.dylib; sourceTree = SDKROOT; };
-		42D277571472EFA700D867A4 /* libpcre.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpcre.a; path = "../external-deps/pcre/lib/macos/libpcre.a"; sourceTree = "<group>"; };
-		42D277581472EFA700D867A4 /* libpcrecpp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpcrecpp.a; path = "../external-deps/pcre/lib/macos/libpcrecpp.a"; sourceTree = "<group>"; };
-		42DDE88415191CDA00D9B550 /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/macos/libpng.a"; sourceTree = "<group>"; };
+		42D277571472EFA700D867A4 /* libpcre.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpcre.a; path = "../external-deps/pcre/lib/macosx/libpcre.a"; sourceTree = "<group>"; };
+		42D277581472EFA700D867A4 /* libpcrecpp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpcrecpp.a; path = "../external-deps/pcre/lib/macosx/libpcrecpp.a"; sourceTree = "<group>"; };
+		5BCD0642152CFC3C0071FAB5 /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/macosx/libpng.a"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -177,7 +179,6 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				42DDE88515191CDA00D9B550 /* libpng.a in Frameworks */,
 				42D277591472EFA700D867A4 /* libpcre.a in Frameworks */,
 				42D277591472EFA700D867A4 /* libpcre.a in Frameworks */,
 				42D2775A1472EFA700D867A4 /* libpcrecpp.a in Frameworks */,
 				42D2775A1472EFA700D867A4 /* libpcrecpp.a in Frameworks */,
 				42C8EE351472B60100E43619 /* libfreetype.a in Frameworks */,
 				42C8EE351472B60100E43619 /* libfreetype.a in Frameworks */,
@@ -185,6 +186,7 @@
 				42C8EE3B1472DAAE00E43619 /* libbz2.dylib in Frameworks */,
 				42C8EE3B1472DAAE00E43619 /* libbz2.dylib in Frameworks */,
 				42C8EE391472DAA300E43619 /* libz.dylib in Frameworks */,
 				42C8EE391472DAA300E43619 /* libz.dylib in Frameworks */,
 				42C8EE371472D7E700E43619 /* libxml2.dylib in Frameworks */,
 				42C8EE371472D7E700E43619 /* libxml2.dylib in Frameworks */,
+				5BCD0643152CFC3C0071FAB5 /* libpng.a in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -194,7 +196,6 @@
 		42475CDB147208A000610A6A = {
 		42475CDB147208A000610A6A = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				4283906414896F3000E2B2F5 /* gameplay */,
 				42475CE9147208A000610A6A /* src */,
 				42475CE9147208A000610A6A /* src */,
 				427D4F44147DC9080076760E /* Libraries */,
 				427D4F44147DC9080076760E /* Libraries */,
 				42475CE7147208A000610A6A /* Products */,
 				42475CE7147208A000610A6A /* Products */,
@@ -224,6 +225,9 @@
 				4283905814896E6C00E2B2F5 /* BoundingVolume.h */,
 				4283905814896E6C00E2B2F5 /* BoundingVolume.h */,
 				42C8EDBF14724CD700E43619 /* Camera.cpp */,
 				42C8EDBF14724CD700E43619 /* Camera.cpp */,
 				42C8EDC014724CD700E43619 /* Camera.h */,
 				42C8EDC014724CD700E43619 /* Camera.h */,
+				4251B128152D044B002F6199 /* Curve.cpp */,
+				4251B129152D044B002F6199 /* Curve.h */,
+				4251B12A152D044B002F6199 /* Curve.inl */,
 				42C8EDC314724CD700E43619 /* DAEChannelTarget.cpp */,
 				42C8EDC314724CD700E43619 /* DAEChannelTarget.cpp */,
 				42C8EDC414724CD700E43619 /* DAEChannelTarget.h */,
 				42C8EDC414724CD700E43619 /* DAEChannelTarget.h */,
 				42C8EDC514724CD700E43619 /* DAEOptimizer.cpp */,
 				42C8EDC514724CD700E43619 /* DAEOptimizer.cpp */,
@@ -273,6 +277,7 @@
 				42C8EDF114724CD700E43619 /* Object.h */,
 				42C8EDF114724CD700E43619 /* Object.h */,
 				42C8EDF214724CD700E43619 /* Quaternion.cpp */,
 				42C8EDF214724CD700E43619 /* Quaternion.cpp */,
 				42C8EDF314724CD700E43619 /* Quaternion.h */,
 				42C8EDF314724CD700E43619 /* Quaternion.h */,
+				4251B12B152D044B002F6199 /* Quaternion.inl */,
 				42C8EDF414724CD700E43619 /* Reference.cpp */,
 				42C8EDF414724CD700E43619 /* Reference.cpp */,
 				42C8EDF514724CD700E43619 /* Reference.h */,
 				42C8EDF514724CD700E43619 /* Reference.h */,
 				42C8EDF614724CD700E43619 /* ReferenceTable.cpp */,
 				42C8EDF614724CD700E43619 /* ReferenceTable.cpp */,
@@ -306,6 +311,7 @@
 		427D4F44147DC9080076760E /* Libraries */ = {
 		427D4F44147DC9080076760E /* Libraries */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				5BCD0642152CFC3C0071FAB5 /* libpng.a */,
 				42D277571472EFA700D867A4 /* libpcre.a */,
 				42D277571472EFA700D867A4 /* libpcre.a */,
 				42D277581472EFA700D867A4 /* libpcrecpp.a */,
 				42D277581472EFA700D867A4 /* libpcrecpp.a */,
 				42C8EE3A1472DAAE00E43619 /* libbz2.dylib */,
 				42C8EE3A1472DAAE00E43619 /* libbz2.dylib */,
@@ -313,20 +319,10 @@
 				42C8EE361472D7E700E43619 /* libxml2.dylib */,
 				42C8EE361472D7E700E43619 /* libxml2.dylib */,
 				42C8EE341472B60100E43619 /* libfreetype.a */,
 				42C8EE341472B60100E43619 /* libfreetype.a */,
 				42475D7B14720ECE00610A6A /* libdom.a */,
 				42475D7B14720ECE00610A6A /* libdom.a */,
-				42DDE88415191CDA00D9B550 /* libpng.a */,
 			);
 			);
 			name = Libraries;
 			name = Libraries;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
-		4283906414896F3000E2B2F5 /* gameplay */ = {
-			isa = PBXGroup;
-			children = (
-				4283906114896F1600E2B2F5 /* Curve.cpp */,
-				4283906214896F1600E2B2F5 /* Curve.h */,
-			);
-			name = gameplay;
-			sourceTree = "<group>";
-		};
 /* End PBXGroup section */
 /* End PBXGroup section */
 
 
 /* Begin PBXNativeTarget section */
 /* Begin PBXNativeTarget section */
@@ -418,8 +414,8 @@
 				42C8EE3214724CD700E43619 /* Vertex.cpp in Sources */,
 				42C8EE3214724CD700E43619 /* Vertex.cpp in Sources */,
 				42C8EE3314724CD700E43619 /* VertexElement.cpp in Sources */,
 				42C8EE3314724CD700E43619 /* VertexElement.cpp in Sources */,
 				4283905914896E6C00E2B2F5 /* BoundingVolume.cpp in Sources */,
 				4283905914896E6C00E2B2F5 /* BoundingVolume.cpp in Sources */,
-				4283906314896F1600E2B2F5 /* Curve.cpp in Sources */,
 				42783423148D6F7500A6E27F /* FBXSceneEncoder.cpp in Sources */,
 				42783423148D6F7500A6E27F /* FBXSceneEncoder.cpp in Sources */,
+				4251B12C152D044B002F6199 /* Curve.cpp in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -503,7 +499,7 @@
 		42475CF1147208A100610A6A /* Debug */ = {
 		42475CF1147208A100610A6A /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
 				CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
 				CLANG_CXX_LIBRARY = "compiler-default";
 				CLANG_CXX_LIBRARY = "compiler-default";
 				GCC_C_LANGUAGE_STANDARD = "compiler-default";
 				GCC_C_LANGUAGE_STANDARD = "compiler-default";
@@ -520,12 +516,11 @@
 				);
 				);
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
-					"\"$(SRCROOT)/../external-deps/freetype2/lib/macos\"",
-					"\"$(SRCROOT)/../external-deps/collada-dom/lib/macos\"",
-					"\"$(SRCROOT)/../external-deps/pcre/lib/macos\"",
-					"\"$(SRCROOT)/../../../Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug\"",
-					"\"$(SYSTEM_APPS_DIR)/Autodesk/FBXSDK20122/lib/gcc4/ub\"",
-					"\"$(SRCROOT)/../external-deps/libpng/lib/macos\"",
+					"\"$(SRCROOT)/../external-deps/freetype2/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/collada-dom/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/pcre/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/libpng/lib/macosx\"",
+					"\"$(SRCROOT)\"",
 				);
 				);
 				MACH_O_TYPE = mh_execute;
 				MACH_O_TYPE = mh_execute;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -536,7 +531,7 @@
 		42475CF2147208A100610A6A /* Release */ = {
 		42475CF2147208A100610A6A /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
 				CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
 				CLANG_CXX_LIBRARY = "compiler-default";
 				CLANG_CXX_LIBRARY = "compiler-default";
 				GCC_C_LANGUAGE_STANDARD = "compiler-default";
 				GCC_C_LANGUAGE_STANDARD = "compiler-default";
@@ -553,12 +548,11 @@
 				);
 				);
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
-					"\"$(SRCROOT)/../external-deps/freetype2/lib/macos\"",
-					"\"$(SRCROOT)/../external-deps/collada-dom/lib/macos\"",
-					"\"$(SRCROOT)/../external-deps/pcre/lib/macos\"",
-					"\"$(SRCROOT)/../../../Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug\"",
-					"\"$(SYSTEM_APPS_DIR)/Autodesk/FBXSDK20122/lib/gcc4/ub\"",
-					"\"$(SRCROOT)/../external-deps/libpng/lib/macos\"",
+					"\"$(SRCROOT)/../external-deps/freetype2/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/collada-dom/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/pcre/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/libpng/lib/macosx\"",
+					"\"$(SRCROOT)\"",
 				);
 				);
 				MACH_O_TYPE = mh_execute;
 				MACH_O_TYPE = mh_execute;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";

+ 1 - 0
gameplay-encoder/src/Camera.h

@@ -44,6 +44,7 @@ public:
     };
     };
 
 
 private:
 private:
+    
     unsigned char _cameraType;
     unsigned char _cameraType;
     float _fieldOfView;
     float _fieldOfView;
     float _aspectRatio;
     float _aspectRatio;

+ 1346 - 0
gameplay-encoder/src/Curve.cpp

@@ -0,0 +1,1346 @@
+// Purposely not including Base.h here, or any other gameplay dependencies
+// so this class can be reused between gameplay and gameplay-encoder.
+#include "Curve.h"
+#include "Quaternion.h"
+#include <cassert>
+#include <cmath>
+#include <memory>
+
+using std::memcpy;
+using std::fabs;
+using std::sqrt;
+using std::cos;
+using std::sin;
+using std::exp;
+using std::strcmp;
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef MATH_PI
+#define MATH_PI 3.14159265358979323846f
+#endif
+
+#ifndef MATH_PIOVER2 
+#define MATH_PIOVER2 1.57079632679489661923f
+#endif
+
+#ifndef MATH_PIX2
+#define MATH_PIX2 6.28318530717958647693f
+#endif
+
+// Object deletion macro
+#ifndef SAFE_DELETE
+#define SAFE_DELETE(x) \
+    if (x) \
+    { \
+        delete x; \
+        x = NULL; \
+    }
+#endif
+
+// Array deletion macro
+#ifndef SAFE_DELETE_ARRAY
+#define SAFE_DELETE_ARRAY(x) \
+    if (x) \
+    { \
+        delete[] x; \
+        x = NULL; \
+    }
+#endif
+
+
+namespace gameplay
+{
+
+Curve::Curve(unsigned int pointCount, unsigned int componentCount)
+    : _pointCount(pointCount), _componentCount(componentCount), _componentSize(sizeof(float)*componentCount), _quaternionOffset(NULL), _points(NULL)
+{
+    _points = new Point[_pointCount];
+    for (unsigned int i = 0; i < _pointCount; i++)
+    {
+        _points[i].time = 0.0f;
+        _points[i].value = new float[_componentCount];
+        _points[i].inValue = new float[_componentCount];
+        _points[i].outValue = new float[_componentCount];
+        _points[i].type = LINEAR;
+    }
+    _points[_pointCount - 1].time = 1.0f;
+}
+
+Curve::~Curve()
+{
+    SAFE_DELETE_ARRAY(_points);
+    SAFE_DELETE_ARRAY(_quaternionOffset);
+}
+
+Curve::Point::Point()
+    : time(0.0f), value(NULL), inValue(NULL), outValue(NULL)
+{
+}
+
+Curve::Point::~Point()
+{
+    SAFE_DELETE_ARRAY(value);
+    SAFE_DELETE_ARRAY(inValue);
+    SAFE_DELETE_ARRAY(outValue);
+}
+
+unsigned int Curve::getPointCount() const
+{
+    return _pointCount;
+}
+
+unsigned int Curve::getComponentCount() const
+{
+    return _componentCount;
+}
+
+float Curve::getStartTime() const
+{
+    return _points[0].time;
+}
+
+float Curve::getEndTime() const
+{
+    return _points[_pointCount-1].time;
+}
+
+void Curve::setPoint(unsigned int index, float time, float* value, InterpolationType type)
+{
+    setPoint(index, time, value, type, NULL, NULL);
+}
+
+void Curve::setPoint(unsigned int index, float time, float* value, InterpolationType type, float* inValue, float* outValue)
+{
+    assert(index < _pointCount && time >= 0.0f && time <= 1.0f && !(index == 0 && time != 0.0f) && !(index == _pointCount - 1 && time != 1.0f));
+
+    _points[index].time = time;
+    _points[index].type = type;
+
+    if (value)
+        memcpy(_points[index].value, value, _componentSize);
+
+    if (inValue)
+        memcpy(_points[index].inValue, inValue, _componentSize);
+
+    if (outValue)
+        memcpy(_points[index].outValue, outValue, _componentSize);
+}
+
+void Curve::setTangent(unsigned int index, InterpolationType type, float* inValue, float* outValue)
+{
+    assert(index < _pointCount);
+
+    _points[index].type = type;
+
+    if (inValue)
+        memcpy(_points[index].inValue, inValue, _componentSize);
+
+    if (outValue)
+        memcpy(_points[index].outValue, outValue, _componentSize);
+}
+
+void Curve::evaluate(float time, float* dst) const
+{
+    assert(dst && time >= 0 && time <= 1.0f);
+
+    // Check if we are at or beyond the bounds of the curve.
+    if (time <= _points[0].time)
+    {
+        memcpy(dst, _points[0].value, _componentSize);
+        return;
+    }
+    else if (time >= _points[_pointCount - 1].time)
+    {
+        memcpy(dst, _points[_pointCount - 1].value, _componentSize);
+        return;
+    }
+
+    // Locate the points we are interpolating between using a binary search.
+    unsigned int index = determineIndex(time);
+    
+    Point* from = _points + index;
+    Point* to = _points + (index + 1);
+
+    // Calculate the fractional time between the two points.
+    float scale = (to->time - from->time);
+    float t = (time - from->time) / scale;
+
+    // Calculate the value of the curve discretely if appropriate.
+    switch (from->type)
+    {
+        case BEZIER:
+        {
+            interpolateBezier(t, from, to, dst);
+            return;
+        }
+        case BSPLINE:
+        {
+            Point* c0;
+            Point* c1;
+            if (index == 0)
+            {
+                c0 = from;
+            }
+            else
+            {
+                c0 = (_points + index - 1);
+            }
+            
+            if (index == _pointCount - 2)
+            {
+                c1 = to;
+            }
+            else
+            {
+                c1 = (_points + index + 2);
+            }
+            interpolateBSpline(t, c0, from, to, c1, dst);
+            return;
+        }
+        case FLAT:
+        {
+            interpolateHermiteFlat(t, from, to, dst);
+            return;
+        }
+        case HERMITE:
+        {
+            interpolateHermite(t, from, to, dst);
+            return;
+        }
+        case LINEAR:
+        {
+            // Can just break here because linear formula follows switch
+            break;
+        }
+        case SMOOTH:
+        {
+            interpolateHermiteSmooth(t, index, from, to, dst);
+            return;
+        }
+        case STEP:
+        {
+            memcpy(dst, from->value, _componentSize);
+            return;
+        }
+        case QUADRATIC_IN:
+        {
+            t *= t;
+            break;
+        }
+        case QUADRATIC_OUT:
+        {
+            t *= -(t - 2.0f);
+            break;
+        }
+        case QUADRATIC_IN_OUT:
+        {
+            float tx2 = t * 2.0f;
+
+            if (tx2 < 1.0f)
+                t = 0.5f * (tx2 * tx2);
+            else
+            {
+                float temp = tx2 - 1.0f;
+                t = 0.5f * (-( temp * (temp - 2.0f)) + 1.0f);
+            }
+            break;
+        }
+        case QUADRATIC_OUT_IN:
+        {
+            if (t < 0.5f)
+            {
+                t = 2.0f * t * (1.0f - t);
+            }
+            else
+            {
+                t = 1.0f + 2.0f * t * (t - 1.0f);
+            }
+            break;
+        }
+        case CUBIC_IN:
+        {
+            t *= t * t;
+            break;
+        }
+        case CUBIC_OUT:
+        {
+            t--;
+            t = t * t * t + 1;
+            break;
+        }
+        case CUBIC_IN_OUT:
+        {
+            if ((t *= 2.0f) < 1.0f)
+            {
+                t = t * t * t * 0.5f;
+            }
+            else
+            {
+                t -= 2.0f;
+                t = (t * t * t + 2.0f) * 0.5f;
+            }
+            break;
+        }
+        case CUBIC_OUT_IN:
+        {
+            t = (2.0f * t - 1.0f);
+            t = (t * t * t + 1) * 0.5f;
+            break;
+        }
+        case QUARTIC_IN:
+        {
+            t *= t * t * t;
+            break;
+        }
+        case QUARTIC_OUT:
+        {
+            t--;
+            t = -(t * t * t * t) + 1.0f;
+            break;
+        }
+        case QUARTIC_IN_OUT:
+        {
+            t *= 2.0f;
+            if (t < 1.0f)
+            {
+                t = 0.5f * t * t * t * t;
+            }
+            else
+            {
+                t -= 2.0f;
+                t = -0.5f * (t * t * t * t - 2.0f);
+            }
+            break;
+        }
+        case QUARTIC_OUT_IN:
+        {
+            t = 2.0f * t - 1.0f;
+            if (t < 0.0f)
+            {
+                t = 0.5f * (-(t * t) * t * t + 1.0f);
+            }
+            else
+            {
+                t = 0.5f * (t * t * t * t + 1.0f);
+            }
+            break;
+        }
+        case QUINTIC_IN:
+        {
+            t *= t * t * t * t;
+            break;
+        }
+        case QUINTIC_OUT:
+        {
+            t--;
+            t = t * t * t * t * t + 1.0f;
+            break;
+        }
+        case QUINTIC_IN_OUT:
+        {
+            t *= 2.0f;
+            if (t < 1.0f)
+            {
+                t = 0.5f * t * t * t * t * t;
+            }
+            else
+            {
+                t -= 2.0f;
+                t = 0.5f * (t * t * t * t * t + 2.0f);
+            }
+            break;
+        }
+        case QUINTIC_OUT_IN:
+        {
+            t = 2.0f * t - 1.0f;
+            t = 0.5f * (t * t * t * t * t + 1.0f);
+            break;
+        }
+        case SINE_IN:
+        {
+            t = -(cos(t * MATH_PIOVER2) - 1.0f);
+            break;
+        }
+        case SINE_OUT:
+        {
+            t = sin(t * MATH_PIOVER2);
+            break;
+        }
+        case SINE_IN_OUT:
+        {
+            t = -0.5f * (cos(MATH_PI * t) - 1.0f);
+            break;
+        }
+        case SINE_OUT_IN:
+        {
+            if (t < 0.5f)
+            {
+                t = 0.5f * sin(MATH_PI * t);
+            }
+            else
+            {
+                t = -0.5f * cos(MATH_PIOVER2 * (2.0f * t - 1.0f)) + 1.0f;
+            }
+            break;
+        }
+        case EXPONENTIAL_IN:
+        {
+            if (t != 0.0f)
+            {
+                t = exp(10.0f * (t - 1.0f));
+            }
+            break;
+        }
+        case EXPONENTIAL_OUT:
+        {
+            if (t != 1.0f)
+            {
+                t = -exp(-10.0f * t) + 1.0f;
+            }
+            break;
+        }
+        case EXPONENTIAL_IN_OUT:
+        {
+            if (t != 0.0f && t != 1.0f)
+            {
+                if (t < 0.5f)
+                {
+                    t = 0.5f * exp(10.0f * (2.0f * t - 1.0f));
+                }
+                else
+                {
+                    t = -0.5f * exp(10.0f * (-2.0f * t + 1.0f)) + 1.0f;
+                }
+            }
+            break;
+        }
+        case EXPONENTIAL_OUT_IN:
+        {
+            if (t != 0.0f && t != 1.0f)
+            {
+                if (t < 0.5f)
+                {
+                    t = -0.5f * exp(-20.0f * t) + 0.5f;
+                }
+                else
+                {
+                    t = 0.5f * exp(20.0f * (t - 1.0f)) + 0.5f;
+                }
+            }
+            break;
+        }
+        case CIRCULAR_IN:
+        {
+            t = -(sqrt(1.0f - t * t) - 1.0f);
+            break;
+        }
+        case CIRCULAR_OUT:
+        {
+            t--;
+            t = sqrt(1.0f - t * t);
+            break;
+        }
+        case CIRCULAR_IN_OUT:
+        {
+            t *= 2.0f;
+            if (t < 1.0f)
+            {
+                t = 0.5f * (-sqrt((1.0f - t * t)) + 1.0f);
+            }
+            else
+            {
+                t -= 2.0f;
+                t = 0.5f * (sqrt((1.0f - t * t)) + 1.0f);
+            }
+            break;
+        }
+        case CIRCULAR_OUT_IN:
+        {
+            t = 2.0f * t - 1.0f;
+            if (t < 0.0f)
+            {
+                t = 0.5f * sqrt(1.0f - t * t);
+            }
+            else
+            {
+                t = 0.5f * (2.0f - sqrt(1.0f - t * t));
+            }
+            break;
+        }
+        case ELASTIC_IN:
+        {
+            if (t != 0.0f && t != 1.0f)
+            {
+                t = t - 1.0f;
+                t = -1.0f * ( exp(10.0f * t) * sin( (t - 0.075f) * MATH_PIX2 / 0.3f ) );
+            }
+            break;
+        }
+        case ELASTIC_OUT:
+        {
+            if (t != 0.0f && t != 1.0f)
+            {
+                t = exp(-10.0f * t) * sin((t - 0.075f) * MATH_PIX2 / 0.3f) + 1.0f;
+            }
+            break;
+        }
+        case ELASTIC_IN_OUT:
+        {
+            if (t != 0.0f && t != 1.0f)
+            {
+                t = 2.0f * t - 1.0f;
+                if (t < 0.0f)
+                {
+                    t = -0.5f * (exp((10 * t)) * sin(((t - 0.1125f) * MATH_PIX2 / 0.45f)));
+                }
+                else
+                {
+                    t = 0.5f * exp((-10 * t)) * sin(((t - 0.1125f) * MATH_PIX2 / 0.45f)) + 1.0f;
+                }
+            }
+            break;
+        }
+        case ELASTIC_OUT_IN:
+        {
+            if (t != 0.0f && t != 1.0f)
+            {
+                t *= 2.0f;
+                if (t < 1.0f)
+                {
+                    t = 0.5f * (exp((-10 * t)) * sin(((t - 0.1125f) * (MATH_PIX2) / 0.45f))) + 0.5f;
+                }
+                else
+                {
+                    t = 0.5f * (exp((10 *(t - 2))) * sin(((t - 0.1125f) * (MATH_PIX2) / 0.45f))) + 0.5f;
+                }
+            }
+            break;
+        }
+        case OVERSHOOT_IN:
+        {
+            t = t * t * (2.70158f * t - 1.70158f);
+            break;
+        }
+        case OVERSHOOT_OUT:
+        {
+            t--;
+            t = t * t * (2.70158f * t + 1.70158f) + 1;
+            break;
+        }
+        case OVERSHOOT_IN_OUT:
+        {
+            t *= 2.0f;
+            if (t < 1.0f)
+            {
+                t = 0.5f * t * t * (3.5949095f * t - 2.5949095f);
+            }
+            else
+            {
+                t -= 2.0f;
+                t = 0.5f * (t * t * (3.5949095f * t + 2.5949095f) + 2.0f);
+            }
+            break;
+        }
+        case OVERSHOOT_OUT_IN:
+        {
+            t = 2.0f * t - 1.0f;
+            if (t < 0.0f)
+            {
+                t = 0.5f * (t * t * (3.5949095f * t + 2.5949095f) + 1.0f);
+            }
+            else
+            {
+                t = 0.5f * (t * t * (3.5949095f * t - 2.5949095f) + 1.0f);
+            }
+            break;
+        }
+        case BOUNCE_IN:
+        {
+            t = 1.0f - t;
+
+            if (t < 0.36363636363636365f)
+            {
+                t = 7.5625f * t * t;
+            }
+            else if (t < 0.7272727272727273f)
+            {
+                t -= 0.5454545454545454f;
+                t = 7.5625f * t * t + 0.75f;
+            }
+            else if (t < 0.9090909090909091f)
+            {
+                t -= 0.8181818181818182f;
+                t = 7.5625f * t * t + 0.9375f;
+            }
+            else
+            {
+                t -= 0.9545454545454546f;
+                t = 7.5625f * t * t + 0.984375f;
+            }
+
+            t = 1.0f - t;
+            break;
+        }
+        case BOUNCE_OUT:
+        {
+            if (t < 0.36363636363636365f)
+            {
+                t = 7.5625f * t * t;
+            }
+            else if (t < 0.7272727272727273f)
+            {
+                t -= 0.5454545454545454f;
+                t = 7.5625f * t * t + 0.75f;
+            }
+            else if (t < 0.9090909090909091f)
+            {
+                t -= 0.8181818181818182f;
+                t = 7.5625f * t * t + 0.9375f;
+            }
+            else
+            {
+                t -= 0.9545454545454546f;
+                t = 7.5625f * t * t + 0.984375f;
+            }
+            break;
+        }
+        case BOUNCE_IN_OUT:
+        {
+            if (t < 0.5f)
+            {
+                t = 1.0f - t * 2.0f;
+
+                if (t < 0.36363636363636365f)
+                {
+                    t = 7.5625f * t * t;
+                }
+                else if (t < 0.7272727272727273f)
+                {
+                    t -= 0.5454545454545454f;
+                    t = 7.5625f * t * t + 0.75f;
+                }
+                else if (t < 0.9090909090909091f)
+                {
+                    t -= 0.8181818181818182f;
+                    t = 7.5625f * t * t + 0.9375f;
+                }
+                else
+                {
+                    t -= 0.9545454545454546f;
+                    t = 7.5625f * t * t + 0.984375f;
+                }
+
+                t = (1.0f - t) * 0.5f;
+            }
+            else
+            {
+                t = t * 2.0f - 1.0f;
+                if (t < 0.36363636363636365f)
+                {
+                    t = 7.5625f * t * t;
+                }
+                else if (t < 0.7272727272727273f)
+                {
+                    t -= 0.5454545454545454f;
+                    t = 7.5625f * t * t + 0.75f;
+                }
+                else if (t < 0.9090909090909091f)
+                {
+                    t -= 0.8181818181818182f;
+                    t = 7.5625f * t * t + 0.9375f;
+                }
+                else
+                {
+                    t -= 0.9545454545454546f;
+                    t = 7.5625f * t * t + 0.984375f;
+                }
+
+                t = 0.5f * t + 0.5f;
+            }
+            break;
+        }
+        case BOUNCE_OUT_IN:
+        {
+            if (t < 0.1818181818f)
+            {
+                t = 15.125f * t * t;
+            }
+            else if (t < 0.3636363636f)
+            {
+                t = 1.5f + (-8.250000001f + 15.125f * t) * t;
+            }
+            else if (t < 0.4545454546f)
+            {
+                t = 3.0f + (-12.375f + 15.125f * t) * t;
+            }
+            else if (t < 0.5f)
+            {
+                t = 3.9375f + (-14.4375f + 15.125f * t) * t;
+            }
+            else if (t <= 0.5454545455f)
+            {
+                t = -3.625000004f + (15.81250001f - 15.125f * t) * t;
+            }
+            else if (t <= 0.6363636365f)
+            {
+                t = -4.75f + (17.875f - 15.125f * t) * t;
+            }
+            else if (t <= 0.8181818180f)
+            {
+                t = -7.374999995f + (21.99999999f - 15.125f * t) * t;
+            }
+            else
+            {
+                t = -14.125f + (30.25f - 15.125f * t) * t;
+            }
+            break;
+        }
+    }
+
+    interpolateLinear(t, from, to, dst);
+}
+
+float Curve::lerp(float t, float from, float to)
+{
+    return lerpInl(t, from, to);
+}
+
+void Curve::setQuaternionOffset(unsigned int offset)
+{
+    assert(offset <= (_componentCount - 4));
+
+    if (!_quaternionOffset)
+        _quaternionOffset = new unsigned int[1];
+    
+    *_quaternionOffset = offset;
+}
+
+void Curve::interpolateBezier(float s, Point* from, Point* to, float* dst) const
+{
+    float s_2 = s * s;
+    float eq0 = 1 - s;
+    float eq0_2 = eq0 * eq0;
+    float eq1 = eq0_2 * eq0;
+    float eq2 = 3 * s * eq0_2;
+    float eq3 = 3 * s_2 * eq0;
+    float eq4 = s_2 * s;
+
+    float* fromValue = from->value;
+    float* toValue = to->value;
+    float* outValue = from->outValue;
+    float* inValue = to->inValue;
+
+
+    if (!_quaternionOffset)
+    {
+        for (unsigned int i = 0; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = bezier(eq1, eq2, eq3, eq4, fromValue[i], outValue[i], toValue[i], inValue[i]);
+        }
+    }
+    else
+    {
+        // Interpolate any values up to the quaternion offset as scalars.
+        unsigned int quaternionOffset = *_quaternionOffset;
+        unsigned int i = 0;
+        for (i = 0; i < quaternionOffset; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = bezier(eq1, eq2, eq3, eq4, fromValue[i], outValue[i], toValue[i], inValue[i]);
+        }
+
+        // Handle quaternion component.
+        float interpTime = bezier(eq1, eq2, eq3, eq4, from->time, outValue[i], to->time, inValue[i]);
+        interpolateQuaternion(interpTime, (fromValue + i), (toValue + i), (dst + i));
+        
+        // Handle remaining components (if any) as scalars
+        for (i += 4; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = bezier(eq1, eq2, eq3, eq4, fromValue[i], outValue[i], toValue[i], inValue[i]);
+        }
+    }
+}
+
+void Curve::interpolateBSpline(float s, Point* c0, Point* c1, Point* c2, Point* c3, float* dst) const
+{   
+    float s_2 = s * s;
+    float s_3 = s_2 * s;
+    float eq0 = (-s_3 + 3 * s_2 - 3 * s + 1) / 6.0f;
+    float eq1 = (3 * s_3 - 6 * s_2 + 4) / 6.0f;
+    float eq2 = (-3 * s_3 + 3 * s_2 + 3 * s + 1) / 6.0f;
+    float eq3 = s_3 / 6.0f;
+
+    float* c0Value = c0->value;
+    float* c1Value = c1->value;
+    float* c2Value = c2->value;
+    float* c3Value = c3->value;
+
+    if (!_quaternionOffset)
+    {
+        for (unsigned int i = 0; i < _componentCount; i++)
+        {
+            if (c1Value[i] == c2Value[i])
+                dst[i] = c1Value[i];
+            else
+                dst[i] = bspline(eq0, eq1, eq2, eq3, c0Value[i], c1Value[i], c2Value[i], c3Value[i]);
+        }
+    }
+    else
+    {
+        // Interpolate any values up to the quaternion offset as scalars.
+        unsigned int quaternionOffset = *_quaternionOffset;
+        unsigned int i = 0;
+        for (i = 0; i < quaternionOffset; i++)
+        {
+            if (c1Value[i] == c2Value[i])
+                dst[i] = c1Value[i];
+            else
+                dst[i] = bspline(eq0, eq1, eq2, eq3, c0Value[i], c1Value[i], c2Value[i], c3Value[i]);
+        }
+
+        // Handle quaternion component.
+        float interpTime;
+        if (c0->time == c1->time)
+            interpTime = bspline(eq0, eq1, eq2, eq3, -c0->time, c1->time, c2->time, c3->time);
+        else if (c2->time == c3->time)
+            interpTime = bspline(eq0, eq1, eq2, eq3, c0->time, c1->time, c2->time, -c3->time); 
+        else
+            interpTime = bspline(eq0, eq1, eq2, eq3, c0->time, c1->time, c2->time, c3->time);
+        interpolateQuaternion(s, (c1Value + i) , (c2Value + i), (dst + i));
+            
+        // Handle remaining components (if any) as scalars
+        for (i += 4; i < _componentCount; i++)
+        {
+            if (c1Value[i] == c2Value[i])
+                dst[i] = c1Value[i];
+            else
+                dst[i] = bspline(eq0, eq1, eq2, eq3, c0Value[i], c1Value[i], c2Value[i], c3Value[i]);
+        }
+    }
+}
+
+void Curve::interpolateHermite(float s, Point* from, Point* to, float* dst) const
+{
+    // Calculate the hermite basis functions.
+    float s_2 = s * s;                   // t^2
+    float s_3 = s_2 * s;                 // t^3
+    float h00 = 2 * s_3 - 3 * s_2 + 1;   // basis function 0
+    float h01 = -2 * s_3 + 3 * s_2;      // basis function 1
+    float h10 = s_3 - 2 * s_2 + s;       // basis function 2
+    float h11 = s_3 - s_2;               // basis function 3
+
+    float* fromValue = from->value;
+    float* toValue = to->value;
+    float* outValue = from->outValue;
+    float* inValue = to->inValue;
+
+    if (!_quaternionOffset)
+    {
+        for (unsigned int i = 0; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = hermite(h00, h01, h10, h11, fromValue[i], outValue[i], toValue[i], inValue[i]);
+        }
+    }
+    else
+    {
+        // Interpolate any values up to the quaternion offset as scalars.
+        unsigned int quaternionOffset = *_quaternionOffset;
+        unsigned int i = 0;
+        for (i = 0; i < quaternionOffset; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = hermite(h00, h01, h10, h11, fromValue[i], outValue[i], toValue[i], inValue[i]);
+        }
+
+        // Handle quaternion component.
+        float interpTime = hermite(h00, h01, h10, h11, from->time, outValue[i], to->time, inValue[i]);
+        interpolateQuaternion(interpTime, (fromValue + i), (toValue + i), (dst + i));
+        
+        // Handle remaining components (if any) as scalars
+        for (i += 4; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = hermite(h00, h01, h10, h11, fromValue[i], outValue[i], toValue[i], inValue[i]);
+        }
+    }
+}
+
+void Curve::interpolateHermiteFlat(float s, Point* from, Point* to, float* dst) const
+{
+    // Calculate the hermite basis functions.
+    float s_2 = s * s;                   // t^2
+    float s_3 = s_2 * s;                 // t^3
+    float h00 = 2 * s_3 - 3 * s_2 + 1;   // basis function 0
+    float h01 = -2 * s_3 + 3 * s_2;      // basis function 1
+
+    float* fromValue = from->value;
+    float* toValue = to->value;
+
+    if (!_quaternionOffset)
+    {
+        for (unsigned int i = 0; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = hermiteFlat(h00, h01, fromValue[i], toValue[i]);
+        }
+    }
+    else
+    {
+        // Interpolate any values up to the quaternion offset as scalars.
+        unsigned int quaternionOffset = *_quaternionOffset;
+        unsigned int i = 0;
+        for (i = 0; i < quaternionOffset; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = hermiteFlat(h00, h01, fromValue[i], toValue[i]);
+        }
+
+        // Handle quaternion component.
+        float interpTime = hermiteFlat(h00, h01, from->time, to->time);
+        interpolateQuaternion(interpTime, (fromValue + i), (toValue + i), (dst + i));
+        
+        // Handle remaining components (if any) as scalars
+        for (i += 4; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = hermiteFlat(h00, h01, fromValue[i], toValue[i]);
+        }
+    }
+}
+
+void Curve::interpolateHermiteSmooth(float s, unsigned int index, Point* from, Point* to, float* dst) const
+{
+    // Calculate the hermite basis functions.
+    float s_2 = s * s;                   // t^2
+    float s_3 = s_2 * s;                 // t^3
+    float h00 = 2 * s_3 - 3 * s_2 + 1;   // basis function 0
+    float h01 = -2 * s_3 + 3 * s_2;      // basis function 1
+    float h10 = s_3 - 2 * s_2 + s;       // basis function 2
+    float h11 = s_3 - s_2;               // basis function 3
+
+    float inValue;
+    float outValue;
+
+    float* fromValue = from->value;
+    float* toValue = to->value;
+
+    if (!_quaternionOffset)
+    {
+        for (unsigned int i = 0; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+            {
+                dst[i] = fromValue[i];
+            }
+            else
+            {
+                if (index == 0)
+                {
+                    outValue = toValue[i] - fromValue[i];
+                }
+                else
+                {
+                    outValue = (toValue[i] - (from - 1)->value[i]) * ((from->time - (from - 1)->time) / (to->time - (from - 1)->time));
+                }
+
+                if (index == _pointCount - 2)
+                {
+                    inValue = toValue[i] - fromValue[i];
+                }
+                else
+                {
+                    inValue = ((to + 1)->value[i] - fromValue[i]) * ((to->time - from->time) / ((to + 1)->time - from->time));
+                }
+
+                dst[i] = hermiteSmooth(h00, h01, h10, h11, fromValue[i], outValue, toValue[i], inValue);
+            }
+        }
+    }
+    else
+    {
+        // Interpolate any values up to the quaternion offset as scalars.
+        unsigned int quaternionOffset = *_quaternionOffset;
+        unsigned int i = 0;
+        for (i = 0; i < quaternionOffset; i++)
+        {   
+            if (fromValue[i] == toValue[i])
+            {
+                dst[i] = fromValue[i];
+            }
+            else
+            {    
+                if (index == 0)
+                {
+                    outValue = toValue[i] - fromValue[i];
+                }
+                else
+                {
+                    outValue = (toValue[i] - (from - 1)->value[i]) * ((from->time - (from - 1)->time) / (to->time - (from - 1)->time));
+                }
+
+                if (index == _pointCount - 2)
+                {
+                    inValue = toValue[i] - fromValue[i];
+                }
+                else
+                {
+                    inValue = ((to + 1)->value[i] - fromValue[i]) * ((to->time - from->time) / ((to + 1)->time - from->time));
+                }
+
+                dst[i] = hermiteSmooth(h00, h01, h10, h11, fromValue[i], outValue, toValue[i], inValue);
+            }
+        }
+
+        // Handle quaternion component.
+        if (index == 0)
+        {
+            outValue = to->time - from->time;
+        }
+        else
+        {
+            outValue = (to->time - (from - 1)->time) * ((from->time - (from - 1)->time) / (to->time - (from - 1)->time));
+        }
+
+        if (index == _pointCount - 2)
+        {
+            inValue = to->time - from->time;
+        }
+        else
+        {
+            inValue = ((to + 1)->time - from->time) * ((to->time - from->time) / ((to + 1)->time - from->time));
+        }
+
+        float interpTime = hermiteSmooth(h00, h01, h10, h11, from->time, outValue, to->time, inValue);
+        interpolateQuaternion(interpTime, (fromValue + i), (toValue + i), (dst + i));
+        
+        // Handle remaining components (if any) as scalars
+        for (i += 4; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+            {
+                dst[i] = fromValue[i];
+            }
+            else
+            {
+                // Interpolate as scalar.
+                if (index == 0)
+                {
+                    outValue = toValue[i] - fromValue[i];
+                }
+                else
+                {
+                    outValue = (toValue[i] - (from - 1)->value[i]) * ((from->time - (from - 1)->time) / (to->time - (from - 1)->time));
+                }
+
+                if (index == _pointCount - 2)
+                {
+                    inValue = toValue[i] - fromValue[i];
+                }
+                else
+                {
+                    inValue = ((to + 1)->value[i] - fromValue[i]) * ((to->time - from->time) / ((to + 1)->time - from->time));
+                }
+
+                dst[i] = hermiteSmooth(h00, h01, h10, h11, fromValue[i], outValue, toValue[i], inValue);
+            }
+        }
+    }
+}
+
+void Curve::interpolateLinear(float s, Point* from, Point* to, float* dst) const
+{
+    float* fromValue = from->value;
+    float* toValue = to->value;
+
+    if (!_quaternionOffset)
+    {
+        for (unsigned int i = 0; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = lerpInl(s, fromValue[i], toValue[i]);
+        }
+    }
+    else
+    {
+        // Interpolate any values up to the quaternion offset as scalars.
+        unsigned int quaternionOffset = *_quaternionOffset;
+        unsigned int i = 0;
+        for (i = 0; i < quaternionOffset; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = lerpInl(s, fromValue[i], toValue[i]);
+        }
+
+        // Handle quaternion component.
+        interpolateQuaternion(s, (fromValue + i), (toValue + i), (dst + i));
+        
+        // handle any remaining components as scalars
+        for (i += 4; i < _componentCount; i++)
+        {
+            if (fromValue[i] == toValue[i])
+                dst[i] = fromValue[i];
+            else
+                dst[i] = lerpInl(s, fromValue[i], toValue[i]);
+        }
+    }
+}
+
+void Curve::interpolateQuaternion(float s, float* from, float* to, float* dst) const
+{
+    // Evaluate.
+    if (s >= 0)
+    {
+        Quaternion::slerp(from[0], from[1], from[2], from[3], to[0], to[1], to[2], to[3], s, dst, dst + 1, dst + 2, dst + 3);
+    }
+    else
+        Quaternion::slerp(to[0], to[1], to[2], to[3], from[0], from[1], from[2], from[3], s, dst, dst + 1, dst + 2, dst + 3);
+
+    //((Quaternion*) dst)->normalize();
+}
+
+int Curve::determineIndex(float time) const
+{
+    unsigned int min = 0;
+    unsigned int max = _pointCount - 1;
+    unsigned int mid = 0;
+
+    // Do a binary search to determine the index.
+    do 
+    {
+        mid = (min + max) >> 1;
+
+        if (time >= _points[mid].time && time <= _points[mid + 1].time)
+            return mid;
+        else if (time < _points[mid].time)
+            max = mid - 1;
+        else
+            min = mid + 1;
+    } while (min <= max);
+    
+    // We should never hit this!
+    return -1;
+}
+
+int Curve::getInterpolationType(const char* curveId)
+{
+    if (strcmp(curveId, "BEZIER") == 0)
+    {
+        return Curve::BEZIER;
+    }
+    else if (strcmp(curveId, "BSPLINE") == 0)
+    {
+        return Curve::BSPLINE;
+    }
+    else if (strcmp(curveId, "FLAT") == 0)
+    {
+        return Curve::FLAT;
+    }
+    else if (strcmp(curveId, "HERMITE") == 0)
+    {
+        return Curve::HERMITE;
+    }
+    else if (strcmp(curveId, "LINEAR") == 0)
+    {
+        return Curve::LINEAR;
+    }
+    else if (strcmp(curveId, "SMOOTH") == 0)
+    {
+        return Curve::SMOOTH;
+    }
+    else if (strcmp(curveId, "STEP") == 0)
+    {
+        return Curve::STEP;
+    }
+    else if (strcmp(curveId, "QUADRATIC_IN") == 0)
+    {
+        return Curve::QUADRATIC_IN;
+    }
+    else if (strcmp(curveId, "QUADRATIC_OUT") == 0)
+    {
+        return Curve::QUADRATIC_OUT;
+    }
+    else if (strcmp(curveId, "QUADRATIC_IN_OUT") == 0)
+    {
+        return Curve::QUADRATIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "QUADRATIC_OUT_IN") == 0)
+    {
+        return Curve::QUADRATIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "CUBIC_IN") == 0)
+    {
+        return Curve::CUBIC_IN;
+    }
+    else if (strcmp(curveId, "CUBIC_OUT") == 0)
+    {
+        return Curve::CUBIC_OUT;
+    }
+    else if (strcmp(curveId, "CUBIC_IN_OUT") == 0)
+    {
+        return Curve::CUBIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "CUBIC_OUT_IN") == 0)
+    {
+        return Curve::CUBIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "QUARTIC_IN") == 0)
+    {
+        return Curve::QUARTIC_IN;
+    }
+    else if (strcmp(curveId, "QUARTIC_OUT") == 0)
+    {
+        return Curve::QUARTIC_OUT;
+    }
+    else if (strcmp(curveId, "QUARTIC_IN_OUT") == 0)
+    {
+        return Curve::QUARTIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "QUARTIC_OUT_IN") == 0)
+    {
+        return Curve::QUARTIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "QUINTIC_IN") == 0)
+    {
+        return Curve::QUINTIC_IN;
+    }
+    else if (strcmp(curveId, "QUINTIC_OUT") == 0)
+    {
+        return Curve::QUINTIC_OUT;
+    }
+    else if (strcmp(curveId, "QUINTIC_IN_OUT") == 0)
+    {
+        return Curve::QUINTIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "QUINTIC_OUT_IN") == 0)
+    {
+        return Curve::QUINTIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "SINE_IN") == 0)
+    {
+        return Curve::SINE_IN;
+    }
+    else if (strcmp(curveId, "SINE_OUT") == 0)
+    {
+        return Curve::SINE_OUT;
+    }
+    else if (strcmp(curveId, "SINE_IN_OUT") == 0)
+    {
+        return Curve::SINE_IN_OUT;
+    }
+    else if (strcmp(curveId, "SINE_OUT_IN") == 0)
+    {
+        return Curve::SINE_OUT_IN;
+    }
+    else if (strcmp(curveId, "EXPONENTIAL_IN") == 0)
+    {
+        return Curve::EXPONENTIAL_IN;
+    }
+    else if (strcmp(curveId, "EXPONENTIAL_OUT") == 0)
+    {
+        return Curve::EXPONENTIAL_OUT;
+    }
+    else if (strcmp(curveId, "EXPONENTIAL_IN_OUT") == 0)
+    {
+        return Curve::EXPONENTIAL_IN_OUT;
+    }
+    else if (strcmp(curveId, "EXPONENTIAL_OUT_IN") == 0)
+    {
+        return Curve::EXPONENTIAL_OUT_IN;
+    }
+    else if (strcmp(curveId, "CIRCULAR_IN") == 0)
+    {
+        return Curve::CIRCULAR_IN;
+    }
+    else if (strcmp(curveId, "CIRCULAR_OUT") == 0)
+    {
+        return Curve::CIRCULAR_OUT;
+    }
+    else if (strcmp(curveId, "CIRCULAR_IN_OUT") == 0)
+    {
+        return Curve::CIRCULAR_IN_OUT;
+    }
+    else if (strcmp(curveId, "CIRCULAR_OUT_IN") == 0)
+    {
+        return Curve::CIRCULAR_OUT_IN;
+    }
+    else if (strcmp(curveId, "ELASTIC_IN") == 0)
+    {
+        return Curve::ELASTIC_IN;
+    }
+    else if (strcmp(curveId, "ELASTIC_OUT") == 0)
+    {
+        return Curve::ELASTIC_OUT;
+    }
+    else if (strcmp(curveId, "ELASTIC_IN_OUT") == 0)
+    {
+        return Curve::ELASTIC_IN_OUT;
+    }
+    else if (strcmp(curveId, "ELASTIC_OUT_IN") == 0)
+    {
+        return Curve::ELASTIC_OUT_IN;
+    }
+    else if (strcmp(curveId, "OVERSHOOT_IN") == 0)
+    {
+        return Curve::OVERSHOOT_IN;
+    }
+    else if (strcmp(curveId, "OVERSHOOT_OUT") == 0)
+    {
+        return Curve::OVERSHOOT_OUT;
+    }
+    else if (strcmp(curveId, "OVERSHOOT_IN_OUT") == 0)
+    {
+        return Curve::OVERSHOOT_IN_OUT;
+    }
+    else if (strcmp(curveId, "OVERSHOOT_OUT_IN") == 0)
+    {
+        return Curve::OVERSHOOT_OUT_IN;
+    }
+    else if (strcmp(curveId, "BOUNCE_IN") == 0)
+    {
+        return Curve::BOUNCE_IN;
+    }
+    else if (strcmp(curveId, "BOUNCE_OUT") == 0)
+    {
+        return Curve::BOUNCE_OUT;
+    }
+    else if (strcmp(curveId, "BOUNCE_IN_OUT") == 0)
+    {
+        return Curve::BOUNCE_IN_OUT;
+    }
+    else if (strcmp(curveId, "BOUNCE_OUT_IN") == 0)
+    {
+        return Curve::BOUNCE_OUT_IN;
+    }
+
+    return -1;
+}
+
+}

+ 484 - 0
gameplay-encoder/src/Curve.h

@@ -0,0 +1,484 @@
+#ifndef CURVE_H_
+#define CURVE_H_
+
+namespace gameplay
+{
+
+/**
+ * Represents an n-dimensional curve.
+ */
+class Curve
+{
+    friend class Animation;
+    friend class AnimationClip;
+    friend class AnimationController;
+    friend class MeshSkin;
+
+public:
+
+    /**
+     * Types of interpolation.
+     *
+     * Defines how the points in the curve are connected.
+     *
+     * Note: InterpolationType::BEZIER requires control points and InterpolationType::HERMITE requires tangents.
+     */
+    enum InterpolationType
+    {
+        /**
+         * Bezier Interpolation. 
+         *
+         * Requires that two control points are set for each segment.
+         */
+        BEZIER,
+
+        /**
+         * B-Spline Interpolation. 
+         *
+         * Uses the points as control points, and the curve is guaranteed to only pass through the
+         * first and last point.
+         */
+        BSPLINE,
+
+        /**
+         * Flat Interpolation. 
+         * 
+         * A form of Hermite interpolation that generates flat tangents for you. The tangents have a value equal to 0.
+         */
+        FLAT,
+
+        /**
+         * Hermite Interpolation. 
+         *
+         * Requires that two tangents for each segment.
+         */
+        HERMITE,
+
+        /**
+         * Linear Interpolation.
+         */
+        LINEAR,
+
+        /** 
+         * Smooth Interpolation. 
+         *
+         * A form of Hermite interpolation that generates tangents for each segment based on the points prior to and after the segment.
+         */
+        SMOOTH,
+
+        /**
+         * Discrete Interpolation.
+         */ 
+        STEP,
+
+        /**
+         * Quadratic-In Interpolation.
+         */
+        QUADRATIC_IN, 
+        
+        /**
+         * Quadratic-Out Interpolation.
+         */
+        QUADRATIC_OUT,
+
+        /**
+         * Quadratic-In-Out Interpolation.
+         */
+        QUADRATIC_IN_OUT,
+
+        /**
+         * Quadratic-Out-In Interpolation.
+         */
+        QUADRATIC_OUT_IN,
+
+        /**
+         * Cubic-In Interpolation.
+         */
+        CUBIC_IN,
+        
+        /**
+         * Cubic-Out Interpolation.
+         */
+        CUBIC_OUT,
+        
+        /**
+         * Cubic-In-Out Interpolation.
+         */
+        CUBIC_IN_OUT,
+        
+        /**
+         * Cubic-Out-In Interpolation.
+         */
+        CUBIC_OUT_IN,
+
+        /**
+         * Quartic-In Interpolation.
+         */
+        QUARTIC_IN,
+
+        /**
+         * Quartic-Out Interpolation.
+         */
+        QUARTIC_OUT,
+
+        /**
+         * Quartic-In-Out Interpolation.
+         */
+        QUARTIC_IN_OUT,
+
+        /**
+         * Quartic-Out-In Interpolation.
+         */
+        QUARTIC_OUT_IN,
+
+        /**
+         * Quintic-In Interpolation.
+         */
+        QUINTIC_IN,
+        
+        /**
+         * Quintic-Out Interpolation.
+         */
+        QUINTIC_OUT,
+        
+        /**
+         * Quintic-In-Out Interpolation.
+         */
+        QUINTIC_IN_OUT,
+        
+        /**
+         * Quintic-Out-In Interpolation.
+         */
+        QUINTIC_OUT_IN,
+        
+        /**
+         * Sine-In Interpolation.
+         */
+        SINE_IN,
+        
+        /**
+         * Sine-Out Interpolation.
+         */
+        SINE_OUT,
+        
+        /**
+         * Sine-In-Out Interpolation.
+         */
+        SINE_IN_OUT,
+        
+        /**
+         * Sine-Out-In Interpolation.
+         */
+        SINE_OUT_IN,
+
+        /**
+         * Exponential-In Interpolation.
+         */
+        EXPONENTIAL_IN,
+
+        /**
+         * Exponential-Out Interpolation.
+         */
+        EXPONENTIAL_OUT,
+
+        /**
+         * Exponential-In-Out Interpolation.
+         */
+        EXPONENTIAL_IN_OUT,
+
+        /**
+         * Exponential-Out-In Interpolation.
+         */
+        EXPONENTIAL_OUT_IN,
+
+        /**
+         * Circular-In Interpolation.
+         */
+        CIRCULAR_IN,
+
+        /**
+         * Circular-Out Interpolation.
+         */
+        CIRCULAR_OUT,
+
+        /**
+         * Circular-In-Out Interpolation.
+         */
+        CIRCULAR_IN_OUT,
+
+        /**
+         * Circular-Out-In Interpolation.
+         */
+        CIRCULAR_OUT_IN,
+
+        /**
+         * Elastic-In Interpolation.
+         */
+        ELASTIC_IN,
+
+        /**
+         * Elastic-Out Interpolation.
+         */
+        ELASTIC_OUT,
+
+        /**
+         * Elastic-In-Out Interpolation.
+         */
+        ELASTIC_IN_OUT,
+
+        /**
+         * Elastic-Out-In Interpolation.
+         */
+        ELASTIC_OUT_IN,
+
+        /**
+         * Overshoot-In Interpolation.
+         */
+        OVERSHOOT_IN,
+
+        /**
+         * Overshoot-Out Interpolation.
+         */
+        OVERSHOOT_OUT,
+
+        /**
+         * Overshoot-In-Out Interpolation.
+         */
+        OVERSHOOT_IN_OUT,
+
+        /**
+         * Overshoot-Out-In Interpolation.
+         */
+        OVERSHOOT_OUT_IN,
+
+        /**
+         * Bounce-In Interpolation.
+         */
+        BOUNCE_IN,
+
+        /**
+         * Bounce-Out Interpolation.
+         */
+        BOUNCE_OUT,
+
+        /**
+         * Bounce-In-Out Interpolation.
+         */
+        BOUNCE_IN_OUT,
+
+        /**
+         * Bounce-Out-In Interpolation.
+         */
+        BOUNCE_OUT_IN
+    };
+
+
+    /**
+     * Constructs a new curve and the specified parameters.
+     *
+     * @param pointCount The number of points in the curve.
+     * @param componentCount The number of float component values per key value.
+     */
+    Curve(unsigned int pointCount, unsigned int componentCount);
+
+    /**
+     * Destructor.
+     */
+    ~Curve();
+
+    /**
+     * Gets the number of points in the curve.
+     *
+     * @return The number of points in the curve.
+     */
+    unsigned int getPointCount() const;
+
+    /**
+     * Gets the number of float component values per points.
+     *
+     * @return The number of float component values per point.
+     */
+    unsigned int getComponentCount() const;
+
+    /**
+     * Returns the start time for the curve.
+     *
+     * @return The curve's start time.
+     */
+    float getStartTime() const;
+
+    /**
+     * Returns the end time for the curve.
+     *
+     * @return The curve's end time.
+     */
+    float getEndTime() const;
+
+    /**
+     * Sets the given point values on the curve the curve.
+     *
+     * @param index The index of the point.
+     * @param time The time for the key.
+     * @param value The point to add.
+     * @param type The curve interpolation type.
+     */
+    void setPoint(unsigned int index, float time, float* value, InterpolationType type);
+
+    /**
+     * Sets the given point on the curve for the specified index and the specified parameters.
+     *
+     * @param index The index of the point.
+     * @param time The time of the point within the curve.
+     * @param value The value of the point to copy the data from.
+     * @param type The curve interpolation type.
+     * @param inValue The tangent approaching the point.
+     * @param outValue The tangent leaving the point.
+     */
+    void setPoint(unsigned int index, float time, float* value, InterpolationType type, float* inValue, float* outValue);
+
+    /**
+     * Sets the tangents for a point on the curve specified by the index.
+     *
+     * @param index The index of the point.
+     * @param type The curve interpolation type.
+     * @param inValue The tangent approaching the point.
+     * @param outValue The tangent leaving the point.
+     */
+    void setTangent(unsigned int index, InterpolationType type, float* inValue, float* outValue);
+    
+    /**
+     * Evaluates the curve at the given position value (between 0.0 and 1.0 inclusive).
+     *
+     * @param time The position to evaluate the curve at.
+     * @param dst The evaluated value of the curve at the given time.
+     */
+    void evaluate(float time, float* dst) const;
+
+    /**
+     * Linear interpolation function.
+     */
+    static float lerp(float t, float from, float to);
+
+private:
+
+    /**
+     * Defines a single point within a curve.
+     */
+    class Point
+    {
+    public:
+
+        /** The time of the point within the curve. */
+        float time;
+        /** The value of the point. */
+        float* value;
+        /** The value of the tangent when approaching this point (from the previous point in the curve). */
+        float* inValue;
+        /** The value of the tangent when leaving this point (towards the next point in the curve). */
+        float* outValue;
+        /** The type of interpolation to use between this point and the next point. */
+        InterpolationType type;
+
+        /**
+         * Constructor.
+         */
+        Point();
+
+        /**
+         * Destructor.
+         */
+        ~Point();
+    };
+
+    /**
+     * Constructor.
+     */
+    Curve();
+
+    /**
+     * Constructor.
+     */
+    Curve(const Curve& copy);
+
+    /**
+     * Bezier interpolation function.
+     */
+    void interpolateBezier(float s, Point* from, Point* to, float* dst) const;
+
+    /**
+     * Bspline interpolation function.
+     */
+    void interpolateBSpline(float s, Point* c0, Point* c1, Point* c2, Point* c3, float* dst) const;
+
+    /**
+     * Hermite interpolation function.
+     */
+    void interpolateHermite(float s, Point* from, Point* to, float* dst) const;
+
+    /**
+     * Hermite interpolation function.
+     */
+    void interpolateHermiteFlat(float s, Point* from, Point* to, float* dst) const;
+
+    /**
+     * Hermite interpolation function.
+     */
+    void interpolateHermiteSmooth(float s, unsigned int index, Point* from, Point* to, float* dst) const;
+
+    /** 
+     * Linear interpolation function.
+     */ 
+    void interpolateLinear(float s, Point* from, Point* to, float* dst) const;
+
+    /**
+     * Quaternion interpolation function.
+     */
+    void interpolateQuaternion(float s, float* from, float* to, float* dst) const;
+    
+    /**
+     * Determines the current keyframe to interpolate from based on the specified time.
+     */ 
+    int determineIndex(float time) const;
+
+    /**
+     * Sets the offset for the beginning of a Quaternion piece of data within the curve's value span at the specified
+     * index. The next four components of data starting at the given index will be interpolated as a Quaternion.
+     * This function will assert an error if the given index is greater than the component size subtracted by the four components required
+     * to store a quaternion.
+     * 
+     * @param index The index of the Quaternion rotation data.
+     */
+    void setQuaternionOffset(unsigned int index);
+
+    /**
+     * Gets the InterpolationType value for the given string ID
+     *
+     * @param interpolationId The string representation of the InterpolationType
+     * @return the InterpolationType value; -1 if the string does not represent an InterpolationType.
+     */
+    static int getInterpolationType(const char* interpolationId);
+
+    unsigned int _pointCount;           // Number of points on the curve.
+    unsigned int _componentCount;       // Number of components on the curve.
+    unsigned int _componentSize;        // The component size (in bytes).
+    unsigned int* _quaternionOffset;    // Offset for the rotation component.
+    Point* _points;                     // The points on the curve.
+};
+
+inline static float bezier(float eq0, float eq1, float eq2, float eq3, float from, float out, float to, float in);
+
+inline static float bspline(float eq0, float eq1, float eq2, float eq3, float c0, float c1, float c2, float c3);
+
+inline static float hermite(float h00, float h01, float h10, float h11, float from, float out, float to, float in);
+
+inline static float hermiteFlat(float h00, float h01, float from, float to);
+
+inline static float hermiteSmooth(float h00, float h01, float h10, float h11, float from, float out, float to, float in);
+
+inline static float lerpInl(float s, float from, float to);
+
+}
+
+#include "Curve.inl"
+
+#endif

+ 36 - 0
gameplay-encoder/src/Curve.inl

@@ -0,0 +1,36 @@
+
+
+namespace gameplay
+{
+
+inline float bezier(float eq0, float eq1, float eq2, float eq3, float from, float out, float to, float in)
+{
+    return from * eq0 + out * eq1 + in * eq2 + to * eq3;
+}
+
+inline float bspline(float eq0, float eq1, float eq2, float eq3, float c0, float c1, float c2, float c3)
+{
+    return c0 * eq0 + c1 * eq1 + c2 * eq2 + c3 * eq3;
+}
+
+inline float hermite(float h00, float h01, float h10, float h11, float from, float out, float to, float in)
+{
+    return h00 * from + h01 * to + h10 * out + h11 * in;
+}
+
+inline float hermiteFlat(float h00, float h01, float from, float to)
+{
+    return h00 * from + h01 * to;
+}
+
+inline float hermiteSmooth(float h00, float h01, float h10, float h11, float from, float out, float to, float in)
+{
+    return h00 * from + h01 * to + h10 * out + h11 * in;
+}
+
+inline float lerpInl(float s, float from, float to)
+{
+    return from + (to - from) * s;
+}
+
+}

+ 1 - 0
gameplay-encoder/src/DAEChannelTarget.h

@@ -55,6 +55,7 @@ public:
     void getPropertyName(size_t index, std::string* str);
     void getPropertyName(size_t index, std::string* str);
 
 
 private:
 private:
+    
     /**
     /**
      * The channel element.
      * The channel element.
      */
      */

+ 3 - 1
gameplay-encoder/src/DAESceneEncoder.h

@@ -185,11 +185,13 @@ private:
      * Returns the VertexUsage value for the given semantic string.
      * Returns the VertexUsage value for the given semantic string.
      * 
      * 
      * @param semantic The semantic attribute string from the COLLADA <input> element.
      * @param semantic The semantic attribute string from the COLLADA <input> element.
-     * @param The VertexUsage or -1 if the string was not recognized.
+     * 
+     * @return The VertexUsage or -1 if the string was not recognized.
      */
      */
     static int getVertexUsageType(const std::string& semantic);
     static int getVertexUsageType(const std::string& semantic);
     
     
 private:
 private:
+    
     DAE* _collada;        // Collada datastore in memory to read from.
     DAE* _collada;        // Collada datastore in memory to read from.
     domCOLLADA* _dom;
     domCOLLADA* _dom;
     FILE* file;        // Output file to write to.
     FILE* file;        // Output file to write to.

+ 1 - 0
gameplay-encoder/src/Effect.h

@@ -29,6 +29,7 @@ public:
     virtual void writeText(FILE* file);
     virtual void writeText(FILE* file);
 
 
 private:
 private:
+    
     std::string _vertexShader;
     std::string _vertexShader;
     std::string _fragmentShader;
     std::string _fragmentShader;
 };
 };

+ 55 - 10
gameplay-encoder/src/FBXSceneEncoder.cpp

@@ -249,13 +249,13 @@ void FBXSceneEncoder::loadScene(KFbxScene* fbxScene)
     // Find the ambient light of the scene
     // Find the ambient light of the scene
     KFbxColor ambientColor = fbxScene->GetGlobalSettings().GetAmbientColor();
     KFbxColor ambientColor = fbxScene->GetGlobalSettings().GetAmbientColor();
     scene->setAmbientColor((float)ambientColor.mRed, (float)ambientColor.mGreen, (float)ambientColor.mBlue);
     scene->setAmbientColor((float)ambientColor.mRed, (float)ambientColor.mGreen, (float)ambientColor.mBlue);
-
-	// Assign the first camera node (if there is one) in the scene as the active camera
-	// This ensures that if there's a camera in the scene that it is assigned as the 
-	// active camera.
-	// TODO: add logic to find the "active" camera node in the fbxScene
-	scene->setActiveCameraNode(scene->getFirstCameraNode());
-
+    
+    // Assign the first camera node (if there is one) in the scene as the active camera
+    // This ensures that if there's a camera in the scene that it is assigned as the 
+    // active camera.
+    // TODO: add logic to find the "active" camera node in the fbxScene
+    scene->setActiveCameraNode(scene->getFirstCameraNode());
+    
     _gamePlayFile.addScene(scene);
     _gamePlayFile.addScene(scene);
 }
 }
 
 
@@ -652,20 +652,65 @@ void FBXSceneEncoder::loadLight(KFbxNode* fbxNode, Node* node)
     switch (fbxLight->LightType.Get())
     switch (fbxLight->LightType.Get())
     {
     {
     case KFbxLight::ePOINT:
     case KFbxLight::ePOINT:
-        light->setPointLight();
-        // TODO: range
+    {
+        KFbxLight::EDecayType decayType = fbxLight->DecayType.Get();
+        switch (decayType)
+        {
+        case KFbxLight::eNONE:
+            // No decay. Can assume we have an ambient light, because ambient lights in the scene are 
+            // converted to point lights with no decay when exporting to FBX.
+            light->setAmbientLight();
+            break;
+        case KFbxLight::eLINEAR:
+            light->setPointLight();
+            light->setLinearAttenuation((float)fbxLight->DecayStart.Get());
+            break;
+        case KFbxLight::eQUADRATIC:
+            light->setPointLight();
+            light->setQuadraticAttenuation((float)fbxLight->DecayStart.Get());
+            break;
+        case KFbxLight::eCUBIC:
+        default:
+            // Not supported..
+            break;
+        }
         break;
         break;
+    }
     case KFbxLight::eDIRECTIONAL:
     case KFbxLight::eDIRECTIONAL:
+    {
         light->setDirectionalLight();
         light->setDirectionalLight();
         break;
         break;
+    }
     case KFbxLight::eSPOT:
     case KFbxLight::eSPOT:
+    {
         light->setSpotLight();
         light->setSpotLight();
-        // TODO: range and angles
+
+        KFbxLight::EDecayType decayType = fbxLight->DecayType.Get();
+        switch (decayType)
+        {
+        case KFbxLight::eNONE:
+            // No decay.
+            break;
+        case KFbxLight::eLINEAR:
+            light->setLinearAttenuation((float)fbxLight->DecayStart.Get());
+            break;  
+        case KFbxLight::eQUADRATIC:
+            light->setQuadraticAttenuation((float)fbxLight->DecayStart.Get());
+            break;
+        case KFbxLight::eCUBIC:
+            // Not supported..
+            break;
+        }
+
+        light->setFalloffAngle(MATH_DEG_TO_RAD((float)fbxLight->ConeAngle.Get())); // fall off angle
         break;
         break;
+    }
     default:
     default:
+    {
         warning("Unknown light type in node.");
         warning("Unknown light type in node.");
         return;
         return;
     }
     }
+    }
 
 
     _gamePlayFile.addLight(light);
     _gamePlayFile.addLight(light);
     node->setLight(light);
     node->setLight(light);

+ 3 - 0
gameplay-encoder/src/FileIO.h

@@ -1,6 +1,9 @@
 #ifndef FILEIO_H_
 #ifndef FILEIO_H_
 #define FILEIO_H_
 #define FILEIO_H_
 
 
+#include <cstdio>
+#include <list>
+#include <vector>
 
 
 #include "Vector2.h"
 #include "Vector2.h"
 #include "Vector3.h"
 #include "Vector3.h"

+ 15 - 13
gameplay-encoder/src/MeshSkin.cpp

@@ -6,7 +6,7 @@
 #include "GPBFile.h"
 #include "GPBFile.h"
 #include "Animations.h"
 #include "Animations.h"
 #include "Transform.h"
 #include "Transform.h"
-#include "../../gameplay/src/Curve.h"
+#include "Curve.h"
 #include "Matrix.h"
 #include "Matrix.h"
 
 
 namespace gameplay
 namespace gameplay
@@ -313,26 +313,28 @@ void MeshSkin::computeBounds()
         if (duration > maxDuration)
         if (duration > maxDuration)
             maxDuration = duration;
             maxDuration = duration;
 
 
-        // Set curve points
-        float* keyValuesPtr = keyValues;
-        for (unsigned int j = 0; j < keyCount; ++j)
+        if (duration > 0.0f)
         {
         {
-            // Store time normalized, between 0-1
-            float t = (keyTimes[j] - startTime) / duration;
+            // Set curve points
+            float* keyValuesPtr = keyValues;
+            for (unsigned int j = 0; j < keyCount; ++j)
+            {
+                // Store time normalized, between 0-1
+                float t = (keyTimes[j] - startTime) / duration;
 
 
-            // Set the curve point
-            // TODO: Handle other interpolation types
-            curve->setPoint(j, t, keyValuesPtr, gameplay::Curve::LINEAR);
+                // Set the curve point
+                // TODO: Handle other interpolation types
+                curve->setPoint(j, t, keyValuesPtr, gameplay::Curve::LINEAR);
 
 
-            // Move to the next point on the curve
-            keyValuesPtr += curve->getComponentCount();
+                // Move to the next point on the curve
+                keyValuesPtr += curve->getComponentCount();
+            }
+            curves.push_back(curve);
         }
         }
 
 
         delete[] keyValues;
         delete[] keyValues;
         keyValues = NULL;
         keyValues = NULL;
 
 
-        curves.push_back(curve);
-
         DEBUGPRINT_VARG("> %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
         DEBUGPRINT_VARG("> %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
     }
     }
     DEBUGPRINT("\n");
     DEBUGPRINT("\n");

+ 2 - 2
gameplay-encoder/src/Reference.h

@@ -1,5 +1,5 @@
-#ifndef REF_H_
-#define REF_H_
+#ifndef REFERENCE_H_
+#define REFERENCE_H_
 
 
 #include "Object.h"
 #include "Object.h"
 
 

+ 3 - 3
gameplay-newproject.bat

@@ -177,9 +177,9 @@ call:replace %projPath%\%projName%.xcodeproj\project.pbxproj GAMEPLAY_PATH "%gpP
 call:replace %projPath%\%projName%.xcodeproj\project.pbxproj TemplateGame "%className%"
 call:replace %projPath%\%projName%.xcodeproj\project.pbxproj TemplateGame "%className%"
 call:replace %projPath%\%projName%.xcodeproj\project.pbxproj TEMPLATE_PROJECT "%projName%"
 call:replace %projPath%\%projName%.xcodeproj\project.pbxproj TEMPLATE_PROJECT "%projName%"
 
 
-copy gameplay-template\gameplay-template-macos.plist %projPath%\%projName%-macos.plist
-call:replace %projPath%\%projName%-macos.plist TEMPLATE_UUID "%uuid%"
-call:replace %projPath%\%projName%-macos.plist TEMPLATE_AUTHOR "%author%"
+copy gameplay-template\gameplay-template-macosx.plist %projPath%\%projName%-macosx.plist
+call:replace %projPath%\%projName%-macosx.plist TEMPLATE_UUID "%uuid%"
+call:replace %projPath%\%projName%-macosx.plist TEMPLATE_AUTHOR "%author%"
 
 
 REM Copy BlackBerry NDK project files
 REM Copy BlackBerry NDK project files
 copy gameplay-template\template.cproject %projPath%\.cproject
 copy gameplay-template\template.cproject %projPath%\.cproject

+ 3 - 3
gameplay-newproject.sh

@@ -179,9 +179,9 @@ sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/$projName.xcodeproj/projec
 sed -i "" "s*TemplateGame*$className*g" "$projPath/$projName.xcodeproj/project.pbxproj"
 sed -i "" "s*TemplateGame*$className*g" "$projPath/$projName.xcodeproj/project.pbxproj"
 sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.xcodeproj/project.pbxproj"
 sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.xcodeproj/project.pbxproj"
 
 
-cp "gameplay-template/TEMPLATE_PROJECT-macos.plist" "$projPath/$projName-macos.plist"
-sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/$projName-macos.plist"
-sed -i "" "s*TEMPLATE_AUTHOR*$author*g" "$projPath/$projName-macos.plist"
+cp "gameplay-template/TEMPLATE_PROJECT-macosx.plist" "$projPath/$projName-macosx.plist"
+sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/$projName-macosx.plist"
+sed -i "" "s*TEMPLATE_AUTHOR*$author*g" "$projPath/$projName-macosx.plist"
 
 
 cp "gameplay-template/TEMPLATE_PROJECT-ios.plist" "$projPath/$projName-ios.plist"
 cp "gameplay-template/TEMPLATE_PROJECT-ios.plist" "$projPath/$projName-ios.plist"
 sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/$projName-ios.plist"
 sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/$projName-ios.plist"

+ 0 - 0
gameplay-template/TEMPLATE_PROJECT-macos.plist → gameplay-template/TEMPLATE_PROJECT-macosx.plist


+ 74 - 77
gameplay-template/gameplay-template.xcodeproj/project.pbxproj

@@ -33,48 +33,17 @@
 		5B61611F14CCC24C0073B857 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9332D1491A7810098216A /* libz.dylib */; };
 		5B61611F14CCC24C0073B857 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C9332D1491A7810098216A /* libz.dylib */; };
 		5B61612614CCC24C0073B857 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 42C932ED1491A4CB0098216A /* icon.png */; };
 		5B61612614CCC24C0073B857 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 42C932ED1491A4CB0098216A /* icon.png */; };
 		5B61612714CCC24C0073B857 /* res in Resources */ = {isa = PBXBuildFile; fileRef = 42C932F21491A53E0098216A /* res */; };
 		5B61612714CCC24C0073B857 /* res in Resources */ = {isa = PBXBuildFile; fileRef = 42C932F21491A53E0098216A /* res */; };
-		5B8D58AB1512584A00DA5991 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B8D58A51512584A00DA5991 /* CoreMotion.framework */; };
-		5B8D58AC1512584A00DA5991 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B8D58A61512584A00DA5991 /* Foundation.framework */; };
-		5B8D58AD1512584A00DA5991 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B8D58A71512584A00DA5991 /* OpenAL.framework */; };
-		5B8D58AE1512584A00DA5991 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B8D58A81512584A00DA5991 /* OpenGLES.framework */; };
-		5B8D58AF1512584A00DA5991 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B8D58A91512584A00DA5991 /* QuartzCore.framework */; };
-		5B8D58B01512584A00DA5991 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B8D58AA1512584A00DA5991 /* UIKit.framework */; };
-		5BC4E84E150F913F00CBE1C0 /* shaders in Copy GamePlay Bundle Resources */ = {isa = PBXBuildFile; fileRef = 5BC4E849150F911D00CBE1C0 /* shaders */; };
-		5BC4E84F150F913F00CBE1C0 /* textures in Copy GamePlay Bundle Resources */ = {isa = PBXBuildFile; fileRef = 5BC4E84A150F911D00CBE1C0 /* textures */; };
-		5BC4E851150F915300CBE1C0 /* shaders in Copy GamePlay Bundle Resources */ = {isa = PBXBuildFile; fileRef = 5BC4E849150F911D00CBE1C0 /* shaders */; };
-		5BC4E852150F915300CBE1C0 /* textures in Copy GamePlay Bundle Resources */ = {isa = PBXBuildFile; fileRef = 5BC4E84A150F911D00CBE1C0 /* textures */; };
+		5BAF206D152F2DDD003E2AC3 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2067152F2DDD003E2AC3 /* CoreMotion.framework */; };
+		5BAF206E152F2DDD003E2AC3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2068152F2DDD003E2AC3 /* Foundation.framework */; };
+		5BAF206F152F2DDD003E2AC3 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2069152F2DDD003E2AC3 /* OpenAL.framework */; };
+		5BAF2070152F2DDD003E2AC3 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF206A152F2DDD003E2AC3 /* OpenGLES.framework */; };
+		5BAF2071152F2DDD003E2AC3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF206B152F2DDD003E2AC3 /* QuartzCore.framework */; };
+		5BAF2072152F2DDD003E2AC3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF206C152F2DDD003E2AC3 /* UIKit.framework */; };
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
-/* Begin PBXCopyFilesBuildPhase section */
-		5BC4E84D150F912B00CBE1C0 /* Copy GamePlay Bundle Resources */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 2147483647;
-			dstPath = res;
-			dstSubfolderSpec = 7;
-			files = (
-				5BC4E84E150F913F00CBE1C0 /* shaders in Copy GamePlay Bundle Resources */,
-				5BC4E84F150F913F00CBE1C0 /* textures in Copy GamePlay Bundle Resources */,
-			);
-			name = "Copy GamePlay Bundle Resources";
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		5BC4E850150F914500CBE1C0 /* Copy GamePlay Bundle Resources */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 2147483647;
-			dstPath = res;
-			dstSubfolderSpec = 7;
-			files = (
-				5BC4E851150F915300CBE1C0 /* shaders in Copy GamePlay Bundle Resources */,
-				5BC4E852150F915300CBE1C0 /* textures in Copy GamePlay Bundle Resources */,
-			);
-			name = "Copy GamePlay Bundle Resources";
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXCopyFilesBuildPhase section */
-
 /* Begin PBXFileReference section */
 /* Begin PBXFileReference section */
 		42438B521491AD2000D218B8 /* libgameplay.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgameplay.a; path = "~/Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug/libgameplay.a"; sourceTree = "<group>"; };
 		42438B521491AD2000D218B8 /* libgameplay.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgameplay.a; path = "~/Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug/libgameplay.a"; sourceTree = "<group>"; };
-		42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT-MacOSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TEMPLATE_PROJECT-MacOSX.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT-macosx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TEMPLATE_PROJECT-macosx.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		42C932C01491A0DB0098216A /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
 		42C932C01491A0DB0098216A /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
 		42C932ED1491A4CB0098216A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; };
 		42C932ED1491A4CB0098216A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; };
 		42C932EF1491A5160098216A /* TemplateGame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TemplateGame.cpp; path = src/TemplateGame.cpp; sourceTree = SOURCE_ROOT; };
 		42C932EF1491A5160098216A /* TemplateGame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TemplateGame.cpp; path = src/TemplateGame.cpp; sourceTree = SOURCE_ROOT; };
@@ -83,22 +52,22 @@
 		42C933161491A5EB0098216A /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
 		42C933161491A5EB0098216A /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
 		42C9331C1491A6750098216A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		42C9331C1491A6750098216A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		42C9331E1491A67F0098216A /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
 		42C9331E1491A67F0098216A /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
-		42C933201491A6C70098216A /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "GAMEPLAY_PATH/external-deps/bullet/lib/macos/libbullet.a"; sourceTree = "<group>"; };
-		42C933221491A6E50098216A /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos/libogg.a"; sourceTree = "<group>"; };
-		42C933231491A6E50098216A /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos/libvorbis.a"; sourceTree = "<group>"; };
-		42C933241491A6E50098216A /* libvorbisenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisenc.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos/libvorbisenc.a"; sourceTree = "<group>"; };
-		42C933251491A6E50098216A /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos/libvorbisfile.a"; sourceTree = "<group>"; };
-		42C9332A1491A7390098216A /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "GAMEPLAY_PATH/external-deps/libpng/lib/macos/libpng.a"; sourceTree = "<group>"; };
+		42C933201491A6C70098216A /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "GAMEPLAY_PATH/external-deps/bullet/lib/macosx/libbullet.a"; sourceTree = "<group>"; };
+		42C933221491A6E50098216A /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macosx/libogg.a"; sourceTree = "<group>"; };
+		42C933231491A6E50098216A /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macosx/libvorbis.a"; sourceTree = "<group>"; };
+		42C933241491A6E50098216A /* libvorbisenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisenc.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macosx/libvorbisenc.a"; sourceTree = "<group>"; };
+		42C933251491A6E50098216A /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "GAMEPLAY_PATH/external-deps/oggvorbis/lib/macosx/libvorbisfile.a"; sourceTree = "<group>"; };
+		42C9332A1491A7390098216A /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "GAMEPLAY_PATH/external-deps/libpng/lib/macosx/libpng.a"; sourceTree = "<group>"; };
 		42C9332D1491A7810098216A /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
 		42C9332D1491A7810098216A /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
-		5B61611214CCC2200073B857 /* TEMPLATE_PROJECT-macos.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TEMPLATE_PROJECT-macos.plist"; sourceTree = "<group>"; };
+		5B61611214CCC2200073B857 /* TEMPLATE_PROJECT-macosx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "TEMPLATE_PROJECT-macosx.plist"; sourceTree = "<group>"; };
 		5B61612C14CCC24C0073B857 /* TEMPLATE_PROJECT-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TEMPLATE_PROJECT-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		5B61612C14CCC24C0073B857 /* TEMPLATE_PROJECT-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TEMPLATE_PROJECT-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		5B61612E14CCC24D0073B857 /* TEMPLATE_PROJECT-ios.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TEMPLATE_PROJECT-ios.plist"; sourceTree = "<group>"; };
 		5B61612E14CCC24D0073B857 /* TEMPLATE_PROJECT-ios.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TEMPLATE_PROJECT-ios.plist"; sourceTree = "<group>"; };
-		5B8D58A51512584A00DA5991 /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/CoreMotion.framework; sourceTree = DEVELOPER_DIR; };
-		5B8D58A61512584A00DA5991 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
-		5B8D58A71512584A00DA5991 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = DEVELOPER_DIR; };
-		5B8D58A81512584A00DA5991 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
-		5B8D58A91512584A00DA5991 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
-		5B8D58AA1512584A00DA5991 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2067152F2DDD003E2AC3 /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/CoreMotion.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2068152F2DDD003E2AC3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2069152F2DDD003E2AC3 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF206A152F2DDD003E2AC3 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF206B152F2DDD003E2AC3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF206C152F2DDD003E2AC3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
 		5BC4E77F150F879E00CBE1C0 /* gameplay.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = gameplay.xcodeproj; path = GAMEPLAY_PATH/gameplay/gameplay.xcodeproj; sourceTree = SOURCE_ROOT; };
 		5BC4E77F150F879E00CBE1C0 /* gameplay.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = gameplay.xcodeproj; path = GAMEPLAY_PATH/gameplay/gameplay.xcodeproj; sourceTree = SOURCE_ROOT; };
 		5BC4E849150F911D00CBE1C0 /* shaders */ = {isa = PBXFileReference; lastKnownFileType = text; name = shaders; path = GAMEPLAY_PATH/gameplay/res/shaders; sourceTree = SOURCE_ROOT; };
 		5BC4E849150F911D00CBE1C0 /* shaders */ = {isa = PBXFileReference; lastKnownFileType = text; name = shaders; path = GAMEPLAY_PATH/gameplay/res/shaders; sourceTree = SOURCE_ROOT; };
 		5BC4E84A150F911D00CBE1C0 /* textures */ = {isa = PBXFileReference; lastKnownFileType = text; name = textures; path = GAMEPLAY_PATH/gameplay/res/textures; sourceTree = SOURCE_ROOT; };
 		5BC4E84A150F911D00CBE1C0 /* textures */ = {isa = PBXFileReference; lastKnownFileType = text; name = textures; path = GAMEPLAY_PATH/gameplay/res/textures; sourceTree = SOURCE_ROOT; };
@@ -128,12 +97,12 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				5B8D58AB1512584A00DA5991 /* CoreMotion.framework in Frameworks */,
-				5B8D58AC1512584A00DA5991 /* Foundation.framework in Frameworks */,
-				5B8D58AD1512584A00DA5991 /* OpenAL.framework in Frameworks */,
-				5B8D58AE1512584A00DA5991 /* OpenGLES.framework in Frameworks */,
-				5B8D58AF1512584A00DA5991 /* QuartzCore.framework in Frameworks */,
-				5B8D58B01512584A00DA5991 /* UIKit.framework in Frameworks */,
+				5BAF206D152F2DDD003E2AC3 /* CoreMotion.framework in Frameworks */,
+				5BAF206E152F2DDD003E2AC3 /* Foundation.framework in Frameworks */,
+				5BAF206F152F2DDD003E2AC3 /* OpenAL.framework in Frameworks */,
+				5BAF2070152F2DDD003E2AC3 /* OpenGLES.framework in Frameworks */,
+				5BAF2071152F2DDD003E2AC3 /* QuartzCore.framework in Frameworks */,
+				5BAF2072152F2DDD003E2AC3 /* UIKit.framework in Frameworks */,
 				5B61611814CCC24C0073B857 /* libgameplay.a in Frameworks */,
 				5B61611814CCC24C0073B857 /* libgameplay.a in Frameworks */,
 				5B61611914CCC24C0073B857 /* libbullet.a in Frameworks */,
 				5B61611914CCC24C0073B857 /* libbullet.a in Frameworks */,
 				5B61611A14CCC24C0073B857 /* libogg.a in Frameworks */,
 				5B61611A14CCC24C0073B857 /* libogg.a in Frameworks */,
@@ -151,7 +120,7 @@
 		42C932B11491A0DB0098216A = {
 		42C932B11491A0DB0098216A = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				5B61611214CCC2200073B857 /* TEMPLATE_PROJECT-macos.plist */,
+				5B61611214CCC2200073B857 /* TEMPLATE_PROJECT-macosx.plist */,
 				5B61612E14CCC24D0073B857 /* TEMPLATE_PROJECT-ios.plist */,
 				5B61612E14CCC24D0073B857 /* TEMPLATE_PROJECT-ios.plist */,
 				42C932ED1491A4CB0098216A /* icon.png */,
 				42C932ED1491A4CB0098216A /* icon.png */,
 				42C932F21491A53E0098216A /* res */,
 				42C932F21491A53E0098216A /* res */,
@@ -208,12 +177,12 @@
 		5B61613914CCC3560073B857 /* iOS */ = {
 		5B61613914CCC3560073B857 /* iOS */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				5B8D58A51512584A00DA5991 /* CoreMotion.framework */,
-				5B8D58A61512584A00DA5991 /* Foundation.framework */,
-				5B8D58A71512584A00DA5991 /* OpenAL.framework */,
-				5B8D58A81512584A00DA5991 /* OpenGLES.framework */,
-				5B8D58A91512584A00DA5991 /* QuartzCore.framework */,
-				5B8D58AA1512584A00DA5991 /* UIKit.framework */,
+				5BAF2067152F2DDD003E2AC3 /* CoreMotion.framework */,
+				5BAF2068152F2DDD003E2AC3 /* Foundation.framework */,
+				5BAF2069152F2DDD003E2AC3 /* OpenAL.framework */,
+				5BAF206A152F2DDD003E2AC3 /* OpenGLES.framework */,
+				5BAF206B152F2DDD003E2AC3 /* QuartzCore.framework */,
+				5BAF206C152F2DDD003E2AC3 /* UIKit.framework */,
 			);
 			);
 			name = iOS;
 			name = iOS;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -226,7 +195,7 @@
 				42C933161491A5EB0098216A /* OpenGL.framework */,
 				42C933161491A5EB0098216A /* OpenGL.framework */,
 				42C9331E1491A67F0098216A /* OpenAL.framework */,
 				42C9331E1491A67F0098216A /* OpenAL.framework */,
 			);
 			);
-			name = "MacOSX";
+			name = MacOSX;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
 		5BC4E825150F8CE600CBE1C0 /* GamePlay */ = {
 		5BC4E825150F8CE600CBE1C0 /* GamePlay */ = {
@@ -250,7 +219,7 @@
 				42C932B91491A0DB0098216A /* Frameworks */,
 				42C932B91491A0DB0098216A /* Frameworks */,
 				42C933301491A7B50098216A /* ShellScript */,
 				42C933301491A7B50098216A /* ShellScript */,
 				42C932BA1491A0DB0098216A /* Resources */,
 				42C932BA1491A0DB0098216A /* Resources */,
-				5BC4E84D150F912B00CBE1C0 /* Copy GamePlay Bundle Resources */,
+				5BAF20D7152F30C3003E2AC3 /* Copy Gameplay Resources - Run Script */,
 			);
 			);
 			buildRules = (
 			buildRules = (
 			);
 			);
@@ -269,7 +238,7 @@
 				5B61611714CCC24C0073B857 /* Frameworks */,
 				5B61611714CCC24C0073B857 /* Frameworks */,
 				5B61612414CCC24C0073B857 /* ShellScript */,
 				5B61612414CCC24C0073B857 /* ShellScript */,
 				5B61612514CCC24C0073B857 /* Resources */,
 				5B61612514CCC24C0073B857 /* Resources */,
-				5BC4E850150F914500CBE1C0 /* Copy GamePlay Bundle Resources */,
+				5BAF20A3152F2FCE003E2AC3 /* Copy Gameplay Reousrces Run Script */,
 			);
 			);
 			buildRules = (
 			buildRules = (
 			);
 			);
@@ -354,6 +323,34 @@
 			shellPath = /bin/sh;
 			shellPath = /bin/sh;
 			shellScript = "touch -cm ${SRCROOT}/res";
 			shellScript = "touch -cm ${SRCROOT}/res";
 		};
 		};
+		5BAF20A3152F2FCE003E2AC3 /* Copy Gameplay Reousrces Run Script */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Copy Gameplay Reousrces Run Script";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "cp -rn GAMEPLAY_PATH/gameplay/res/shaders ${SRCROOT}/res\ncp -rn GAMEPLAY_PATH/gameplay/res/logo_powered_white.png ${SRCROOT}/res\ntouch -cm ${SRCROOT}/res";
+		};
+		5BAF20D7152F30C3003E2AC3 /* Copy Gameplay Resources - Run Script */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "Copy Gameplay Resources - Run Script";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "cp -rn GAMEPLAY_PATH/gameplay/res/shaders ${SRCROOT}/res\ncp -rn GAMEPLAY_PATH/gameplay/res/logo_powered_white.png ${SRCROOT}/res\ntouch -cm ${SRCROOT}/res";
+		};
 /* End PBXShellScriptBuildPhase section */
 /* End PBXShellScriptBuildPhase section */
 
 
 /* Begin PBXSourcesBuildPhase section */
 /* Begin PBXSourcesBuildPhase section */
@@ -397,7 +394,7 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GENERATE_PKGINFO_FILE = YES;
 				GENERATE_PKGINFO_FILE = YES;
-				INFOPLIST_FILE = "TEMPLATE_PROJECT-macos.plist";
+				INFOPLIST_FILE = "TEMPLATE_PROJECT-macosx.plist";
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -420,7 +417,7 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GENERATE_PKGINFO_FILE = YES;
 				GENERATE_PKGINFO_FILE = YES;
-				INFOPLIST_FILE = "TEMPLATE_PROJECT-macos.plist";
+				INFOPLIST_FILE = "TEMPLATE_PROJECT-macosx.plist";
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SDKROOT = macosx;
 				SDKROOT = macosx;
@@ -440,12 +437,12 @@
 					"GAMEPLAY_PATH/external-deps/bullet/include",
 					"GAMEPLAY_PATH/external-deps/bullet/include",
 					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
 					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
 				);
 				);
-				INFOPLIST_FILE = "TEMPLATE_PROJECT-macos.plist";
+				INFOPLIST_FILE = "TEMPLATE_PROJECT-macosx.plist";
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
-					"\"GAMEPLAY_PATH/external-deps/libpng/lib/macos\"",
-					"\"GAMEPLAY_PATH/external-deps/bullet/lib/macos\"",
-					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos\"",
+					"\"GAMEPLAY_PATH/external-deps/libpng/lib/macosx\"",
+					"\"GAMEPLAY_PATH/external-deps/bullet/lib/macosx\"",
+					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/macosx\"",
 				);
 				);
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				USER_HEADER_SEARCH_PATHS = "";
 				USER_HEADER_SEARCH_PATHS = "";
@@ -466,12 +463,12 @@
 					"GAMEPLAY_PATH/external-deps/bullet/include",
 					"GAMEPLAY_PATH/external-deps/bullet/include",
 					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
 					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
 				);
 				);
-				INFOPLIST_FILE = "TEMPLATE_PROJECT-macos.plist";
+				INFOPLIST_FILE = "TEMPLATE_PROJECT-macosx.plist";
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
-					"\"GAMEPLAY_PATH/external-deps/libpng/lib/macos\"",
-					"\"GAMEPLAY_PATH/external-deps/bullet/lib/macos\"",
-					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/macos\"",
+					"\"GAMEPLAY_PATH/external-deps/libpng/lib/macosx\"",
+					"\"GAMEPLAY_PATH/external-deps/bullet/lib/macosx\"",
+					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/macosx\"",
 				);
 				);
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				USER_HEADER_SEARCH_PATHS = "";
 				USER_HEADER_SEARCH_PATHS = "";

+ 82 - 39
gameplay.doxyfile

@@ -1,4 +1,4 @@
-# Doxyfile 1.7.5.1
+# Doxyfile 1.8.0
 
 
 # This file describes the settings to be used by the documentation system
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project
 # doxygen (www.doxygen.org) for a project
@@ -45,7 +45,7 @@ PROJECT_BRIEF          =
 # exceed 55 pixels and the maximum width should not exceed 200 pixels. 
 # exceed 55 pixels and the maximum width should not exceed 200 pixels. 
 # Doxygen will copy the logo to the output directory.
 # Doxygen will copy the logo to the output directory.
 
 
-PROJECT_LOGO           = 
+PROJECT_LOGO           = ./gameplay-api/gameplay.png
 
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
 # base path where the generated documentation will be put. 
 # base path where the generated documentation will be put. 
@@ -205,6 +205,13 @@ TAB_SIZE               = 8
 
 
 ALIASES                = 
 ALIASES                = 
 
 
+# This tag can be used to specify a number of word-keyword mappings (TCL only). 
+# A mapping has the form "name=value". For example adding 
+# "class=itcl::class" will allow you to use the command class in the 
+# itcl::class meaning.
+
+TCL_SUBST              = 
+
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
 # sources only. Doxygen will then generate output that is more tailored for C. 
 # sources only. Doxygen will then generate output that is more tailored for C. 
 # For instance, some of the names that are used will be different. The list 
 # For instance, some of the names that are used will be different. The list 
@@ -243,6 +250,15 @@ OPTIMIZE_OUTPUT_VHDL   = NO
 
 
 EXTENSION_MAPPING      = 
 EXTENSION_MAPPING      = 
 
 
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all 
+# comments according to the Markdown format, which allows for more readable 
+# documentation. See http://daringfireball.net/projects/markdown/ for details. 
+# The output of markdown processing is further processed by doxygen, so you 
+# can mix doxygen, HTML, and XML commands with Markdown formatting. 
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT       = YES
+
 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
 # to include (a tag file for) the STL sources as input, then you should 
 # to include (a tag file for) the STL sources as input, then you should 
 # set this tag to YES in order to let doxygen match functions declarations and 
 # set this tag to YES in order to let doxygen match functions declarations and 
@@ -325,10 +341,21 @@ TYPEDEF_HIDES_STRUCT   = NO
 # a logarithmic scale so increasing the size by one will roughly double the 
 # a logarithmic scale so increasing the size by one will roughly double the 
 # memory usage. The cache size is given by this formula: 
 # memory usage. The cache size is given by this formula: 
 # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
 # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
-# corresponding to a cache size of 2^16 = 65536 symbols
+# corresponding to a cache size of 2^16 = 65536 symbols.
 
 
 SYMBOL_CACHE_SIZE      = 0
 SYMBOL_CACHE_SIZE      = 0
 
 
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be 
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given 
+# their name and scope. Since this can be an expensive process and often the 
+# same symbol appear multiple times in the code, doxygen keeps a cache of 
+# pre-resolved symbols. If the cache is too small doxygen will become slower. 
+# If the cache is too large, memory is wasted. The cache size is given by this 
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE      = 0
+
 #---------------------------------------------------------------------------
 #---------------------------------------------------------------------------
 # Build related configuration options
 # Build related configuration options
 #---------------------------------------------------------------------------
 #---------------------------------------------------------------------------
@@ -345,6 +372,11 @@ EXTRACT_ALL            = NO
 
 
 EXTRACT_PRIVATE        = NO
 EXTRACT_PRIVATE        = NO
 
 
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE        = NO
+
 # If the EXTRACT_STATIC tag is set to YES all static members of a file 
 # If the EXTRACT_STATIC tag is set to YES all static members of a file 
 # will be included in the documentation.
 # will be included in the documentation.
 
 
@@ -574,7 +606,8 @@ LAYOUT_FILE            =
 # .bib extension is automatically appended if omitted. Using this command 
 # .bib extension is automatically appended if omitted. Using this command 
 # requires the bibtex tool to be installed. See also 
 # requires the bibtex tool to be installed. See also 
 # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style 
 # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style 
-# of the bibliography can be controlled using LATEX_BIB_STYLE.
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this 
+# feature you need bibtex and perl available in the search path.
 
 
 CITE_BIB_FILES         = 
 CITE_BIB_FILES         = 
 
 
@@ -695,14 +728,15 @@ FILE_PATTERNS          = *.c \
 
 
 RECURSIVE              = NO
 RECURSIVE              = NO
 
 
-# The EXCLUDE tag can be used to specify files and/or directories that should 
+# The EXCLUDE tag can be used to specify files and/or directories that should be 
 # excluded from the INPUT source files. This way you can easily exclude a 
 # excluded from the INPUT source files. This way you can easily exclude a 
 # subdirectory from a directory tree whose root is specified with the INPUT tag. 
 # subdirectory from a directory tree whose root is specified with the INPUT tag. 
-# Note that relative paths are relative to directory from which doxygen is run.
+# Note that relative paths are relative to the directory from which doxygen is 
+# run.
 
 
 EXCLUDE                = 
 EXCLUDE                = 
 
 
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or 
 # directories that are symbolic links (a Unix file system feature) are excluded 
 # directories that are symbolic links (a Unix file system feature) are excluded 
 # from the input.
 # from the input.
 
 
@@ -887,7 +921,7 @@ HTML_FILE_EXTENSION    = .html
 # standard header. Note that when using a custom header you are responsible  
 # standard header. Note that when using a custom header you are responsible  
 # for the proper inclusion of any scripts and style sheets that doxygen 
 # for the proper inclusion of any scripts and style sheets that doxygen 
 # needs, which is dependent on the configuration options used. 
 # needs, which is dependent on the configuration options used. 
-# It is adviced to generate a default header using "doxygen -w html 
+# It is advised to generate a default header using "doxygen -w html 
 # header.html footer.html stylesheet.css YourConfigFile" and then modify 
 # header.html footer.html stylesheet.css YourConfigFile" and then modify 
 # that header. Note that the header is subject to change so you typically 
 # that header. Note that the header is subject to change so you typically 
 # have to redo this when upgrading to a newer version of doxygen or when 
 # have to redo this when upgrading to a newer version of doxygen or when 
@@ -906,7 +940,7 @@ HTML_FOOTER            =
 # fine-tune the look of the HTML output. If the tag is left blank doxygen 
 # fine-tune the look of the HTML output. If the tag is left blank doxygen 
 # will generate a default style sheet. Note that doxygen will try to copy 
 # will generate a default style sheet. Note that doxygen will try to copy 
 # the style sheet file to the HTML output directory, so don't put your own 
 # the style sheet file to the HTML output directory, so don't put your own 
-# stylesheet in the HTML output directory as well, or it will be erased!
+# style sheet in the HTML output directory as well, or it will be erased!
 
 
 HTML_STYLESHEET        = 
 HTML_STYLESHEET        = 
 
 
@@ -920,7 +954,7 @@ HTML_STYLESHEET        =
 HTML_EXTRA_FILES       = 
 HTML_EXTRA_FILES       = 
 
 
 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. 
 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. 
-# Doxygen will adjust the colors in the stylesheet and background images 
+# Doxygen will adjust the colors in the style sheet and background images 
 # according to this color. Hue is specified as an angle on a colorwheel, 
 # according to this color. Hue is specified as an angle on a colorwheel, 
 # see http://en.wikipedia.org/wiki/Hue for more information. 
 # see http://en.wikipedia.org/wiki/Hue for more information. 
 # For instance the value 0 represents red, 60 is yellow, 120 is green, 
 # For instance the value 0 represents red, 60 is yellow, 120 is green, 
@@ -1115,29 +1149,33 @@ GENERATE_ECLIPSEHELP   = NO
 
 
 ECLIPSE_DOC_ID         = org.doxygen.Project
 ECLIPSE_DOC_ID         = org.doxygen.Project
 
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it.
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) 
+# at top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it. Since the tabs have the same information as the 
+# navigation tree you can set this option to NO if you already set 
+# GENERATE_TREEVIEW to YES.
 
 
 DISABLE_INDEX          = NO
 DISABLE_INDEX          = NO
 
 
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values 
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML 
-# documentation. Note that a value of 0 will completely suppress the enum 
-# values from appearing in the overview section.
-
-ENUM_VALUES_PER_LINE   = 4
-
 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
 # structure should be generated to display hierarchical information. 
 # structure should be generated to display hierarchical information. 
 # If the tag value is set to YES, a side panel will be generated 
 # If the tag value is set to YES, a side panel will be generated 
 # containing a tree-like index structure (just like the one that 
 # containing a tree-like index structure (just like the one that 
 # is generated for HTML Help). For this to work a browser that supports 
 # is generated for HTML Help). For this to work a browser that supports 
 # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
 # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
-# Windows users are probably better off using the HTML help feature.
+# Windows users are probably better off using the HTML help feature. 
+# Since the tree basically has the same information as the tab index you 
+# could consider to set DISABLE_INDEX to NO when enabling this option.
 
 
 GENERATE_TREEVIEW      = YES
 GENERATE_TREEVIEW      = YES
 
 
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values 
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML 
+# documentation. Note that a value of 0 will completely suppress the enum 
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
 # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 
 # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 
 # and Class Hierarchy pages using a tree view instead of an ordered list.
 # and Class Hierarchy pages using a tree view instead of an ordered list.
 
 
@@ -1174,7 +1212,7 @@ FORMULA_TRANSPARENT    = YES
 # (see http://www.mathjax.org) which uses client side Javascript for the 
 # (see http://www.mathjax.org) which uses client side Javascript for the 
 # rendering instead of using prerendered bitmaps. Use this if you do not 
 # rendering instead of using prerendered bitmaps. Use this if you do not 
 # have LaTeX installed or if you want to formulas look prettier in the HTML 
 # have LaTeX installed or if you want to formulas look prettier in the HTML 
-# output. When enabled you also need to install MathJax separately and 
+# output. When enabled you may also need to install MathJax separately and 
 # configure the path to it using the MATHJAX_RELPATH option.
 # configure the path to it using the MATHJAX_RELPATH option.
 
 
 USE_MATHJAX            = NO
 USE_MATHJAX            = NO
@@ -1183,10 +1221,10 @@ USE_MATHJAX            = NO
 # HTML output directory using the MATHJAX_RELPATH option. The destination 
 # HTML output directory using the MATHJAX_RELPATH option. The destination 
 # directory should contain the MathJax.js script. For instance, if the mathjax 
 # directory should contain the MathJax.js script. For instance, if the mathjax 
 # directory is located at the same level as the HTML output directory, then 
 # directory is located at the same level as the HTML output directory, then 
-# MATHJAX_RELPATH should be ../mathjax. The default value points to the 
-# mathjax.org site, so you can quickly see the result without installing 
-# MathJax, but it is strongly recommended to install a local copy of MathJax 
-# before deployment.
+# MATHJAX_RELPATH should be ../mathjax. The default value points to 
+# the MathJax Content Delivery Network so you can quickly see the result without 
+# installing MathJax.  However, it is strongly recommended to install a local 
+# copy of MathJax from http://www.mathjax.org before deployment.
 
 
 MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
 MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
 
 
@@ -1345,7 +1383,7 @@ COMPACT_RTF            = NO
 
 
 RTF_HYPERLINKS         = NO
 RTF_HYPERLINKS         = NO
 
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# Load style sheet definitions from file. Syntax is similar to doxygen's 
 # config file, i.e. a series of assignments. You only have to provide 
 # config file, i.e. a series of assignments. You only have to provide 
 # replacements, missing definitions are set to their default value.
 # replacements, missing definitions are set to their default value.
 
 
@@ -1534,20 +1572,16 @@ SKIP_FUNCTION_MACROS   = YES
 # Configuration::additions related to external references
 # Configuration::additions related to external references
 #---------------------------------------------------------------------------
 #---------------------------------------------------------------------------
 
 
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
+# The TAGFILES option can be used to specify one or more tagfiles. For each 
+# tag file the location of the external documentation should be added. The 
+# format of a tag file without this location is as follows: 
 #   TAGFILES = file1 file2 ... 
 #   TAGFILES = file1 file2 ... 
 # Adding location for the tag files is done as follows: 
 # Adding location for the tag files is done as follows: 
 #   TAGFILES = file1=loc1 "file2 = loc2" ... 
 #   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
-# does not have to be run to correct the links. 
-# Note that each tag file must have a unique name 
-# (where the name does NOT include the path) 
-# If a tag file is not located in the directory in which doxygen 
-# is run, you must also specify the path to the tagfile here.
+# where "loc1" and "loc2" can be relative or absolute paths 
+# or URLs. Note that each tag file must have a unique name (where the name does 
+# NOT include the path). If a tag file is not located in the directory in which 
+# doxygen is run, you must also specify the path to the tagfile here.
 
 
 TAGFILES               = 
 TAGFILES               = 
 
 
@@ -1638,7 +1672,7 @@ DOT_FONTPATH           =
 # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
 # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
 # will generate a graph for each documented class showing the direct and 
 # will generate a graph for each documented class showing the direct and 
 # indirect inheritance relations. Setting this tag to YES will force the 
 # indirect inheritance relations. Setting this tag to YES will force the 
-# the CLASS_DIAGRAMS tag to NO.
+# CLASS_DIAGRAMS tag to NO.
 
 
 CLASS_GRAPH            = YES
 CLASS_GRAPH            = YES
 
 
@@ -1660,6 +1694,15 @@ GROUP_GRAPHS           = YES
 
 
 UML_LOOK               = NO
 UML_LOOK               = NO
 
 
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside 
+# the class node. If there are many fields or methods and many nodes the 
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS 
+# threshold limits the number of items for each type to make the size more 
+# managable. Set this to 0 for no limit. Note that the threshold may be 
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
 # If set to YES, the inheritance and collaboration graphs will show the 
 # If set to YES, the inheritance and collaboration graphs will show the 
 # relations between templates and their instances.
 # relations between templates and their instances.
 
 

+ 22 - 11
gameplay.sln

@@ -3,11 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual Studio 2010
 # Visual Studio 2010
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay", "gameplay\gameplay.vcxproj", "{1032BA4B-57EB-4348-9E03-29DD63E80E4A}"
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay", "gameplay\gameplay.vcxproj", "{1032BA4B-57EB-4348-9E03-29DD63E80E4A}"
 EndProject
 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
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample01-longboard", "gameplay-samples\sample01-longboard\sample01-longboard.vcxproj", "{9A515C8B-3320-4C5C-9754-211E91206C9D}"
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample01-longboard", "gameplay-samples\sample01-longboard\sample01-longboard.vcxproj", "{9A515C8B-3320-4C5C-9754-211E91206C9D}"
 	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}
@@ -25,6 +20,16 @@ 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}"
+	ProjectSection(ProjectDependencies) = postProject
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
+	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
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
 		Debug|Win32 = Debug|Win32
@@ -38,12 +43,6 @@ Global
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|Win32.Build.0 = DebugMem|Win32
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|Win32.Build.0 = DebugMem|Win32
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|Win32.ActiveCfg = Release|Win32
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|Win32.ActiveCfg = Release|Win32
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|Win32.Build.0 = Release|Win32
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|Win32.Build.0 = Release|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}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
-		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|Win32.Build.0 = DebugMem|Win32
-		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.ActiveCfg = Release|Win32
-		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.Build.0 = Release|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|Win32.ActiveCfg = Debug|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|Win32.ActiveCfg = Debug|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|Win32.Build.0 = Debug|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|Win32.Build.0 = Debug|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
@@ -68,6 +67,18 @@ 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
+		{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}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.ActiveCfg = Release|Win32
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE

+ 3 - 0
gameplay.xcworkspace/contents.xcworkspacedata

@@ -19,4 +19,7 @@
    <FileRef
    <FileRef
       location = "group:gameplay-samples/sample03-character/sample03-character.xcodeproj">
       location = "group:gameplay-samples/sample03-character/sample03-character.xcodeproj">
    </FileRef>
    </FileRef>
+   <FileRef
+      location = "group:gameplay-samples/sample04-particles/sample04-particles.xcodeproj">
+   </FileRef>
 </Workspace>
 </Workspace>

+ 1 - 1
gameplay/android/jni/Android.mk

@@ -16,7 +16,7 @@ LOCAL_PATH := $(call my-dir)/../../src
 
 
 include $(CLEAR_VARS)
 include $(CLEAR_VARS)
 LOCAL_MODULE    := libgameplay
 LOCAL_MODULE    := libgameplay
-LOCAL_SRC_FILES := Animation.cpp DepthStencilTarget.cpp MeshBatch.cpp PhysicsRigidBody.cpp SceneLoader.cpp AnimationClip.cpp Effect.cpp MeshPart.cpp PhysicsSocketConstraint.cpp SpriteBatch.cpp AnimationController.cpp FileSystem.cpp MeshSkin.cpp PhysicsSpringConstraint.cpp Technique.cpp AnimationTarget.cpp Font.cpp Model.cpp Plane.cpp Texture.cpp AnimationValue.cpp FrameBuffer.cpp Node.cpp PlatformAndroid.cpp PlatformQNX.cpp AudioBuffer.cpp Frustum.cpp Package.cpp PlatformWin32.cpp Transform.cpp AudioController.cpp Game.cpp ParticleEmitter.cpp Properties.cpp Vector2.cpp AudioListener.cpp Image.cpp Pass.cpp Quaternion.cpp Vector3.cpp AudioSource.cpp Joint.cpp PhysicsConstraint.cpp Ray.cpp Vector4.cpp BoundingBox.cpp Light.cpp PhysicsController.cpp Rectangle.cpp VertexAttributeBinding.cpp BoundingSphere.cpp Material.cpp PhysicsFixedConstraint.cpp Ref.cpp VertexFormat.cpp Camera.cpp MaterialParameter.cpp PhysicsGenericConstraint.cpp RenderState.cpp Viewport.cpp Curve.cpp Matrix.cpp PhysicsHingeConstraint.cpp RenderTarget.cpp DebugNew.cpp Mesh.cpp PhysicsMotionState.cpp Scene.cpp
+LOCAL_SRC_FILES := AbsoluteLayout.cpp Animation.cpp AnimationClip.cpp AnimationController.cpp AnimationTarget.cpp AnimationValue.cpp AudioBuffer.cpp AudioController.cpp AudioListener.cpp AudioSource.cpp BoundingBox.cpp BoundingSphere.cpp Button.cpp Camera.cpp CheckBox.cpp Container.cpp Control.cpp Curve.cpp DebugNew.cpp DepthStencilTarget.cpp Effect.cpp FileSystem.cpp Font.cpp Form.cpp FrameBuffer.cpp Frustum.cpp Game.cpp gameplay-main-android.cpp gameplay-main-qnx.cpp gameplay-main-win32.cpp Image.cpp Joint.cpp Label.cpp Layout.cpp Light.cpp Material.cpp MaterialParameter.cpp Matrix.cpp Mesh.cpp MeshBatch.cpp MeshPart.cpp MeshSkin.cpp Model.cpp Node.cpp Package.cpp ParticleEmitter.cpp Pass.cpp PhysicsCharacter.cpp PhysicsCollisionObject.cpp PhysicsCollisionShape.cpp PhysicsConstraint.cpp PhysicsController.cpp PhysicsFixedConstraint.cpp PhysicsGenericConstraint.cpp PhysicsGhostObject.cpp PhysicsHingeConstraint.cpp PhysicsMotionState.cpp PhysicsRigidBody.cpp PhysicsSocketConstraint.cpp PhysicsSpringConstraint.cpp Plane.cpp PlatformAndroid.cpp PlatformQNX.cpp PlatformWin32.cpp Properties.cpp Quaternion.cpp RadioButton.cpp Ray.cpp Rectangle.cpp Ref.cpp RenderState.cpp RenderTarget.cpp Scene.cpp SceneLoader.cpp Slider.cpp SpriteBatch.cpp Technique.cpp TextBox.cpp Texture.cpp Theme.cpp ThemeStyle.cpp Transform.cpp Vector2.cpp Vector3.cpp Vector4.cpp VertexAttributeBinding.cpp VertexFormat.cpp VerticalLayout.cpp
 LOCAL_CFLAGS := -D__ANDROID__ -I"../../external-deps/bullet/include" -I"../../external-deps/libpng/include"
 LOCAL_CFLAGS := -D__ANDROID__ -I"../../external-deps/bullet/include" -I"../../external-deps/libpng/include"
 LOCAL_STATIC_LIBRARIES := android_native_app_glue
 LOCAL_STATIC_LIBRARIES := android_native_app_glue
 
 

+ 6 - 6
gameplay/gameplay.vcxproj

@@ -30,7 +30,6 @@
     <ClCompile Include="src\Button.cpp" />
     <ClCompile Include="src\Button.cpp" />
     <ClCompile Include="src\Camera.cpp" />
     <ClCompile Include="src\Camera.cpp" />
     <ClCompile Include="src\CheckBox.cpp" />
     <ClCompile Include="src\CheckBox.cpp" />
-    <ClCompile Include="src\CloneContext.cpp" />
     <ClCompile Include="src\Container.cpp" />
     <ClCompile Include="src\Container.cpp" />
     <ClCompile Include="src\Control.cpp" />
     <ClCompile Include="src\Control.cpp" />
     <ClCompile Include="src\Curve.cpp" />
     <ClCompile Include="src\Curve.cpp" />
@@ -49,6 +48,7 @@
     <ClCompile Include="src\Image.cpp" />
     <ClCompile Include="src\Image.cpp" />
     <ClCompile Include="src\Joint.cpp" />
     <ClCompile Include="src\Joint.cpp" />
     <ClCompile Include="src\Label.cpp" />
     <ClCompile Include="src\Label.cpp" />
+    <ClCompile Include="src\Layout.cpp" />
     <ClCompile Include="src\Light.cpp" />
     <ClCompile Include="src\Light.cpp" />
     <ClCompile Include="src\Material.cpp" />
     <ClCompile Include="src\Material.cpp" />
     <ClCompile Include="src\MeshBatch.cpp" />
     <ClCompile Include="src\MeshBatch.cpp" />
@@ -95,6 +95,7 @@
     <ClCompile Include="src\TextBox.cpp" />
     <ClCompile Include="src\TextBox.cpp" />
     <ClCompile Include="src\Texture.cpp" />
     <ClCompile Include="src\Texture.cpp" />
     <ClCompile Include="src\Theme.cpp" />
     <ClCompile Include="src\Theme.cpp" />
+    <ClCompile Include="src\ThemeStyle.cpp" />
     <ClCompile Include="src\Transform.cpp" />
     <ClCompile Include="src\Transform.cpp" />
     <ClCompile Include="src\Vector2.cpp" />
     <ClCompile Include="src\Vector2.cpp" />
     <ClCompile Include="src\Vector3.cpp" />
     <ClCompile Include="src\Vector3.cpp" />
@@ -102,7 +103,6 @@
     <ClCompile Include="src\VertexAttributeBinding.cpp" />
     <ClCompile Include="src\VertexAttributeBinding.cpp" />
     <ClCompile Include="src\VertexFormat.cpp" />
     <ClCompile Include="src\VertexFormat.cpp" />
     <ClCompile Include="src\VerticalLayout.cpp" />
     <ClCompile Include="src\VerticalLayout.cpp" />
-    <ClCompile Include="src\Viewport.cpp" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\AbsoluteLayout.h" />
     <ClInclude Include="src\AbsoluteLayout.h" />
@@ -121,7 +121,6 @@
     <ClInclude Include="src\Button.h" />
     <ClInclude Include="src\Button.h" />
     <ClInclude Include="src\Camera.h" />
     <ClInclude Include="src\Camera.h" />
     <ClInclude Include="src\CheckBox.h" />
     <ClInclude Include="src\CheckBox.h" />
-    <ClInclude Include="src\CloneContext.h" />
     <ClInclude Include="src\Container.h" />
     <ClInclude Include="src\Container.h" />
     <ClInclude Include="src\Control.h" />
     <ClInclude Include="src\Control.h" />
     <ClInclude Include="src\Curve.h" />
     <ClInclude Include="src\Curve.h" />
@@ -179,12 +178,14 @@
     <ClInclude Include="src\RenderTarget.h" />
     <ClInclude Include="src\RenderTarget.h" />
     <ClInclude Include="src\Scene.h" />
     <ClInclude Include="src\Scene.h" />
     <ClInclude Include="src\SceneLoader.h" />
     <ClInclude Include="src\SceneLoader.h" />
+    <ClInclude Include="src\ScreenDisplayer.h" />
     <ClInclude Include="src\Slider.h" />
     <ClInclude Include="src\Slider.h" />
     <ClInclude Include="src\SpriteBatch.h" />
     <ClInclude Include="src\SpriteBatch.h" />
     <ClInclude Include="src\Technique.h" />
     <ClInclude Include="src\Technique.h" />
     <ClInclude Include="src\TextBox.h" />
     <ClInclude Include="src\TextBox.h" />
     <ClInclude Include="src\Texture.h" />
     <ClInclude Include="src\Texture.h" />
     <ClInclude Include="src\Theme.h" />
     <ClInclude Include="src\Theme.h" />
+    <ClInclude Include="src\ThemeStyle.h" />
     <ClInclude Include="src\TimeListener.h" />
     <ClInclude Include="src\TimeListener.h" />
     <ClInclude Include="src\Touch.h" />
     <ClInclude Include="src\Touch.h" />
     <ClInclude Include="src\Transform.h" />
     <ClInclude Include="src\Transform.h" />
@@ -194,7 +195,6 @@
     <ClInclude Include="src\VertexAttributeBinding.h" />
     <ClInclude Include="src\VertexAttributeBinding.h" />
     <ClInclude Include="src\VertexFormat.h" />
     <ClInclude Include="src\VertexFormat.h" />
     <ClInclude Include="src\VerticalLayout.h" />
     <ClInclude Include="src\VerticalLayout.h" />
-    <ClInclude Include="src\Viewport.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <None Include="res\logo_black.png" />
     <None Include="res\logo_black.png" />
@@ -227,13 +227,13 @@
     <None Include="src\Curve.inl" />
     <None Include="src\Curve.inl" />
     <None Include="src\Game.inl" />
     <None Include="src\Game.inl" />
     <None Include="src\gameplay-main-ios.mm" />
     <None Include="src\gameplay-main-ios.mm" />
-    <None Include="src\gameplay-main-macos.mm" />
+    <None Include="src\gameplay-main-macosx.mm" />
     <None Include="src\Image.inl" />
     <None Include="src\Image.inl" />
     <None Include="src\Matrix.inl" />
     <None Include="src\Matrix.inl" />
     <None Include="src\MeshBatch.inl" />
     <None Include="src\MeshBatch.inl" />
     <None Include="src\Plane.inl" />
     <None Include="src\Plane.inl" />
     <None Include="src\PlatformiOS.mm" />
     <None Include="src\PlatformiOS.mm" />
-    <None Include="src\PlatformMacOS.mm" />
+    <None Include="src\PlatformMacOSX.mm" />
     <None Include="src\Quaternion.inl" />
     <None Include="src\Quaternion.inl" />
     <None Include="src\Ray.inl" />
     <None Include="src\Ray.inl" />
     <None Include="src\Vector2.inl" />
     <None Include="src\Vector2.inl" />

+ 10 - 10
gameplay/gameplay.vcxproj.filters

@@ -126,9 +126,6 @@
     <ClCompile Include="src\VertexFormat.cpp">
     <ClCompile Include="src\VertexFormat.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="src\Viewport.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
     <ClCompile Include="src\AudioController.cpp">
     <ClCompile Include="src\AudioController.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
@@ -276,7 +273,10 @@
     <ClCompile Include="src\PhysicsCollisionShape.cpp">
     <ClCompile Include="src\PhysicsCollisionShape.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="src\CloneContext.cpp">
+    <ClCompile Include="src\ThemeStyle.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Layout.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
   </ItemGroup>
   </ItemGroup>
@@ -398,9 +398,6 @@
     <ClInclude Include="src\VertexFormat.h">
     <ClInclude Include="src\VertexFormat.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="src\Viewport.h">
-      <Filter>src</Filter>
-    </ClInclude>
     <ClInclude Include="src\AudioController.h">
     <ClInclude Include="src\AudioController.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
@@ -548,7 +545,10 @@
     <ClInclude Include="src\PhysicsCollisionShape.h">
     <ClInclude Include="src\PhysicsCollisionShape.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="src\CloneContext.h">
+    <ClInclude Include="src\ScreenDisplayer.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\ThemeStyle.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
   </ItemGroup>
   </ItemGroup>
@@ -613,10 +613,10 @@
     <None Include="res\shaders\bumped-specular.fsh">
     <None Include="res\shaders\bumped-specular.fsh">
       <Filter>res\shaders</Filter>
       <Filter>res\shaders</Filter>
     </None>
     </None>
-    <None Include="src\gameplay-main-macos.mm">
+    <None Include="src\gameplay-main-macosx.mm">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </None>
     </None>
-    <None Include="src\PlatformMacOS.mm">
+    <None Include="src\PlatformMacOSX.mm">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </None>
     </None>
     <None Include="res\textures\particle-default.png">
     <None Include="res\textures\particle-default.png">

+ 98 - 81
gameplay/gameplay.xcodeproj/project.pbxproj

@@ -14,6 +14,18 @@
 		4208DEEC14A407B900D3C511 /* Keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEEB14A407B900D3C511 /* Keyboard.h */; };
 		4208DEEC14A407B900D3C511 /* Keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEEB14A407B900D3C511 /* Keyboard.h */; };
 		4208DEEE14A407D500D3C511 /* Touch.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEED14A407D500D3C511 /* Touch.h */; };
 		4208DEEE14A407D500D3C511 /* Touch.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEED14A407D500D3C511 /* Touch.h */; };
 		4234D99E14686C52003031B3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4234D99D14686C52003031B3 /* Cocoa.framework */; };
 		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 */; };
+		4251B133152D049B002F6199 /* ThemeStyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4251B12F152D049B002F6199 /* ThemeStyle.cpp */; };
+		4251B134152D049B002F6199 /* ThemeStyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4251B12F152D049B002F6199 /* ThemeStyle.cpp */; };
+		4251B135152D049B002F6199 /* ThemeStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 4251B130152D049B002F6199 /* ThemeStyle.h */; };
+		4251B136152D049B002F6199 /* ThemeStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 4251B130152D049B002F6199 /* ThemeStyle.h */; };
+		42554EA1152BC35C000ED910 /* PhysicsCollisionShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42554E9F152BC35C000ED910 /* PhysicsCollisionShape.cpp */; };
+		42554EA2152BC35C000ED910 /* PhysicsCollisionShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42554E9F152BC35C000ED910 /* PhysicsCollisionShape.cpp */; };
+		42554EA3152BC35C000ED910 /* PhysicsCollisionShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 42554EA0152BC35C000ED910 /* PhysicsCollisionShape.h */; };
+		42554EA4152BC35C000ED910 /* PhysicsCollisionShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 42554EA0152BC35C000ED910 /* PhysicsCollisionShape.h */; };
+		4271C08E15337C8200B89DA7 /* Layout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4271C08D15337C8200B89DA7 /* Layout.cpp */; };
+		4271C08F15337C8200B89DA7 /* Layout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4271C08D15337C8200B89DA7 /* Layout.cpp */; };
 		428390991489D6E800E2B2F5 /* SceneLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 428390971489D6E800E2B2F5 /* SceneLoader.cpp */; };
 		428390991489D6E800E2B2F5 /* SceneLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 428390971489D6E800E2B2F5 /* SceneLoader.cpp */; };
 		4283909A1489D6E800E2B2F5 /* SceneLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 428390981489D6E800E2B2F5 /* SceneLoader.h */; };
 		4283909A1489D6E800E2B2F5 /* SceneLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 428390981489D6E800E2B2F5 /* SceneLoader.h */; };
 		42CCD556146EC1EB00353661 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CCD555146EC1EB00353661 /* libpng.a */; };
 		42CCD556146EC1EB00353661 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CCD555146EC1EB00353661 /* libpng.a */; };
@@ -65,7 +77,7 @@
 		42CD0E6E147D8FF60000361E /* Frustum.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DDB147D8FF50000361E /* Frustum.h */; };
 		42CD0E6E147D8FF60000361E /* Frustum.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DDB147D8FF50000361E /* Frustum.h */; };
 		42CD0E6F147D8FF60000361E /* Game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDC147D8FF50000361E /* Game.cpp */; };
 		42CD0E6F147D8FF60000361E /* Game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDC147D8FF50000361E /* Game.cpp */; };
 		42CD0E70147D8FF60000361E /* Game.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DDD147D8FF50000361E /* Game.h */; };
 		42CD0E70147D8FF60000361E /* Game.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DDD147D8FF50000361E /* Game.h */; };
-		42CD0E71147D8FF60000361E /* gameplay-main-macos.mm in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDE147D8FF50000361E /* gameplay-main-macos.mm */; };
+		42CD0E71147D8FF60000361E /* gameplay-main-macosx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDE147D8FF50000361E /* gameplay-main-macosx.mm */; };
 		42CD0E74147D8FF60000361E /* gameplay.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE1147D8FF50000361E /* gameplay.h */; };
 		42CD0E74147D8FF60000361E /* gameplay.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE1147D8FF50000361E /* gameplay.h */; };
 		42CD0E77147D8FF60000361E /* Joint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DE4147D8FF50000361E /* Joint.cpp */; };
 		42CD0E77147D8FF60000361E /* Joint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DE4147D8FF50000361E /* Joint.cpp */; };
 		42CD0E78147D8FF60000361E /* Joint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE5147D8FF50000361E /* Joint.h */; };
 		42CD0E78147D8FF60000361E /* Joint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE5147D8FF50000361E /* Joint.h */; };
@@ -114,7 +126,7 @@
 		42CD0EA3147D8FF60000361E /* Plane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E16147D8FF50000361E /* Plane.cpp */; };
 		42CD0EA3147D8FF60000361E /* Plane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E16147D8FF50000361E /* Plane.cpp */; };
 		42CD0EA4147D8FF60000361E /* Plane.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E17147D8FF50000361E /* Plane.h */; };
 		42CD0EA4147D8FF60000361E /* Plane.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E17147D8FF50000361E /* Plane.h */; };
 		42CD0EA5147D8FF60000361E /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E19147D8FF50000361E /* Platform.h */; };
 		42CD0EA5147D8FF60000361E /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E19147D8FF50000361E /* Platform.h */; };
-		42CD0EA6147D8FF60000361E /* PlatformMacOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1A147D8FF50000361E /* PlatformMacOS.mm */; };
+		42CD0EA6147D8FF60000361E /* PlatformMacOSX.mm in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1A147D8FF50000361E /* PlatformMacOSX.mm */; };
 		42CD0EA9147D8FF60000361E /* Properties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1D147D8FF50000361E /* Properties.cpp */; };
 		42CD0EA9147D8FF60000361E /* Properties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1D147D8FF50000361E /* Properties.cpp */; };
 		42CD0EAA147D8FF60000361E /* Properties.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E1E147D8FF50000361E /* Properties.h */; };
 		42CD0EAA147D8FF60000361E /* Properties.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E1E147D8FF50000361E /* Properties.h */; };
 		42CD0EAB147D8FF60000361E /* Quaternion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1F147D8FF50000361E /* Quaternion.cpp */; };
 		42CD0EAB147D8FF60000361E /* Quaternion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1F147D8FF50000361E /* Quaternion.cpp */; };
@@ -149,8 +161,6 @@
 		42CD0EC8147D8FF60000361E /* VertexAttributeBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E41147D8FF50000361E /* VertexAttributeBinding.h */; };
 		42CD0EC8147D8FF60000361E /* VertexAttributeBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E41147D8FF50000361E /* VertexAttributeBinding.h */; };
 		42CD0EC9147D8FF60000361E /* VertexFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E42147D8FF50000361E /* VertexFormat.cpp */; };
 		42CD0EC9147D8FF60000361E /* VertexFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E42147D8FF50000361E /* VertexFormat.cpp */; };
 		42CD0ECA147D8FF60000361E /* VertexFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E43147D8FF50000361E /* VertexFormat.h */; };
 		42CD0ECA147D8FF60000361E /* VertexFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E43147D8FF50000361E /* VertexFormat.h */; };
-		42CD0ECB147D8FF60000361E /* Viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E44147D8FF50000361E /* Viewport.cpp */; };
-		42CD0ECC147D8FF60000361E /* Viewport.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E45147D8FF50000361E /* Viewport.h */; };
 		5B04C52D14BFCFE100EB0071 /* Animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB1147D8FF50000361E /* Animation.cpp */; };
 		5B04C52D14BFCFE100EB0071 /* Animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB1147D8FF50000361E /* Animation.cpp */; };
 		5B04C52E14BFCFE100EB0071 /* AnimationClip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB3147D8FF50000361E /* AnimationClip.cpp */; };
 		5B04C52E14BFCFE100EB0071 /* AnimationClip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB3147D8FF50000361E /* AnimationClip.cpp */; };
 		5B04C52F14BFCFE100EB0071 /* AnimationController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB5147D8FF50000361E /* AnimationController.cpp */; };
 		5B04C52F14BFCFE100EB0071 /* AnimationController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB5147D8FF50000361E /* AnimationController.cpp */; };
@@ -212,7 +222,6 @@
 		5B04C56D14BFCFE100EB0071 /* Vector4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E3D147D8FF50000361E /* Vector4.cpp */; };
 		5B04C56D14BFCFE100EB0071 /* Vector4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E3D147D8FF50000361E /* Vector4.cpp */; };
 		5B04C56E14BFCFE100EB0071 /* VertexAttributeBinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E40147D8FF50000361E /* VertexAttributeBinding.cpp */; };
 		5B04C56E14BFCFE100EB0071 /* VertexAttributeBinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E40147D8FF50000361E /* VertexAttributeBinding.cpp */; };
 		5B04C56F14BFCFE100EB0071 /* VertexFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E42147D8FF50000361E /* VertexFormat.cpp */; };
 		5B04C56F14BFCFE100EB0071 /* VertexFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E42147D8FF50000361E /* VertexFormat.cpp */; };
-		5B04C57014BFCFE100EB0071 /* Viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E44147D8FF50000361E /* Viewport.cpp */; };
 		5B04C57114BFCFE100EB0071 /* SceneLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 428390971489D6E800E2B2F5 /* SceneLoader.cpp */; };
 		5B04C57114BFCFE100EB0071 /* SceneLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 428390971489D6E800E2B2F5 /* SceneLoader.cpp */; };
 		5B04C57214BFCFE100EB0071 /* Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4208DEE614A4079F00D3C511 /* Image.cpp */; };
 		5B04C57214BFCFE100EB0071 /* Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4208DEE614A4079F00D3C511 /* Image.cpp */; };
 		5B04C57314BFCFE100EB0071 /* MeshBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4201818D14A41B18008C3F56 /* MeshBatch.cpp */; };
 		5B04C57314BFCFE100EB0071 /* MeshBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4201818D14A41B18008C3F56 /* MeshBatch.cpp */; };
@@ -286,7 +295,6 @@
 		5B04C5BE14BFCFE100EB0071 /* Vector4.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E3E147D8FF50000361E /* Vector4.h */; };
 		5B04C5BE14BFCFE100EB0071 /* Vector4.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E3E147D8FF50000361E /* Vector4.h */; };
 		5B04C5BF14BFCFE100EB0071 /* VertexAttributeBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E41147D8FF50000361E /* VertexAttributeBinding.h */; };
 		5B04C5BF14BFCFE100EB0071 /* VertexAttributeBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E41147D8FF50000361E /* VertexAttributeBinding.h */; };
 		5B04C5C014BFCFE100EB0071 /* VertexFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E43147D8FF50000361E /* VertexFormat.h */; };
 		5B04C5C014BFCFE100EB0071 /* VertexFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E43147D8FF50000361E /* VertexFormat.h */; };
-		5B04C5C114BFCFE100EB0071 /* Viewport.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E45147D8FF50000361E /* Viewport.h */; };
 		5B04C5C214BFCFE100EB0071 /* SceneLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 428390981489D6E800E2B2F5 /* SceneLoader.h */; };
 		5B04C5C214BFCFE100EB0071 /* SceneLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 428390981489D6E800E2B2F5 /* SceneLoader.h */; };
 		5B04C5C314BFCFE100EB0071 /* Image.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEE714A4079F00D3C511 /* Image.h */; };
 		5B04C5C314BFCFE100EB0071 /* Image.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEE714A4079F00D3C511 /* Image.h */; };
 		5B04C5C414BFCFE100EB0071 /* Keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEEB14A407B900D3C511 /* Keyboard.h */; };
 		5B04C5C414BFCFE100EB0071 /* Keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEEB14A407B900D3C511 /* Keyboard.h */; };
@@ -298,14 +306,14 @@
 		5B2BC7601512514500D176CD /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC75E1512514500D176CD /* OpenGL.framework */; };
 		5B2BC7601512514500D176CD /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC75E1512514500D176CD /* OpenGL.framework */; };
 		5B2BC7621512514D00D176CD /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC7611512514D00D176CD /* QuartzCore.framework */; };
 		5B2BC7621512514D00D176CD /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC7611512514D00D176CD /* QuartzCore.framework */; };
 		5B2BC7641512516B00D176CD /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC7631512516B00D176CD /* libz.dylib */; };
 		5B2BC7641512516B00D176CD /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC7631512516B00D176CD /* libz.dylib */; };
-		5B2BC765151251EB00D176CD /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC7561512507500D176CD /* CoreMotion.framework */; };
-		5B2BC76D151251EB00D176CD /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC766151251EB00D176CD /* CoreGraphics.framework */; };
-		5B2BC76E151251EB00D176CD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC767151251EB00D176CD /* Foundation.framework */; };
-		5B2BC76F151251EB00D176CD /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC768151251EB00D176CD /* libz.dylib */; };
-		5B2BC770151251EB00D176CD /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC769151251EB00D176CD /* OpenAL.framework */; };
-		5B2BC771151251EB00D176CD /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC76A151251EB00D176CD /* OpenGLES.framework */; };
-		5B2BC772151251EB00D176CD /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC76B151251EB00D176CD /* QuartzCore.framework */; };
-		5B2BC773151251EB00D176CD /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B2BC76C151251EB00D176CD /* UIKit.framework */; };
+		5BAF201F152F2A6D003E2AC3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF201E152F2A6D003E2AC3 /* libz.dylib */; };
+		5BAF2027152F2AF0003E2AC3 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2020152F2AF0003E2AC3 /* CoreGraphics.framework */; };
+		5BAF2028152F2AF0003E2AC3 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2021152F2AF0003E2AC3 /* CoreMotion.framework */; };
+		5BAF2029152F2AF0003E2AC3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2022152F2AF0003E2AC3 /* Foundation.framework */; };
+		5BAF202A152F2AF0003E2AC3 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2023152F2AF0003E2AC3 /* OpenAL.framework */; };
+		5BAF202B152F2AF0003E2AC3 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2024152F2AF0003E2AC3 /* OpenGLES.framework */; };
+		5BAF202C152F2AF0003E2AC3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2025152F2AF0003E2AC3 /* QuartzCore.framework */; };
+		5BAF202D152F2AF0003E2AC3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BAF2026152F2AF0003E2AC3 /* UIKit.framework */; };
 		5BB0823D14C6FEC40019975F /* Mouse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BB0823C14C6FEC40019975F /* Mouse.h */; };
 		5BB0823D14C6FEC40019975F /* Mouse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BB0823C14C6FEC40019975F /* Mouse.h */; };
 		5BB0823E14C6FEC40019975F /* Mouse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BB0823C14C6FEC40019975F /* Mouse.h */; };
 		5BB0823E14C6FEC40019975F /* Mouse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BB0823C14C6FEC40019975F /* Mouse.h */; };
 		5BBE143E1513E400003FB362 /* PhysicsGhostObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BBE143C1513E400003FB362 /* PhysicsGhostObject.cpp */; };
 		5BBE143E1513E400003FB362 /* PhysicsGhostObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BBE143C1513E400003FB362 /* PhysicsGhostObject.cpp */; };
@@ -322,7 +330,6 @@
 		5BC4E746150F843D00CBE1C0 /* Container.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263B150F822A004C9099 /* Container.h */; };
 		5BC4E746150F843D00CBE1C0 /* Container.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263B150F822A004C9099 /* Container.h */; };
 		5BC4E747150F843D00CBE1C0 /* Control.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5263C150F822A004C9099 /* Control.cpp */; };
 		5BC4E747150F843D00CBE1C0 /* Control.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5263C150F822A004C9099 /* Control.cpp */; };
 		5BC4E748150F843D00CBE1C0 /* Control.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263D150F822A004C9099 /* Control.h */; };
 		5BC4E748150F843D00CBE1C0 /* Control.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263D150F822A004C9099 /* Control.h */; };
-		5BC4E749150F843D00CBE1C0 /* FlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263E150F822A004C9099 /* FlowLayout.h */; };
 		5BC4E74A150F843D00CBE1C0 /* Form.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5263F150F822A004C9099 /* Form.cpp */; };
 		5BC4E74A150F843D00CBE1C0 /* Form.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5263F150F822A004C9099 /* Form.cpp */; };
 		5BC4E74B150F843D00CBE1C0 /* Form.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD52640150F822A004C9099 /* Form.h */; };
 		5BC4E74B150F843D00CBE1C0 /* Form.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD52640150F822A004C9099 /* Form.h */; };
 		5BC4E74C150F843D00CBE1C0 /* Label.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD52641150F822A004C9099 /* Label.cpp */; };
 		5BC4E74C150F843D00CBE1C0 /* Label.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD52641150F822A004C9099 /* Label.cpp */; };
@@ -348,7 +355,6 @@
 		5BD52656150F822A004C9099 /* Container.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263B150F822A004C9099 /* Container.h */; };
 		5BD52656150F822A004C9099 /* Container.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263B150F822A004C9099 /* Container.h */; };
 		5BD52657150F822A004C9099 /* Control.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5263C150F822A004C9099 /* Control.cpp */; };
 		5BD52657150F822A004C9099 /* Control.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5263C150F822A004C9099 /* Control.cpp */; };
 		5BD52658150F822A004C9099 /* Control.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263D150F822A004C9099 /* Control.h */; };
 		5BD52658150F822A004C9099 /* Control.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263D150F822A004C9099 /* Control.h */; };
-		5BD52659150F822A004C9099 /* FlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5263E150F822A004C9099 /* FlowLayout.h */; };
 		5BD5265A150F822A004C9099 /* Form.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5263F150F822A004C9099 /* Form.cpp */; };
 		5BD5265A150F822A004C9099 /* Form.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5263F150F822A004C9099 /* Form.cpp */; };
 		5BD5265B150F822A004C9099 /* Form.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD52640150F822A004C9099 /* Form.h */; };
 		5BD5265B150F822A004C9099 /* Form.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD52640150F822A004C9099 /* Form.h */; };
 		5BD5265C150F822A004C9099 /* Label.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD52641150F822A004C9099 /* Label.cpp */; };
 		5BD5265C150F822A004C9099 /* Label.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD52641150F822A004C9099 /* Label.cpp */; };
@@ -387,15 +393,21 @@
 		4208DEED14A407D500D3C511 /* Touch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Touch.h; path = src/Touch.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; };
 		4234D99A14686C52003031B3 /* libgameplay.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgameplay.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		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; };
 		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; };
+		4251B12F152D049B002F6199 /* ThemeStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThemeStyle.cpp; path = src/ThemeStyle.cpp; sourceTree = SOURCE_ROOT; };
+		4251B130152D049B002F6199 /* ThemeStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThemeStyle.h; path = src/ThemeStyle.h; sourceTree = SOURCE_ROOT; };
+		42554E9F152BC35C000ED910 /* PhysicsCollisionShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PhysicsCollisionShape.cpp; path = src/PhysicsCollisionShape.cpp; sourceTree = SOURCE_ROOT; };
+		42554EA0152BC35C000ED910 /* PhysicsCollisionShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhysicsCollisionShape.h; path = src/PhysicsCollisionShape.h; sourceTree = SOURCE_ROOT; };
+		4271C08D15337C8200B89DA7 /* Layout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Layout.cpp; path = src/Layout.cpp; sourceTree = SOURCE_ROOT; };
 		428390971489D6E800E2B2F5 /* SceneLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SceneLoader.cpp; path = src/SceneLoader.cpp; sourceTree = SOURCE_ROOT; };
 		428390971489D6E800E2B2F5 /* SceneLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SceneLoader.cpp; path = src/SceneLoader.cpp; sourceTree = SOURCE_ROOT; };
 		428390981489D6E800E2B2F5 /* SceneLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SceneLoader.h; path = src/SceneLoader.h; sourceTree = SOURCE_ROOT; };
 		428390981489D6E800E2B2F5 /* SceneLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SceneLoader.h; path = src/SceneLoader.h; sourceTree = SOURCE_ROOT; };
 		42C932AF14919FD10098216A /* Game.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Game.inl; path = src/Game.inl; sourceTree = SOURCE_ROOT; };
 		42C932AF14919FD10098216A /* Game.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Game.inl; path = src/Game.inl; sourceTree = SOURCE_ROOT; };
-		42CCD555146EC1EB00353661 /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/macos/libpng.a"; sourceTree = "<group>"; };
-		42CD0DA6147D8EA80000361E /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "../external-deps/bullet/lib/macos/libbullet.a"; sourceTree = "<group>"; };
-		42CD0DA7147D8EA80000361E /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "../external-deps/oggvorbis/lib/macos/libogg.a"; sourceTree = "<group>"; };
-		42CD0DA8147D8EA80000361E /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "../external-deps/oggvorbis/lib/macos/libvorbis.a"; sourceTree = "<group>"; };
-		42CD0DA9147D8EA80000361E /* libvorbisenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisenc.a; path = "../external-deps/oggvorbis/lib/macos/libvorbisenc.a"; sourceTree = "<group>"; };
-		42CD0DAA147D8EA80000361E /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "../external-deps/oggvorbis/lib/macos/libvorbisfile.a"; sourceTree = "<group>"; };
+		42CCD555146EC1EB00353661 /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/macosx/libpng.a"; sourceTree = "<group>"; };
+		42CD0DA6147D8EA80000361E /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "../external-deps/bullet/lib/macosx/libbullet.a"; sourceTree = "<group>"; };
+		42CD0DA7147D8EA80000361E /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "../external-deps/oggvorbis/lib/macosx/libogg.a"; sourceTree = "<group>"; };
+		42CD0DA8147D8EA80000361E /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "../external-deps/oggvorbis/lib/macosx/libvorbis.a"; sourceTree = "<group>"; };
+		42CD0DA9147D8EA80000361E /* libvorbisenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisenc.a; path = "../external-deps/oggvorbis/lib/macosx/libvorbisenc.a"; sourceTree = "<group>"; };
+		42CD0DAA147D8EA80000361E /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "../external-deps/oggvorbis/lib/macosx/libvorbisfile.a"; sourceTree = "<group>"; };
 		42CD0DB1147D8FF50000361E /* Animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Animation.cpp; path = src/Animation.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0DB1147D8FF50000361E /* Animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Animation.cpp; path = src/Animation.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0DB2147D8FF50000361E /* Animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Animation.h; path = src/Animation.h; sourceTree = SOURCE_ROOT; };
 		42CD0DB2147D8FF50000361E /* Animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Animation.h; path = src/Animation.h; sourceTree = SOURCE_ROOT; };
 		42CD0DB3147D8FF50000361E /* AnimationClip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnimationClip.cpp; path = src/AnimationClip.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0DB3147D8FF50000361E /* AnimationClip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnimationClip.cpp; path = src/AnimationClip.cpp; sourceTree = SOURCE_ROOT; };
@@ -441,7 +453,7 @@
 		42CD0DDB147D8FF50000361E /* Frustum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Frustum.h; path = src/Frustum.h; sourceTree = SOURCE_ROOT; };
 		42CD0DDB147D8FF50000361E /* Frustum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Frustum.h; path = src/Frustum.h; sourceTree = SOURCE_ROOT; };
 		42CD0DDC147D8FF50000361E /* Game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Game.cpp; path = src/Game.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0DDC147D8FF50000361E /* Game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Game.cpp; path = src/Game.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0DDD147D8FF50000361E /* Game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Game.h; path = src/Game.h; sourceTree = SOURCE_ROOT; };
 		42CD0DDD147D8FF50000361E /* Game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Game.h; path = src/Game.h; sourceTree = SOURCE_ROOT; };
-		42CD0DDE147D8FF50000361E /* gameplay-main-macos.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "gameplay-main-macos.mm"; path = "src/gameplay-main-macos.mm"; sourceTree = SOURCE_ROOT; };
+		42CD0DDE147D8FF50000361E /* gameplay-main-macosx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "gameplay-main-macosx.mm"; path = "src/gameplay-main-macosx.mm"; sourceTree = SOURCE_ROOT; };
 		42CD0DDF147D8FF50000361E /* gameplay-main-qnx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gameplay-main-qnx.cpp"; path = "src/gameplay-main-qnx.cpp"; sourceTree = SOURCE_ROOT; };
 		42CD0DDF147D8FF50000361E /* gameplay-main-qnx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gameplay-main-qnx.cpp"; path = "src/gameplay-main-qnx.cpp"; sourceTree = SOURCE_ROOT; };
 		42CD0DE0147D8FF50000361E /* gameplay-main-win32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gameplay-main-win32.cpp"; path = "src/gameplay-main-win32.cpp"; sourceTree = SOURCE_ROOT; };
 		42CD0DE0147D8FF50000361E /* gameplay-main-win32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gameplay-main-win32.cpp"; path = "src/gameplay-main-win32.cpp"; sourceTree = SOURCE_ROOT; };
 		42CD0DE1147D8FF50000361E /* gameplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gameplay.h; path = src/gameplay.h; sourceTree = SOURCE_ROOT; };
 		42CD0DE1147D8FF50000361E /* gameplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gameplay.h; path = src/gameplay.h; sourceTree = SOURCE_ROOT; };
@@ -499,7 +511,7 @@
 		42CD0E17147D8FF50000361E /* Plane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plane.h; path = src/Plane.h; sourceTree = SOURCE_ROOT; };
 		42CD0E17147D8FF50000361E /* Plane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plane.h; path = src/Plane.h; sourceTree = SOURCE_ROOT; };
 		42CD0E18147D8FF50000361E /* Plane.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Plane.inl; path = src/Plane.inl; sourceTree = SOURCE_ROOT; };
 		42CD0E18147D8FF50000361E /* Plane.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Plane.inl; path = src/Plane.inl; sourceTree = SOURCE_ROOT; };
 		42CD0E19147D8FF50000361E /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = src/Platform.h; sourceTree = SOURCE_ROOT; };
 		42CD0E19147D8FF50000361E /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = src/Platform.h; sourceTree = SOURCE_ROOT; };
-		42CD0E1A147D8FF50000361E /* PlatformMacOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatformMacOS.mm; path = src/PlatformMacOS.mm; sourceTree = SOURCE_ROOT; };
+		42CD0E1A147D8FF50000361E /* PlatformMacOSX.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatformMacOSX.mm; path = src/PlatformMacOSX.mm; sourceTree = SOURCE_ROOT; };
 		42CD0E1B147D8FF50000361E /* PlatformQNX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformQNX.cpp; path = src/PlatformQNX.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0E1B147D8FF50000361E /* PlatformQNX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformQNX.cpp; path = src/PlatformQNX.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0E1C147D8FF50000361E /* PlatformWin32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformWin32.cpp; path = src/PlatformWin32.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0E1C147D8FF50000361E /* PlatformWin32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformWin32.cpp; path = src/PlatformWin32.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0E1D147D8FF50000361E /* Properties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Properties.cpp; path = src/Properties.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0E1D147D8FF50000361E /* Properties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Properties.cpp; path = src/Properties.cpp; sourceTree = SOURCE_ROOT; };
@@ -541,31 +553,28 @@
 		42CD0E41147D8FF50000361E /* VertexAttributeBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VertexAttributeBinding.h; path = src/VertexAttributeBinding.h; sourceTree = SOURCE_ROOT; };
 		42CD0E41147D8FF50000361E /* VertexAttributeBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VertexAttributeBinding.h; path = src/VertexAttributeBinding.h; sourceTree = SOURCE_ROOT; };
 		42CD0E42147D8FF50000361E /* VertexFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VertexFormat.cpp; path = src/VertexFormat.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0E42147D8FF50000361E /* VertexFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VertexFormat.cpp; path = src/VertexFormat.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0E43147D8FF50000361E /* VertexFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VertexFormat.h; path = src/VertexFormat.h; sourceTree = SOURCE_ROOT; };
 		42CD0E43147D8FF50000361E /* VertexFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VertexFormat.h; path = src/VertexFormat.h; sourceTree = SOURCE_ROOT; };
-		42CD0E44147D8FF50000361E /* Viewport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Viewport.cpp; path = src/Viewport.cpp; sourceTree = SOURCE_ROOT; };
-		42CD0E45147D8FF50000361E /* Viewport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Viewport.h; path = src/Viewport.h; sourceTree = SOURCE_ROOT; };
 		5B04C5CA14BFCFE100EB0071 /* libgameplay.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgameplay.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		5B04C5CA14BFCFE100EB0071 /* libgameplay.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgameplay.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		5B04C5CB14BFD48500EB0071 /* gameplay-main-ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "gameplay-main-ios.mm"; path = "src/gameplay-main-ios.mm"; sourceTree = SOURCE_ROOT; };
 		5B04C5CB14BFD48500EB0071 /* gameplay-main-ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "gameplay-main-ios.mm"; path = "src/gameplay-main-ios.mm"; sourceTree = SOURCE_ROOT; };
 		5B04C5CC14BFD48500EB0071 /* PlatformiOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatformiOS.mm; path = src/PlatformiOS.mm; sourceTree = SOURCE_ROOT; };
 		5B04C5CC14BFD48500EB0071 /* PlatformiOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatformiOS.mm; path = src/PlatformiOS.mm; sourceTree = SOURCE_ROOT; };
-		5B2BC7561512507500D176CD /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/CoreMotion.framework; sourceTree = DEVELOPER_DIR; };
 		5B2BC75D1512514500D176CD /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
 		5B2BC75D1512514500D176CD /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
 		5B2BC75E1512514500D176CD /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
 		5B2BC75E1512514500D176CD /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
 		5B2BC7611512514D00D176CD /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		5B2BC7611512514D00D176CD /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		5B2BC7631512516B00D176CD /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
 		5B2BC7631512516B00D176CD /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
-		5B2BC766151251EB00D176CD /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
-		5B2BC767151251EB00D176CD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
-		5B2BC768151251EB00D176CD /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
-		5B2BC769151251EB00D176CD /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = DEVELOPER_DIR; };
-		5B2BC76A151251EB00D176CD /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
-		5B2BC76B151251EB00D176CD /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
-		5B2BC76C151251EB00D176CD /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
-		5B5ADCE214C22DF900AC6109 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = SDKs/MacOSX10.7.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
-		5B5ADCE414C22E1F00AC6109 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
+		5B2BC768151251EB00D176CD /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
 		5B5DB92D14C25B7B007755DB /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "../external-deps/bullet/lib/ios/i386/libbullet.a"; sourceTree = "<group>"; };
 		5B5DB92D14C25B7B007755DB /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "../external-deps/bullet/lib/ios/i386/libbullet.a"; sourceTree = "<group>"; };
 		5B5DB92F14C25B94007755DB /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/ios/armv7/libpng.a"; sourceTree = "<group>"; };
 		5B5DB92F14C25B94007755DB /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/ios/armv7/libpng.a"; sourceTree = "<group>"; };
 		5B5DB93114C25BA5007755DB /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libogg.a"; sourceTree = "<group>"; };
 		5B5DB93114C25BA5007755DB /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libogg.a"; sourceTree = "<group>"; };
 		5B5DB93214C25BA5007755DB /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbis.a"; sourceTree = "<group>"; };
 		5B5DB93214C25BA5007755DB /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbis.a"; sourceTree = "<group>"; };
 		5B5DB93314C25BA5007755DB /* libvorbisenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisenc.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbisenc.a"; sourceTree = "<group>"; };
 		5B5DB93314C25BA5007755DB /* libvorbisenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisenc.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbisenc.a"; sourceTree = "<group>"; };
 		5B5DB93414C25BA5007755DB /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbisfile.a"; sourceTree = "<group>"; };
 		5B5DB93414C25BA5007755DB /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbisfile.a"; sourceTree = "<group>"; };
+		5BAF201E152F2A6D003E2AC3 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
+		5BAF2020152F2AF0003E2AC3 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2021152F2AF0003E2AC3 /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/CoreMotion.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2022152F2AF0003E2AC3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2023152F2AF0003E2AC3 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2024152F2AF0003E2AC3 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2025152F2AF0003E2AC3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
+		5BAF2026152F2AF0003E2AC3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
 		5BB0823814C6FEB10019975F /* gameplay-main-android.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gameplay-main-android.cpp"; path = "src/gameplay-main-android.cpp"; sourceTree = SOURCE_ROOT; };
 		5BB0823814C6FEB10019975F /* gameplay-main-android.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gameplay-main-android.cpp"; path = "src/gameplay-main-android.cpp"; sourceTree = SOURCE_ROOT; };
 		5BB0823914C6FEB10019975F /* PlatformAndroid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformAndroid.cpp; path = src/PlatformAndroid.cpp; sourceTree = SOURCE_ROOT; };
 		5BB0823914C6FEB10019975F /* PlatformAndroid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformAndroid.cpp; path = src/PlatformAndroid.cpp; sourceTree = SOURCE_ROOT; };
 		5BB0823C14C6FEC40019975F /* Mouse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Mouse.h; path = src/Mouse.h; sourceTree = SOURCE_ROOT; };
 		5BB0823C14C6FEC40019975F /* Mouse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Mouse.h; path = src/Mouse.h; sourceTree = SOURCE_ROOT; };
@@ -582,7 +591,6 @@
 		5BD5263B150F822A004C9099 /* Container.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Container.h; path = src/Container.h; sourceTree = SOURCE_ROOT; };
 		5BD5263B150F822A004C9099 /* Container.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Container.h; path = src/Container.h; sourceTree = SOURCE_ROOT; };
 		5BD5263C150F822A004C9099 /* Control.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Control.cpp; path = src/Control.cpp; sourceTree = SOURCE_ROOT; };
 		5BD5263C150F822A004C9099 /* Control.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Control.cpp; path = src/Control.cpp; sourceTree = SOURCE_ROOT; };
 		5BD5263D150F822A004C9099 /* Control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Control.h; path = src/Control.h; sourceTree = SOURCE_ROOT; };
 		5BD5263D150F822A004C9099 /* Control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Control.h; path = src/Control.h; sourceTree = SOURCE_ROOT; };
-		5BD5263E150F822A004C9099 /* FlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlowLayout.h; path = src/FlowLayout.h; sourceTree = SOURCE_ROOT; };
 		5BD5263F150F822A004C9099 /* Form.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Form.cpp; path = src/Form.cpp; sourceTree = SOURCE_ROOT; };
 		5BD5263F150F822A004C9099 /* Form.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Form.cpp; path = src/Form.cpp; sourceTree = SOURCE_ROOT; };
 		5BD52640150F822A004C9099 /* Form.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Form.h; path = src/Form.h; sourceTree = SOURCE_ROOT; };
 		5BD52640150F822A004C9099 /* Form.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Form.h; path = src/Form.h; sourceTree = SOURCE_ROOT; };
 		5BD52641150F822A004C9099 /* Label.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Label.cpp; path = src/Label.cpp; sourceTree = SOURCE_ROOT; };
 		5BD52641150F822A004C9099 /* Label.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Label.cpp; path = src/Label.cpp; sourceTree = SOURCE_ROOT; };
@@ -629,14 +637,14 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
-				5B2BC76D151251EB00D176CD /* CoreGraphics.framework in Frameworks */,
-				5B2BC76E151251EB00D176CD /* Foundation.framework in Frameworks */,
-				5B2BC76F151251EB00D176CD /* libz.dylib in Frameworks */,
-				5B2BC770151251EB00D176CD /* OpenAL.framework in Frameworks */,
-				5B2BC771151251EB00D176CD /* OpenGLES.framework in Frameworks */,
-				5B2BC772151251EB00D176CD /* QuartzCore.framework in Frameworks */,
-				5B2BC773151251EB00D176CD /* UIKit.framework in Frameworks */,
-				5B2BC765151251EB00D176CD /* CoreMotion.framework in Frameworks */,
+				5BAF2027152F2AF0003E2AC3 /* CoreGraphics.framework in Frameworks */,
+				5BAF2028152F2AF0003E2AC3 /* CoreMotion.framework in Frameworks */,
+				5BAF2029152F2AF0003E2AC3 /* Foundation.framework in Frameworks */,
+				5BAF202A152F2AF0003E2AC3 /* OpenAL.framework in Frameworks */,
+				5BAF202B152F2AF0003E2AC3 /* OpenGLES.framework in Frameworks */,
+				5BAF202C152F2AF0003E2AC3 /* QuartzCore.framework in Frameworks */,
+				5BAF202D152F2AF0003E2AC3 /* UIKit.framework in Frameworks */,
+				5BAF201F152F2A6D003E2AC3 /* libz.dylib in Frameworks */,
 				5B04C57514BFCFE100EB0071 /* libbullet.a in Frameworks */,
 				5B04C57514BFCFE100EB0071 /* libbullet.a in Frameworks */,
 				5B04C57614BFCFE100EB0071 /* libogg.a in Frameworks */,
 				5B04C57614BFCFE100EB0071 /* libogg.a in Frameworks */,
 				5B04C57714BFCFE100EB0071 /* libvorbis.a in Frameworks */,
 				5B04C57714BFCFE100EB0071 /* libvorbis.a in Frameworks */,
@@ -720,7 +728,6 @@
 				42CD0DD3147D8FF50000361E /* Effect.h */,
 				42CD0DD3147D8FF50000361E /* Effect.h */,
 				42CD0DD4147D8FF50000361E /* FileSystem.cpp */,
 				42CD0DD4147D8FF50000361E /* FileSystem.cpp */,
 				42CD0DD5147D8FF50000361E /* FileSystem.h */,
 				42CD0DD5147D8FF50000361E /* FileSystem.h */,
-				5BD5263E150F822A004C9099 /* FlowLayout.h */,
 				42CD0DD6147D8FF50000361E /* Font.cpp */,
 				42CD0DD6147D8FF50000361E /* Font.cpp */,
 				42CD0DD7147D8FF50000361E /* Font.h */,
 				42CD0DD7147D8FF50000361E /* Font.h */,
 				5BD5263F150F822A004C9099 /* Form.cpp */,
 				5BD5263F150F822A004C9099 /* Form.cpp */,
@@ -736,7 +743,7 @@
 				42CD0DE1147D8FF50000361E /* gameplay.h */,
 				42CD0DE1147D8FF50000361E /* gameplay.h */,
 				5BB0823814C6FEB10019975F /* gameplay-main-android.cpp */,
 				5BB0823814C6FEB10019975F /* gameplay-main-android.cpp */,
 				42CD0DE0147D8FF50000361E /* gameplay-main-win32.cpp */,
 				42CD0DE0147D8FF50000361E /* gameplay-main-win32.cpp */,
-				42CD0DDE147D8FF50000361E /* gameplay-main-macos.mm */,
+				42CD0DDE147D8FF50000361E /* gameplay-main-macosx.mm */,
 				5B04C5CB14BFD48500EB0071 /* gameplay-main-ios.mm */,
 				5B04C5CB14BFD48500EB0071 /* gameplay-main-ios.mm */,
 				42CD0DDF147D8FF50000361E /* gameplay-main-qnx.cpp */,
 				42CD0DDF147D8FF50000361E /* gameplay-main-qnx.cpp */,
 				4208DEE614A4079F00D3C511 /* Image.cpp */,
 				4208DEE614A4079F00D3C511 /* Image.cpp */,
@@ -747,6 +754,7 @@
 				4208DEEB14A407B900D3C511 /* Keyboard.h */,
 				4208DEEB14A407B900D3C511 /* Keyboard.h */,
 				5BD52641150F822A004C9099 /* Label.cpp */,
 				5BD52641150F822A004C9099 /* Label.cpp */,
 				5BD52642150F822A004C9099 /* Label.h */,
 				5BD52642150F822A004C9099 /* Label.h */,
+				4271C08D15337C8200B89DA7 /* Layout.cpp */,
 				5BD52643150F822A004C9099 /* Layout.h */,
 				5BD52643150F822A004C9099 /* Layout.h */,
 				42CD0DE6147D8FF50000361E /* Light.cpp */,
 				42CD0DE6147D8FF50000361E /* Light.cpp */,
 				42CD0DE7147D8FF50000361E /* Light.h */,
 				42CD0DE7147D8FF50000361E /* Light.h */,
@@ -784,6 +792,8 @@
 				5BD5266C150F8257004C9099 /* PhysicsCharacter.h */,
 				5BD5266C150F8257004C9099 /* PhysicsCharacter.h */,
 				5BD5266D150F8257004C9099 /* PhysicsCollisionObject.cpp */,
 				5BD5266D150F8257004C9099 /* PhysicsCollisionObject.cpp */,
 				5BD5266E150F8258004C9099 /* PhysicsCollisionObject.h */,
 				5BD5266E150F8258004C9099 /* PhysicsCollisionObject.h */,
+				42554E9F152BC35C000ED910 /* PhysicsCollisionShape.cpp */,
+				42554EA0152BC35C000ED910 /* PhysicsCollisionShape.h */,
 				42CD0DFF147D8FF50000361E /* PhysicsConstraint.cpp */,
 				42CD0DFF147D8FF50000361E /* PhysicsConstraint.cpp */,
 				42CD0E00147D8FF50000361E /* PhysicsConstraint.h */,
 				42CD0E00147D8FF50000361E /* PhysicsConstraint.h */,
 				42CD0E01147D8FF50000361E /* PhysicsConstraint.inl */,
 				42CD0E01147D8FF50000361E /* PhysicsConstraint.inl */,
@@ -812,7 +822,7 @@
 				42CD0E19147D8FF50000361E /* Platform.h */,
 				42CD0E19147D8FF50000361E /* Platform.h */,
 				5BB0823914C6FEB10019975F /* PlatformAndroid.cpp */,
 				5BB0823914C6FEB10019975F /* PlatformAndroid.cpp */,
 				42CD0E1C147D8FF50000361E /* PlatformWin32.cpp */,
 				42CD0E1C147D8FF50000361E /* PlatformWin32.cpp */,
-				42CD0E1A147D8FF50000361E /* PlatformMacOS.mm */,
+				42CD0E1A147D8FF50000361E /* PlatformMacOSX.mm */,
 				5B04C5CC14BFD48500EB0071 /* PlatformiOS.mm */,
 				5B04C5CC14BFD48500EB0071 /* PlatformiOS.mm */,
 				42CD0E1B147D8FF50000361E /* PlatformQNX.cpp */,
 				42CD0E1B147D8FF50000361E /* PlatformQNX.cpp */,
 				42CD0E1D147D8FF50000361E /* Properties.cpp */,
 				42CD0E1D147D8FF50000361E /* Properties.cpp */,
@@ -837,6 +847,7 @@
 				42CD0E2E147D8FF50000361E /* Scene.h */,
 				42CD0E2E147D8FF50000361E /* Scene.h */,
 				428390971489D6E800E2B2F5 /* SceneLoader.cpp */,
 				428390971489D6E800E2B2F5 /* SceneLoader.cpp */,
 				428390981489D6E800E2B2F5 /* SceneLoader.h */,
 				428390981489D6E800E2B2F5 /* SceneLoader.h */,
+				4251B12E152D049B002F6199 /* ScreenDisplayer.h */,
 				5BD52646150F822A004C9099 /* Slider.cpp */,
 				5BD52646150F822A004C9099 /* Slider.cpp */,
 				5BD52647150F822A004C9099 /* Slider.h */,
 				5BD52647150F822A004C9099 /* Slider.h */,
 				42CD0E2F147D8FF50000361E /* SpriteBatch.cpp */,
 				42CD0E2F147D8FF50000361E /* SpriteBatch.cpp */,
@@ -850,6 +861,8 @@
 				5BD5264C150F822A004C9099 /* TimeListener.h */,
 				5BD5264C150F822A004C9099 /* TimeListener.h */,
 				5BD5264A150F822A004C9099 /* Theme.cpp */,
 				5BD5264A150F822A004C9099 /* Theme.cpp */,
 				5BD5264B150F822A004C9099 /* Theme.h */,
 				5BD5264B150F822A004C9099 /* Theme.h */,
+				4251B12F152D049B002F6199 /* ThemeStyle.cpp */,
+				4251B130152D049B002F6199 /* ThemeStyle.h */,
 				4208DEED14A407D500D3C511 /* Touch.h */,
 				4208DEED14A407D500D3C511 /* Touch.h */,
 				42CD0E35147D8FF50000361E /* Transform.cpp */,
 				42CD0E35147D8FF50000361E /* Transform.cpp */,
 				42CD0E36147D8FF50000361E /* Transform.h */,
 				42CD0E36147D8FF50000361E /* Transform.h */,
@@ -868,8 +881,6 @@
 				42CD0E43147D8FF50000361E /* VertexFormat.h */,
 				42CD0E43147D8FF50000361E /* VertexFormat.h */,
 				5BD5264D150F822A004C9099 /* VerticalLayout.cpp */,
 				5BD5264D150F822A004C9099 /* VerticalLayout.cpp */,
 				5BD5264E150F822A004C9099 /* VerticalLayout.h */,
 				5BD5264E150F822A004C9099 /* VerticalLayout.h */,
-				42CD0E44147D8FF50000361E /* Viewport.cpp */,
-				42CD0E45147D8FF50000361E /* Viewport.h */,
 			);
 			);
 			name = src;
 			name = src;
 			path = gameplay;
 			path = gameplay;
@@ -902,14 +913,14 @@
 		5B04C5FD14BFE52300EB0071 /* iOS */ = {
 		5B04C5FD14BFE52300EB0071 /* iOS */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				5B2BC766151251EB00D176CD /* CoreGraphics.framework */,
-				5B2BC767151251EB00D176CD /* Foundation.framework */,
-				5B2BC768151251EB00D176CD /* libz.dylib */,
-				5B2BC769151251EB00D176CD /* OpenAL.framework */,
-				5B2BC76A151251EB00D176CD /* OpenGLES.framework */,
-				5B2BC76B151251EB00D176CD /* QuartzCore.framework */,
-				5B2BC76C151251EB00D176CD /* UIKit.framework */,
-				5B2BC7561512507500D176CD /* CoreMotion.framework */,
+				5BAF201E152F2A6D003E2AC3 /* libz.dylib */,
+				5BAF2020152F2AF0003E2AC3 /* CoreGraphics.framework */,
+				5BAF2021152F2AF0003E2AC3 /* CoreMotion.framework */,
+				5BAF2022152F2AF0003E2AC3 /* Foundation.framework */,
+				5BAF2023152F2AF0003E2AC3 /* OpenAL.framework */,
+				5BAF2024152F2AF0003E2AC3 /* OpenGLES.framework */,
+				5BAF2025152F2AF0003E2AC3 /* QuartzCore.framework */,
+				5BAF2026152F2AF0003E2AC3 /* UIKit.framework */,
 			);
 			);
 			name = iOS;
 			name = iOS;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -917,7 +928,6 @@
 		5B04C5FE14BFE52F00EB0071 /* MacOSX */ = {
 		5B04C5FE14BFE52F00EB0071 /* MacOSX */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				5B2BC7631512516B00D176CD /* libz.dylib */,
 				5B2BC7611512514D00D176CD /* QuartzCore.framework */,
 				5B2BC7611512514D00D176CD /* QuartzCore.framework */,
 				5B2BC75D1512514500D176CD /* OpenAL.framework */,
 				5B2BC75D1512514500D176CD /* OpenAL.framework */,
 				5B2BC75E1512514500D176CD /* OpenGL.framework */,
 				5B2BC75E1512514500D176CD /* OpenGL.framework */,
@@ -935,7 +945,7 @@
 				5B5DB93414C25BA5007755DB /* libvorbisfile.a */,
 				5B5DB93414C25BA5007755DB /* libvorbisfile.a */,
 				5B5DB92F14C25B94007755DB /* libpng.a */,
 				5B5DB92F14C25B94007755DB /* libpng.a */,
 				5B5DB92D14C25B7B007755DB /* libbullet.a */,
 				5B5DB92D14C25B7B007755DB /* libbullet.a */,
-				5B5ADCE414C22E1F00AC6109 /* libz.dylib */,
+				5B2BC768151251EB00D176CD /* libz.dylib */,
 			);
 			);
 			name = iOS;
 			name = iOS;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -943,7 +953,7 @@
 		5B5ADCE114C22DC700AC6109 /* MacOSX */ = {
 		5B5ADCE114C22DC700AC6109 /* MacOSX */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				5B5ADCE214C22DF900AC6109 /* libz.dylib */,
+				5B2BC7631512516B00D176CD /* libz.dylib */,
 			);
 			);
 			name = MacOSX;
 			name = MacOSX;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -1019,7 +1029,6 @@
 				42CD0EC6147D8FF60000361E /* Vector4.h in Headers */,
 				42CD0EC6147D8FF60000361E /* Vector4.h in Headers */,
 				42CD0EC8147D8FF60000361E /* VertexAttributeBinding.h in Headers */,
 				42CD0EC8147D8FF60000361E /* VertexAttributeBinding.h in Headers */,
 				42CD0ECA147D8FF60000361E /* VertexFormat.h in Headers */,
 				42CD0ECA147D8FF60000361E /* VertexFormat.h in Headers */,
-				42CD0ECC147D8FF60000361E /* Viewport.h in Headers */,
 				4283909A1489D6E800E2B2F5 /* SceneLoader.h in Headers */,
 				4283909A1489D6E800E2B2F5 /* SceneLoader.h in Headers */,
 				4208DEEA14A4079F00D3C511 /* Image.h in Headers */,
 				4208DEEA14A4079F00D3C511 /* Image.h in Headers */,
 				4208DEEC14A407B900D3C511 /* Keyboard.h in Headers */,
 				4208DEEC14A407B900D3C511 /* Keyboard.h in Headers */,
@@ -1031,7 +1040,6 @@
 				5BD52654150F822A004C9099 /* CheckBox.h in Headers */,
 				5BD52654150F822A004C9099 /* CheckBox.h in Headers */,
 				5BD52656150F822A004C9099 /* Container.h in Headers */,
 				5BD52656150F822A004C9099 /* Container.h in Headers */,
 				5BD52658150F822A004C9099 /* Control.h in Headers */,
 				5BD52658150F822A004C9099 /* Control.h in Headers */,
-				5BD52659150F822A004C9099 /* FlowLayout.h in Headers */,
 				5BD5265B150F822A004C9099 /* Form.h in Headers */,
 				5BD5265B150F822A004C9099 /* Form.h in Headers */,
 				5BD5265D150F822A004C9099 /* Label.h in Headers */,
 				5BD5265D150F822A004C9099 /* Label.h in Headers */,
 				5BD5265E150F822A004C9099 /* Layout.h in Headers */,
 				5BD5265E150F822A004C9099 /* Layout.h in Headers */,
@@ -1044,6 +1052,9 @@
 				5BD52671150F8258004C9099 /* PhysicsCharacter.h in Headers */,
 				5BD52671150F8258004C9099 /* PhysicsCharacter.h in Headers */,
 				5BD52675150F8258004C9099 /* PhysicsCollisionObject.h in Headers */,
 				5BD52675150F8258004C9099 /* PhysicsCollisionObject.h in Headers */,
 				5BBE14401513E400003FB362 /* PhysicsGhostObject.h in Headers */,
 				5BBE14401513E400003FB362 /* PhysicsGhostObject.h in Headers */,
+				42554EA3152BC35C000ED910 /* PhysicsCollisionShape.h in Headers */,
+				4251B131152D049B002F6199 /* ScreenDisplayer.h in Headers */,
+				4251B135152D049B002F6199 /* ThemeStyle.h in Headers */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -1115,7 +1126,6 @@
 				5B04C5BE14BFCFE100EB0071 /* Vector4.h in Headers */,
 				5B04C5BE14BFCFE100EB0071 /* Vector4.h in Headers */,
 				5B04C5BF14BFCFE100EB0071 /* VertexAttributeBinding.h in Headers */,
 				5B04C5BF14BFCFE100EB0071 /* VertexAttributeBinding.h in Headers */,
 				5B04C5C014BFCFE100EB0071 /* VertexFormat.h in Headers */,
 				5B04C5C014BFCFE100EB0071 /* VertexFormat.h in Headers */,
-				5B04C5C114BFCFE100EB0071 /* Viewport.h in Headers */,
 				5B04C5C214BFCFE100EB0071 /* SceneLoader.h in Headers */,
 				5B04C5C214BFCFE100EB0071 /* SceneLoader.h in Headers */,
 				5B04C5C314BFCFE100EB0071 /* Image.h in Headers */,
 				5B04C5C314BFCFE100EB0071 /* Image.h in Headers */,
 				5B04C5C414BFCFE100EB0071 /* Keyboard.h in Headers */,
 				5B04C5C414BFCFE100EB0071 /* Keyboard.h in Headers */,
@@ -1129,7 +1139,6 @@
 				5BC4E744150F843D00CBE1C0 /* CheckBox.h in Headers */,
 				5BC4E744150F843D00CBE1C0 /* CheckBox.h in Headers */,
 				5BC4E746150F843D00CBE1C0 /* Container.h in Headers */,
 				5BC4E746150F843D00CBE1C0 /* Container.h in Headers */,
 				5BC4E748150F843D00CBE1C0 /* Control.h in Headers */,
 				5BC4E748150F843D00CBE1C0 /* Control.h in Headers */,
-				5BC4E749150F843D00CBE1C0 /* FlowLayout.h in Headers */,
 				5BC4E74B150F843D00CBE1C0 /* Form.h in Headers */,
 				5BC4E74B150F843D00CBE1C0 /* Form.h in Headers */,
 				5BC4E74D150F843D00CBE1C0 /* Label.h in Headers */,
 				5BC4E74D150F843D00CBE1C0 /* Label.h in Headers */,
 				5BC4E74E150F843D00CBE1C0 /* Layout.h in Headers */,
 				5BC4E74E150F843D00CBE1C0 /* Layout.h in Headers */,
@@ -1139,15 +1148,18 @@
 				5BC4E756150F843D00CBE1C0 /* Theme.h in Headers */,
 				5BC4E756150F843D00CBE1C0 /* Theme.h in Headers */,
 				5BC4E758150F843D00CBE1C0 /* VerticalLayout.h in Headers */,
 				5BC4E758150F843D00CBE1C0 /* VerticalLayout.h in Headers */,
 				5BBE14411513E400003FB362 /* PhysicsGhostObject.h in Headers */,
 				5BBE14411513E400003FB362 /* PhysicsGhostObject.h in Headers */,
+				42554EA4152BC35C000ED910 /* PhysicsCollisionShape.h in Headers */,
+				4251B132152D049B002F6199 /* ScreenDisplayer.h in Headers */,
+				4251B136152D049B002F6199 /* ThemeStyle.h in Headers */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
 /* End PBXHeadersBuildPhase section */
 /* End PBXHeadersBuildPhase section */
 
 
 /* Begin PBXNativeTarget section */
 /* Begin PBXNativeTarget section */
-		4234D99914686C52003031B3 /* gameplay-macos */ = {
+		4234D99914686C52003031B3 /* gameplay-macosx */ = {
 			isa = PBXNativeTarget;
 			isa = PBXNativeTarget;
-			buildConfigurationList = 4234D9AB14686C52003031B3 /* Build configuration list for PBXNativeTarget "gameplay-macos" */;
+			buildConfigurationList = 4234D9AB14686C52003031B3 /* Build configuration list for PBXNativeTarget "gameplay-macosx" */;
 			buildPhases = (
 			buildPhases = (
 				4234D99614686C52003031B3 /* Sources */,
 				4234D99614686C52003031B3 /* Sources */,
 				4234D99714686C52003031B3 /* Frameworks */,
 				4234D99714686C52003031B3 /* Frameworks */,
@@ -1157,7 +1169,7 @@
 			);
 			);
 			dependencies = (
 			dependencies = (
 			);
 			);
-			name = "gameplay-macos";
+			name = "gameplay-macosx";
 			productName = gameplay;
 			productName = gameplay;
 			productReference = 4234D99A14686C52003031B3 /* libgameplay.a */;
 			productReference = 4234D99A14686C52003031B3 /* libgameplay.a */;
 			productType = "com.apple.product-type.library.static";
 			productType = "com.apple.product-type.library.static";
@@ -1199,7 +1211,7 @@
 			projectDirPath = "";
 			projectDirPath = "";
 			projectRoot = "";
 			projectRoot = "";
 			targets = (
 			targets = (
-				4234D99914686C52003031B3 /* gameplay-macos */,
+				4234D99914686C52003031B3 /* gameplay-macosx */,
 				5B04C52B14BFCFE100EB0071 /* gameplay-ios */,
 				5B04C52B14BFCFE100EB0071 /* gameplay-ios */,
 			);
 			);
 		};
 		};
@@ -1231,7 +1243,7 @@
 				42CD0E6B147D8FF60000361E /* FrameBuffer.cpp in Sources */,
 				42CD0E6B147D8FF60000361E /* FrameBuffer.cpp in Sources */,
 				42CD0E6D147D8FF60000361E /* Frustum.cpp in Sources */,
 				42CD0E6D147D8FF60000361E /* Frustum.cpp in Sources */,
 				42CD0E6F147D8FF60000361E /* Game.cpp in Sources */,
 				42CD0E6F147D8FF60000361E /* Game.cpp in Sources */,
-				42CD0E71147D8FF60000361E /* gameplay-main-macos.mm in Sources */,
+				42CD0E71147D8FF60000361E /* gameplay-main-macosx.mm in Sources */,
 				42CD0E77147D8FF60000361E /* Joint.cpp in Sources */,
 				42CD0E77147D8FF60000361E /* Joint.cpp in Sources */,
 				42CD0E79147D8FF60000361E /* Light.cpp in Sources */,
 				42CD0E79147D8FF60000361E /* Light.cpp in Sources */,
 				42CD0E7B147D8FF60000361E /* Material.cpp in Sources */,
 				42CD0E7B147D8FF60000361E /* Material.cpp in Sources */,
@@ -1255,7 +1267,7 @@
 				42CD0E9F147D8FF60000361E /* PhysicsSocketConstraint.cpp in Sources */,
 				42CD0E9F147D8FF60000361E /* PhysicsSocketConstraint.cpp in Sources */,
 				42CD0EA1147D8FF60000361E /* PhysicsSpringConstraint.cpp in Sources */,
 				42CD0EA1147D8FF60000361E /* PhysicsSpringConstraint.cpp in Sources */,
 				42CD0EA3147D8FF60000361E /* Plane.cpp in Sources */,
 				42CD0EA3147D8FF60000361E /* Plane.cpp in Sources */,
-				42CD0EA6147D8FF60000361E /* PlatformMacOS.mm in Sources */,
+				42CD0EA6147D8FF60000361E /* PlatformMacOSX.mm in Sources */,
 				42CD0EA9147D8FF60000361E /* Properties.cpp in Sources */,
 				42CD0EA9147D8FF60000361E /* Properties.cpp in Sources */,
 				42CD0EAB147D8FF60000361E /* Quaternion.cpp in Sources */,
 				42CD0EAB147D8FF60000361E /* Quaternion.cpp in Sources */,
 				42CD0EAD147D8FF60000361E /* Ray.cpp in Sources */,
 				42CD0EAD147D8FF60000361E /* Ray.cpp in Sources */,
@@ -1273,7 +1285,6 @@
 				42CD0EC5147D8FF60000361E /* Vector4.cpp in Sources */,
 				42CD0EC5147D8FF60000361E /* Vector4.cpp in Sources */,
 				42CD0EC7147D8FF60000361E /* VertexAttributeBinding.cpp in Sources */,
 				42CD0EC7147D8FF60000361E /* VertexAttributeBinding.cpp in Sources */,
 				42CD0EC9147D8FF60000361E /* VertexFormat.cpp in Sources */,
 				42CD0EC9147D8FF60000361E /* VertexFormat.cpp in Sources */,
-				42CD0ECB147D8FF60000361E /* Viewport.cpp in Sources */,
 				428390991489D6E800E2B2F5 /* SceneLoader.cpp in Sources */,
 				428390991489D6E800E2B2F5 /* SceneLoader.cpp in Sources */,
 				4208DEE914A4079F00D3C511 /* Image.cpp in Sources */,
 				4208DEE914A4079F00D3C511 /* Image.cpp in Sources */,
 				4201819014A41B18008C3F56 /* MeshBatch.cpp in Sources */,
 				4201819014A41B18008C3F56 /* MeshBatch.cpp in Sources */,
@@ -1292,6 +1303,9 @@
 				5BD5266F150F8258004C9099 /* PhysicsCharacter.cpp in Sources */,
 				5BD5266F150F8258004C9099 /* PhysicsCharacter.cpp in Sources */,
 				5BD52673150F8258004C9099 /* PhysicsCollisionObject.cpp in Sources */,
 				5BD52673150F8258004C9099 /* PhysicsCollisionObject.cpp in Sources */,
 				5BBE143E1513E400003FB362 /* PhysicsGhostObject.cpp in Sources */,
 				5BBE143E1513E400003FB362 /* PhysicsGhostObject.cpp in Sources */,
+				42554EA1152BC35C000ED910 /* PhysicsCollisionShape.cpp in Sources */,
+				4251B133152D049B002F6199 /* ThemeStyle.cpp in Sources */,
+				4271C08E15337C8200B89DA7 /* Layout.cpp in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -1360,7 +1374,6 @@
 				5B04C56D14BFCFE100EB0071 /* Vector4.cpp in Sources */,
 				5B04C56D14BFCFE100EB0071 /* Vector4.cpp in Sources */,
 				5B04C56E14BFCFE100EB0071 /* VertexAttributeBinding.cpp in Sources */,
 				5B04C56E14BFCFE100EB0071 /* VertexAttributeBinding.cpp in Sources */,
 				5B04C56F14BFCFE100EB0071 /* VertexFormat.cpp in Sources */,
 				5B04C56F14BFCFE100EB0071 /* VertexFormat.cpp in Sources */,
-				5B04C57014BFCFE100EB0071 /* Viewport.cpp in Sources */,
 				5B04C57114BFCFE100EB0071 /* SceneLoader.cpp in Sources */,
 				5B04C57114BFCFE100EB0071 /* SceneLoader.cpp in Sources */,
 				5B04C57214BFCFE100EB0071 /* Image.cpp in Sources */,
 				5B04C57214BFCFE100EB0071 /* Image.cpp in Sources */,
 				5B04C57314BFCFE100EB0071 /* MeshBatch.cpp in Sources */,
 				5B04C57314BFCFE100EB0071 /* MeshBatch.cpp in Sources */,
@@ -1381,6 +1394,9 @@
 				5BC4E755150F843D00CBE1C0 /* Theme.cpp in Sources */,
 				5BC4E755150F843D00CBE1C0 /* Theme.cpp in Sources */,
 				5BC4E757150F843D00CBE1C0 /* VerticalLayout.cpp in Sources */,
 				5BC4E757150F843D00CBE1C0 /* VerticalLayout.cpp in Sources */,
 				5BBE143F1513E400003FB362 /* PhysicsGhostObject.cpp in Sources */,
 				5BBE143F1513E400003FB362 /* PhysicsGhostObject.cpp in Sources */,
+				42554EA2152BC35C000ED910 /* PhysicsCollisionShape.cpp in Sources */,
+				4251B134152D049B002F6199 /* ThemeStyle.cpp in Sources */,
+				4271C08F15337C8200B89DA7 /* Layout.cpp in Sources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -1390,6 +1406,7 @@
 		4234D99114686BB6003031B3 /* Debug */ = {
 		4234D99114686BB6003031B3 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
 				SDKROOT = macosx;
 				SUPPORTED_PLATFORMS = "iphonesimulator macosx iphoneos";
 				SUPPORTED_PLATFORMS = "iphonesimulator macosx iphoneos";
 				VALID_ARCHS = "armv7 armv6 i386 x86_64";
 				VALID_ARCHS = "armv7 armv6 i386 x86_64";
@@ -1438,12 +1455,12 @@
 				);
 				);
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
-					"\"$(SRCROOT)/../external-deps/libpng/lib/macos\"",
-					"\"$(SRCROOT)/../external-deps/bullet/lib/macos\"",
-					"\"$(SRCROOT)/../external-deps/oggvorbis/lib/macos\"",
+					"\"$(SRCROOT)/../external-deps/libpng/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/bullet/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/oggvorbis/lib/macosx\"",
 				);
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
-				ONLY_ACTIVE_ARCH = NO;
+				ONLY_ACTIVE_ARCH = YES;
 				PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
 				PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
 				PRODUCT_NAME = gameplay;
 				PRODUCT_NAME = gameplay;
 				SHARED_PRECOMPS_DIR = "";
 				SHARED_PRECOMPS_DIR = "";
@@ -1480,9 +1497,9 @@
 				);
 				);
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
-					"\"$(SRCROOT)/../external-deps/libpng/lib/macos\"",
-					"\"$(SRCROOT)/../external-deps/bullet/lib/macos\"",
-					"\"$(SRCROOT)/../external-deps/oggvorbis/lib/macos\"",
+					"\"$(SRCROOT)/../external-deps/libpng/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/bullet/lib/macosx\"",
+					"\"$(SRCROOT)/../external-deps/oggvorbis/lib/macosx\"",
 				);
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
 				PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
 				PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
@@ -1599,7 +1616,7 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 			defaultConfigurationName = Release;
 		};
 		};
-		4234D9AB14686C52003031B3 /* Build configuration list for PBXNativeTarget "gameplay-macos" */ = {
+		4234D9AB14686C52003031B3 /* Build configuration list for PBXNativeTarget "gameplay-macosx" */ = {
 			isa = XCConfigurationList;
 			isa = XCConfigurationList;
 			buildConfigurations = (
 			buildConfigurations = (
 				4234D9A914686C52003031B3 /* Debug */,
 				4234D9A914686C52003031B3 /* Debug */,

BIN
gameplay/res/icon_black.psd


BIN
gameplay/res/icon_black128.ico


BIN
gameplay/res/icon_black16.ico


BIN
gameplay/res/icon_black32.ico


BIN
gameplay/res/icon_black64.ico


BIN
gameplay/res/icon_black_transparent.psd


BIN
gameplay/res/icon_black_transparent128.ico


BIN
gameplay/res/icon_black_transparent16.ico


BIN
gameplay/res/icon_black_transparent32.ico


BIN
gameplay/res/icon_black_transparent64.ico


BIN
gameplay/res/icon_white_transparent.psd


BIN
gameplay/res/icon_white_transparent128.ico


BIN
gameplay/res/icon_white_transparent16.ico


BIN
gameplay/res/icon_white_transparent32.ico


BIN
gameplay/res/icon_white_transparent64.ico


Fichier diff supprimé car celui-ci est trop grand
+ 27 - 0
gameplay/res/logo.ai


+ 7 - 0
gameplay/res/shaders/bumped-specular.fsh

@@ -8,6 +8,9 @@ uniform vec3 u_ambientColor;                // Ambient color.
 uniform float u_specularExponent;           // Specular exponent or shininess property.
 uniform float u_specularExponent;           // Specular exponent or shininess property.
 uniform sampler2D u_diffuseTexture;         // Diffuse texture.
 uniform sampler2D u_diffuseTexture;         // Diffuse texture.
 uniform sampler2D u_normalMapTexture;       // Normal map texture.
 uniform sampler2D u_normalMapTexture;       // Normal map texture.
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec2 v_texCoord;                    // Texture Coordinate.
 varying vec2 v_texCoord;                    // Texture Coordinate.
@@ -114,4 +117,8 @@ void main()
     // Light the pixel
     // Light the pixel
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
     gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/bumped.fsh

@@ -7,6 +7,9 @@ uniform vec3 u_lightColor;                   // Light color.
 uniform vec3 u_ambientColor;                 // Ambient color.
 uniform vec3 u_ambientColor;                 // Ambient color.
 uniform sampler2D u_diffuseTexture;          // Diffuse texture.
 uniform sampler2D u_diffuseTexture;          // Diffuse texture.
 uniform sampler2D u_normalMapTexture;        // Normal map texture.
 uniform sampler2D u_normalMapTexture;        // Normal map texture.
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec2 v_texCoord;                     // Texture Coordinate.
 varying vec2 v_texCoord;                     // Texture Coordinate.
@@ -103,4 +106,8 @@ void main()
     // Light the pixel
     // Light the pixel
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.rgb = _ambientColor + _diffuseColor;
     gl_FragColor.rgb = _ambientColor + _diffuseColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/colored-specular.fsh

@@ -9,6 +9,9 @@ uniform float u_specularExponent;               // Specular exponent or shinines
 #if !defined(VERTEX_COLOR)
 #if !defined(VERTEX_COLOR)
 uniform vec4 u_diffuseColor;                    // Diffuse color
 uniform vec4 u_diffuseColor;                    // Diffuse color
 #endif
 #endif
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec3 v_normalVector;                    // NormalVector in view space
 varying vec3 v_normalVector;                    // NormalVector in view space
@@ -122,4 +125,8 @@ void main()
     // Light the pixel
     // Light the pixel
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
     gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/colored.fsh

@@ -6,6 +6,9 @@ precision highp float;
 uniform vec3 u_lightColor;                      // Light color
 uniform vec3 u_lightColor;                      // Light color
 uniform vec3 u_ambientColor;                    // Ambient color
 uniform vec3 u_ambientColor;                    // Ambient color
 uniform vec4 u_diffuseColor;                    // Diffuse color
 uniform vec4 u_diffuseColor;                    // Diffuse color
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec3 v_normalVector;                    // NormalVector in view space.
 varying vec3 v_normalVector;                    // NormalVector in view space.
@@ -101,4 +104,8 @@ void main()
     // Light the pixel
     // Light the pixel
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.rgb = _ambientColor + _diffuseColor;
     gl_FragColor.rgb = _ambientColor + _diffuseColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/diffuse-specular.fsh

@@ -7,6 +7,9 @@ uniform vec3 u_lightColor;                      // Light color
 uniform vec3 u_ambientColor;                    // Ambient color
 uniform vec3 u_ambientColor;                    // Ambient color
 uniform float u_specularExponent;               // Specular exponent or shininess property.
 uniform float u_specularExponent;               // Specular exponent or shininess property.
 uniform sampler2D u_diffuseTexture;             // Diffuse texture.
 uniform sampler2D u_diffuseTexture;             // Diffuse texture.
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec3 v_normalVector;                    // NormalVector in view space.
 varying vec3 v_normalVector;                    // NormalVector in view space.
@@ -114,4 +117,8 @@ void main()
     // Light the pixel
     // Light the pixel
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
     gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/diffuse.fsh

@@ -6,6 +6,9 @@ precision highp float;
 uniform vec3 u_lightColor;                      // Light color
 uniform vec3 u_lightColor;                      // Light color
 uniform vec3 u_ambientColor;                    // Ambient color
 uniform vec3 u_ambientColor;                    // Ambient color
 uniform sampler2D u_diffuseTexture;             // Diffuse texture.
 uniform sampler2D u_diffuseTexture;             // Diffuse texture.
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec3 v_normalVector;                    // NormalVector in view space.
 varying vec3 v_normalVector;                    // NormalVector in view space.
@@ -101,4 +104,8 @@ void main()
     // Light the pixel
     // Light the pixel
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.rgb = _ambientColor + _diffuseColor;
     gl_FragColor.rgb = _ambientColor + _diffuseColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/parallax-specular.fsh

@@ -10,6 +10,9 @@ uniform sampler2D u_diffuseTexture;             // Diffuse texture.
 uniform sampler2D u_bumpMapTexture;             // Height map texture
 uniform sampler2D u_bumpMapTexture;             // Height map texture
 uniform sampler2D u_normalMapTexture;           // Normal map texture.
 uniform sampler2D u_normalMapTexture;           // Normal map texture.
 uniform float u_parallaxHeight;                 // Parallax height
 uniform float u_parallaxHeight;                 // Parallax height
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec2 v_texCoord;                        // Texture Coordinate.
 varying vec2 v_texCoord;                        // Texture Coordinate.
@@ -165,4 +168,8 @@ void main()
     // Light the pixel
     // Light the pixel
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
     gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/parallax.fsh

@@ -9,6 +9,9 @@ uniform sampler2D u_diffuseTexture;             // Diffuse texture.
 uniform sampler2D u_bumpMapTexture;             // Height map texture
 uniform sampler2D u_bumpMapTexture;             // Height map texture
 uniform sampler2D u_normalMapTexture;           // Normal map texture.
 uniform sampler2D u_normalMapTexture;           // Normal map texture.
 uniform float u_parallaxHeight;                 // Parallax height
 uniform float u_parallaxHeight;                 // Parallax height
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec2 v_texCoord;                        // Texture Coordinate.
 varying vec2 v_texCoord;                        // Texture Coordinate.
@@ -157,4 +160,8 @@ void main()
     // Light the pixel
     // Light the pixel
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.a = _baseColor.a;
     gl_FragColor.rgb = _ambientColor + _diffuseColor;
     gl_FragColor.rgb = _ambientColor + _diffuseColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/solid.fsh

@@ -4,8 +4,15 @@ precision highp float;
 
 
 // Uniforms
 // Uniforms
 uniform vec4 u_diffuseColor;        // Diffuse color
 uniform vec4 u_diffuseColor;        // Diffuse color
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;        // Global alpha value
+#endif
 
 
 void main()
 void main()
 {
 {
     gl_FragColor = u_diffuseColor;
     gl_FragColor = u_diffuseColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 7 - 0
gameplay/res/shaders/textured.fsh

@@ -5,6 +5,9 @@ precision highp float;
 // Uniforms
 // Uniforms
 uniform sampler2D u_diffuseTexture;     // Diffuse texture
 uniform sampler2D u_diffuseTexture;     // Diffuse texture
 uniform vec4 u_diffuseColor;            // Diffuse color/tint
 uniform vec4 u_diffuseColor;            // Diffuse color/tint
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;            // Global alpha value
+#endif
 
 
 // Inputs
 // Inputs
 varying vec2 v_texCoord;                // Texture coordinate (u, v).
 varying vec2 v_texCoord;                // Texture coordinate (u, v).
@@ -12,4 +15,8 @@ varying vec2 v_texCoord;                // Texture coordinate (u, v).
 void main()
 void main()
 {
 {
     gl_FragColor = texture2D(u_diffuseTexture, v_texCoord) * u_diffuseColor;
     gl_FragColor = texture2D(u_diffuseTexture, v_texCoord) * u_diffuseColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
 }
 }

+ 6 - 2
gameplay/src/AbsoluteLayout.cpp

@@ -45,9 +45,13 @@ namespace gameplay
         unsigned int controlsCount = controls.size();
         unsigned int controlsCount = controls.size();
         for (unsigned int i = 0; i < controlsCount; i++)
         for (unsigned int i = 0; i < controlsCount; i++)
         {
         {
-            if (controls[i]->isDirty())
+            Control* control = controls[i];
+
+            align(control, container);
+
+            if (control->isDirty() || control->isContainer())
             {
             {
-                controls[i]->update(container->getClip());
+                control->update(container->getClip());
             }
             }
         }
         }
     }
     }

+ 14 - 0
gameplay/src/AbsoluteLayout.h

@@ -16,6 +16,7 @@ class AbsoluteLayout : public Layout
     friend class Container;
     friend class Container;
 
 
 public:
 public:
+
     /**
     /**
      * Get the type of this Layout.
      * Get the type of this Layout.
      *
      *
@@ -24,6 +25,7 @@ public:
     Layout::Type getType();
     Layout::Type getType();
 
 
 protected:
 protected:
+
     /**
     /**
      * Create an AbsoluteLayout.
      * Create an AbsoluteLayout.
      *
      *
@@ -42,8 +44,20 @@ protected:
     void update(const Container* container);
     void update(const Container* container);
 
 
 private:
 private:
+    
+    /*
+     * Constructor.
+     */
     AbsoluteLayout();
     AbsoluteLayout();
+    
+    /*
+     * Constructor.
+     */
     AbsoluteLayout(const AbsoluteLayout& copy);
     AbsoluteLayout(const AbsoluteLayout& copy);
+    
+    /*
+     * Destructor.
+     */
     virtual ~AbsoluteLayout();
     virtual ~AbsoluteLayout();
 };
 };
 
 

+ 13 - 39
gameplay/src/Animation.cpp

@@ -34,6 +34,8 @@ Animation::Animation(const char* id)
 
 
 Animation::~Animation()
 Animation::~Animation()
 {
 {
+    _channels.clear();
+
     if (_defaultClip)
     if (_defaultClip)
     {
     {
         if (_defaultClip->isClipStateBitSet(AnimationClip::CLIP_IS_PLAYING_BIT))
         if (_defaultClip->isClipStateBitSet(AnimationClip::CLIP_IS_PLAYING_BIT))
@@ -59,58 +61,32 @@ Animation::~Animation()
 }
 }
 
 
 Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
 Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
-    : _animation(animation), _target(target), _propertyId(propertyId), _duration(duration)
+    : _animation(animation), _target(target), _propertyId(propertyId), _curve(curve), _duration(duration)
 {
 {
-    _curveRef = Animation::CurveRef::create(curve);
     // get property component count, and ensure the property exists on the AnimationTarget by getting the property component count.
     // get property component count, and ensure the property exists on the AnimationTarget by getting the property component count.
     assert(_target->getAnimationPropertyComponentCount(propertyId));
     assert(_target->getAnimationPropertyComponentCount(propertyId));
-
-    _animation->addRef();
-
+    _curve->addRef();
     _target->addChannel(this);
     _target->addChannel(this);
 }
 }
 
 
 Animation::Channel::Channel(const Channel& copy, Animation* animation, AnimationTarget* target)
 Animation::Channel::Channel(const Channel& copy, Animation* animation, AnimationTarget* target)
-    : _animation(animation), _target(target), _propertyId(copy._propertyId), _duration(copy._duration)
+    : _animation(animation), _target(target), _propertyId(copy._propertyId), _curve(copy._curve), _duration(copy._duration)
 {
 {
-    _curveRef = copy._curveRef;
-    _curveRef->addRef();
-
-    _animation->addRef();
+    _curve->addRef();
     _target->addChannel(this);
     _target->addChannel(this);
 }
 }
 
 
 Animation::Channel::~Channel()
 Animation::Channel::~Channel()
 {
 {
-    SAFE_RELEASE(_curveRef);
+    SAFE_RELEASE(_curve);
     SAFE_RELEASE(_animation);
     SAFE_RELEASE(_animation);
 }
 }
 
 
 Curve* Animation::Channel::getCurve() const
 Curve* Animation::Channel::getCurve() const
-{
-    return _curveRef->getCurve();
-}
-
-Animation::CurveRef* Animation::CurveRef::create(Curve* curve)
-{
-    return new CurveRef(curve);
-}
-
-Curve* Animation::CurveRef::getCurve() const
 {
 {
     return _curve;
     return _curve;
 }
 }
 
 
-Animation::CurveRef::CurveRef(Curve* curve)
-    : _curve(curve)
-{
-}
-
-Animation::CurveRef::~CurveRef()
-{
-    SAFE_DELETE(_curve);
-}
-
 const char* Animation::getId() const
 const char* Animation::getId() const
 {
 {
     return _id.c_str();
     return _id.c_str();
@@ -231,7 +207,7 @@ void Animation::createDefaultClip()
 }
 }
 
 
 void Animation::createClips(Properties* animationProperties, unsigned int frameCount)
 void Animation::createClips(Properties* animationProperties, unsigned int frameCount)
-{   
+{
     assert(animationProperties);
     assert(animationProperties);
     
     
     Properties* pClip = animationProperties->getNextNamespace();
     Properties* pClip = animationProperties->getNextNamespace();
@@ -301,7 +277,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
     unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
     assert(propertyComponentCount > 0);
     assert(propertyComponentCount > 0);
 
 
-    Curve* curve = new Curve(keyCount, propertyComponentCount);
+    Curve* curve = Curve::create(keyCount, propertyComponentCount);
     if (target->_targetType == AnimationTarget::TRANSFORM)
     if (target->_targetType == AnimationTarget::TRANSFORM)
         setTransformRotationOffset(curve, propertyId);
         setTransformRotationOffset(curve, propertyId);
 
 
@@ -328,6 +304,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     SAFE_DELETE(normalizedKeyTimes);
     SAFE_DELETE(normalizedKeyTimes);
 
 
     Channel* channel = new Channel(this, target, propertyId, curve, duration);
     Channel* channel = new Channel(this, target, propertyId, curve, duration);
+    curve->release();
     addChannel(channel);
     addChannel(channel);
     return channel;
     return channel;
 }
 }
@@ -337,7 +314,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
     unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
     assert(propertyComponentCount > 0);
     assert(propertyComponentCount > 0);
 
 
-    Curve* curve = new Curve(keyCount, propertyComponentCount);
+    Curve* curve = Curve::create(keyCount, propertyComponentCount);
     if (target->_targetType == AnimationTarget::TRANSFORM)
     if (target->_targetType == AnimationTarget::TRANSFORM)
         setTransformRotationOffset(curve, propertyId);
         setTransformRotationOffset(curve, propertyId);
     
     
@@ -364,6 +341,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     SAFE_DELETE(normalizedKeyTimes);
     SAFE_DELETE(normalizedKeyTimes);
 
 
     Channel* channel = new Channel(this, target, propertyId, curve, duration);
     Channel* channel = new Channel(this, target, propertyId, curve, duration);
+    curve->release();
     addChannel(channel);
     addChannel(channel);
     return channel;
     return channel;
 }
 }
@@ -385,16 +363,13 @@ void Animation::removeChannel(Channel* channel)
         if (channel == chan) 
         if (channel == chan) 
         {
         {
             _channels.erase(itr);
             _channels.erase(itr);
-            itr = _channels.end();
+            return;
         }
         }
         else
         else
         {
         {
             itr++;
             itr++;
         }
         }
     }
     }
-
-    if (_channels.empty())
-        _controller->destroyAnimation(this);
 }
 }
 
 
 void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId)
 void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId)
@@ -416,7 +391,6 @@ void Animation::setTransformRotationOffset(Curve* curve, unsigned int propertyId
 Animation* Animation::clone()
 Animation* Animation::clone()
 {
 {
     Animation* animation = new Animation(getId());
     Animation* animation = new Animation(getId());
-    _controller->addAnimation(animation);
     return animation;
     return animation;
 }
 }
 
 

+ 4 - 26
gameplay/src/Animation.h

@@ -22,7 +22,6 @@ class AnimationClip;
  */
  */
 class Animation : public Ref
 class Animation : public Ref
 {
 {
-    friend class AnimationController;
     friend class AnimationClip;
     friend class AnimationClip;
     friend class AnimationTarget;
     friend class AnimationTarget;
     friend class Package;
     friend class Package;
@@ -93,29 +92,9 @@ public:
      * Returns true if this animation targets the given AnimationTarget.
      * Returns true if this animation targets the given AnimationTarget.
      */
      */
     bool targets(AnimationTarget* target) const;
     bool targets(AnimationTarget* target) const;
-
+    
 private:
 private:
 
 
-    /**
-     * Defines a reference counted Curve wrapper.
-     * 
-     * Multiple channels can share the same Curve.
-     */
-    class CurveRef : public Ref
-    {
-    public:
-        static CurveRef* create(Curve* curve);
-        Curve* getCurve() const;
-
-    private:
-        CurveRef(Curve* curve);
-        CurveRef(const CurveRef&); // Hidden copy constructor.
-        ~CurveRef();
-        CurveRef& operator=(const CurveRef&); // Hidden copy assignment operator.
-
-        Curve* _curve;
-    };
-
     /**
     /**
      * Defines a channel which holds the target, target property, curve values, and duration.
      * Defines a channel which holds the target, target property, curve values, and duration.
      *
      *
@@ -124,7 +103,6 @@ private:
      */
      */
     class Channel
     class Channel
     {
     {
-        friend class AnimationController;
         friend class AnimationClip;
         friend class AnimationClip;
         friend class Animation;
         friend class Animation;
         friend class AnimationTarget;
         friend class AnimationTarget;
@@ -141,7 +119,7 @@ private:
         Animation* _animation;                // Reference to the animation this channel belongs to.
         Animation* _animation;                // Reference to the animation this channel belongs to.
         AnimationTarget* _target;             // The target of this channel.
         AnimationTarget* _target;             // The target of this channel.
         int _propertyId;                      // The target property this channel targets.
         int _propertyId;                      // The target property this channel targets.
-        CurveRef* _curveRef;                  // The curve used to represent the animation data.
+        Curve* _curve;                        // The curve used to represent the animation data.
         unsigned long _duration;              // The length of the animation (in milliseconds).
         unsigned long _duration;              // The length of the animation (in milliseconds).
     };
     };
 
 
@@ -169,12 +147,12 @@ private:
      * Destructor.
      * Destructor.
      */
      */
     ~Animation();
     ~Animation();
-
+    
     /**
     /**
      * Hidden copy assignment operator.
      * Hidden copy assignment operator.
      */
      */
     Animation& operator=(const Animation&);
     Animation& operator=(const Animation&);
-
+    
     /**
     /**
      * Creates the default clip.
      * Creates the default clip.
      */
      */

+ 4 - 3
gameplay/src/AnimationClip.h

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

+ 1 - 303
gameplay/src/AnimationController.cpp

@@ -7,125 +7,12 @@ namespace gameplay
 {
 {
 
 
 AnimationController::AnimationController()
 AnimationController::AnimationController()
-    : _state(STOPPED), _animations(NULL)
+    : _state(STOPPED)
 {
 {
 }
 }
 
 
 AnimationController::~AnimationController()
 AnimationController::~AnimationController()
 {
 {
-    std::vector<Animation*>::iterator itr = _animations.begin();
-    for ( ; itr != _animations.end(); itr++)
-    {
-        Animation* temp = *itr;
-        SAFE_RELEASE(temp);
-    }
-
-    _animations.clear();
-}
-
-Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, Curve::InterpolationType type)
-{
-    assert(type != Curve::BEZIER && type != Curve::HERMITE);
-    assert(keyCount >= 2 && keyTimes && keyValues && target);
-
-    Animation* animation = new Animation(id, target, propertyId, keyCount, keyTimes, keyValues, type);
-
-    addAnimation(animation);
-    
-    return animation;
-}
-
-Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type)
-{
-    assert(target && keyCount >= 2 && keyTimes && keyValues && keyInValue && keyOutValue);
-    Animation* animation = new Animation(id, target, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
-
-    addAnimation(animation);
-
-    return animation;
-}
-
-Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, const char* animationFile)
-{
-    assert(target && animationFile);
-    
-    Properties* p = Properties::create(animationFile);
-    assert(p);
-
-    Animation* animation = createAnimation(id, target, p->getNextNamespace());
-
-    SAFE_DELETE(p);
-
-    return animation;
-}
-
-Animation* AnimationController::createAnimationFromTo(const char* id, AnimationTarget* target, int propertyId, float* from, float* to, Curve::InterpolationType type, unsigned long duration)
-{
-    const unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
-    float* keyValues = new float[2 * propertyComponentCount];
-
-    memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
-    memcpy(keyValues + propertyComponentCount, to, sizeof(float) * propertyComponentCount);
-
-    unsigned long* keyTimes = new unsigned long[2];
-    keyTimes[0] = 0;
-    keyTimes[1] = duration;
-
-    Animation* animation = createAnimation(id, target, propertyId, 2, keyTimes, keyValues, type);
-
-    SAFE_DELETE_ARRAY(keyValues);
-    SAFE_DELETE_ARRAY(keyTimes);
-    
-    return animation;
-}
-
-Animation* AnimationController::createAnimationFromBy(const char* id, AnimationTarget* target, int propertyId, float* from, float* by, Curve::InterpolationType type, unsigned long duration)
-{
-    const unsigned int propertyComponentCount = target->getAnimationPropertyComponentCount(propertyId);
-    float* keyValues = new float[2 * propertyComponentCount];
-
-    memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
-    memcpy(keyValues + propertyComponentCount, by, sizeof(float) * propertyComponentCount);
-
-    unsigned long* keyTimes = new unsigned long[2];
-    keyTimes[0] = 0;
-    keyTimes[1] = duration;
-
-    Animation* animation = createAnimation(id, target, propertyId, 2, keyTimes, keyValues, type);
-
-    SAFE_DELETE_ARRAY(keyValues);
-    SAFE_DELETE_ARRAY(keyTimes);
-
-    return animation;
-}
-
-Animation* AnimationController::getAnimation(const char* id) const
-{
-    unsigned int animationCount = _animations.size();
-    for (unsigned int i = 0; i < animationCount; i++)
-    {
-        if (_animations.at(i)->_id.compare(id) == 0)
-        {
-            return _animations.at(i);
-        }
-    }
-    return NULL;
-}
-
-Animation* AnimationController::getAnimation(AnimationTarget* target) const
-{
-    if (!target)
-        return NULL;
-    const unsigned int animationCount = _animations.size();
-    for (unsigned int i = 0; i < animationCount; ++i)
-    {
-        Animation* animation = _animations[i];
-        if (animation->targets(target))
-        {
-            return animation;
-        }
-    }
-    return NULL;
 }
 }
 
 
 void AnimationController::stopAllAnimations() 
 void AnimationController::stopAllAnimations() 
@@ -139,144 +26,6 @@ void AnimationController::stopAllAnimations()
     }
     }
 }
 }
 
 
-Animation* AnimationController::createAnimation(const char* id, AnimationTarget* target, Properties* animationProperties)
-{
-    assert(target && animationProperties);
-    assert(std::strcmp(animationProperties->getNamespace(), "animation") == 0);
-    
-    const char* propertyIdStr = animationProperties->getString("property");
-    assert(propertyIdStr);
-    
-    // Get animation target property id
-    int propertyId = AnimationTarget::getPropertyId(target->_targetType, propertyIdStr);
-    assert(propertyId != -1);
-    
-    unsigned int keyCount = animationProperties->getInt("keyCount");
-    assert(keyCount > 0);
-
-    const char* keyTimesStr = animationProperties->getString("keyTimes");
-    assert(keyTimesStr);
-    
-    const char* keyValuesStr = animationProperties->getString("keyValues");
-    assert(keyValuesStr);
-    
-    const char* curveStr = animationProperties->getString("curve");
-    assert(curveStr);
-    
-    char delimeter = ' ';
-    unsigned int startOffset = 0;
-    unsigned int endOffset = (unsigned int)std::string::npos;
-    
-    unsigned long* keyTimes = new unsigned long[keyCount];
-    for (unsigned int i = 0; i < keyCount; i++)
-    {
-        endOffset = static_cast<std::string>(keyTimesStr).find_first_of(delimeter, startOffset);
-        if (endOffset != std::string::npos)
-        {
-            keyTimes[i] = std::strtoul(static_cast<std::string>(keyTimesStr).substr(startOffset, endOffset - startOffset).c_str(), NULL, 0);
-        }
-        else
-        {
-            keyTimes[i] = std::strtoul(static_cast<std::string>(keyTimesStr).substr(startOffset, static_cast<std::string>(keyTimesStr).length()).c_str(), NULL, 0);
-        }
-        startOffset = endOffset + 1;
-    }
-
-    startOffset = 0;
-    endOffset = (unsigned int)std::string::npos;
-    
-    int componentCount = target->getAnimationPropertyComponentCount(propertyId);
-    assert(componentCount > 0);
-    
-    unsigned int components = keyCount * componentCount;
-    
-    float* keyValues = new float[components];
-    for (unsigned int i = 0; i < components; i++)
-    {
-        endOffset = static_cast<std::string>(keyValuesStr).find_first_of(delimeter, startOffset);
-        if (endOffset != std::string::npos)
-        {   
-            keyValues[i] = std::atof(static_cast<std::string>(keyValuesStr).substr(startOffset, endOffset - startOffset).c_str());
-        }
-        else
-        {
-            keyValues[i] = std::atof(static_cast<std::string>(keyValuesStr).substr(startOffset, static_cast<std::string>(keyValuesStr).length()).c_str());
-        }
-        startOffset = endOffset + 1;
-    }
-
-    const char* keyInStr = animationProperties->getString("keyIn");
-    float* keyIn = NULL;
-    if (keyInStr)
-    {
-        keyIn = new float[components];
-        startOffset = 0;
-        endOffset = (unsigned int)std::string::npos;
-        for (unsigned int i = 0; i < components; i++)
-        {
-            endOffset = static_cast<std::string>(keyInStr).find_first_of(delimeter, startOffset);
-            if (endOffset != std::string::npos)
-            {   
-                keyIn[i] = std::atof(static_cast<std::string>(keyInStr).substr(startOffset, endOffset - startOffset).c_str());
-            }
-            else
-            {
-                keyIn[i] = std::atof(static_cast<std::string>(keyInStr).substr(startOffset, static_cast<std::string>(keyInStr).length()).c_str());
-            }
-            startOffset = endOffset + 1;
-        }
-    }
-    
-    const char* keyOutStr = animationProperties->getString("keyOut");
-    float* keyOut = NULL;
-    if (keyOutStr)
-    {   
-        keyOut = new float[components];
-        startOffset = 0;
-        endOffset = (unsigned int)std::string::npos;
-        for (unsigned int i = 0; i < components; i++)
-        {
-            endOffset = static_cast<std::string>(keyOutStr).find_first_of(delimeter, startOffset);
-            if (endOffset != std::string::npos)
-            {   
-                keyOut[i] = std::atof(static_cast<std::string>(keyOutStr).substr(startOffset, endOffset - startOffset).c_str());
-            }
-            else
-            {
-                keyOut[i] = std::atof(static_cast<std::string>(keyOutStr).substr(startOffset, static_cast<std::string>(keyOutStr).length()).c_str());
-            }
-            startOffset = endOffset + 1;
-        }
-    }
-
-    int curve = Curve::getInterpolationType(curveStr);
-
-    Animation* animation = NULL;
-    if (keyIn && keyOut)
-    {
-        animation = createAnimation(id, target, propertyId, keyCount, keyTimes, keyValues, keyIn, keyOut, (Curve::InterpolationType)curve);
-    }
-    else
-    {
-        animation = createAnimation(id, target, propertyId, keyCount, keyTimes, keyValues, (Curve::InterpolationType) curve);
-    }
-
-    SAFE_DELETE(keyOut);
-    SAFE_DELETE(keyIn);
-    SAFE_DELETE(keyValues);
-    SAFE_DELETE(keyTimes);
-
-    Properties* pClip = animationProperties->getNextNamespace();
-    if (pClip && std::strcmp(pClip->getNamespace(), "clip") == 0)
-    {
-        int frameCount = animationProperties->getInt("frameCount");
-        assert(frameCount > 0);
-        animation->createClips(animationProperties, (unsigned int) frameCount);
-    }
-
-    return animation;
-}
-
 AnimationController::State AnimationController::getState() const
 AnimationController::State AnimationController::getState() const
 {
 {
     return _state;
     return _state;
@@ -385,55 +134,4 @@ void AnimationController::update(long elapsedTime)
         _state = IDLE;
         _state = IDLE;
 }
 }
 
 
-void AnimationController::addAnimation(Animation* animation)
-{
-    _animations.push_back(animation);
-}
-
-void AnimationController::destroyAnimation(Animation* animation)
-{
-    assert(animation);
-
-    std::vector<Animation::Channel*>::iterator cItr = animation->_channels.begin();
-    for (; cItr != animation->_channels.end(); cItr++)
-    {
-        Animation::Channel* channel = *cItr;
-        channel->_target->deleteChannel(channel);
-    }
-
-    std::vector<Animation*>::iterator aItr = _animations.begin();
-    while (aItr != _animations.end())
-    {
-        if (animation == *aItr)
-        {
-            Animation* temp = *aItr;
-            SAFE_RELEASE(temp);
-            _animations.erase(aItr);
-            return;
-        }
-        aItr++;
-    }
-}
-
-void AnimationController::destroyAllAnimations()
-{
-    std::vector<Animation*>::iterator aItr = _animations.begin();
-    
-    while (aItr != _animations.end())
-    {
-        Animation* animation = *aItr;
-        std::vector<Animation::Channel*>::iterator cItr = animation->_channels.begin();
-        for (; cItr != animation->_channels.end(); cItr++)
-        {
-            Animation::Channel* channel = *cItr;
-            channel->_target->deleteChannel(channel);
-        }
-
-        SAFE_RELEASE(animation);
-        aItr++;
-    }
-
-    _animations.clear();
-}
-
 }
 }

+ 5 - 119
gameplay/src/AnimationController.h

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

+ 278 - 8
gameplay/src/AnimationTarget.cpp

@@ -2,6 +2,7 @@
 #include "AnimationTarget.h"
 #include "AnimationTarget.h"
 #include "Animation.h"
 #include "Animation.h"
 #include "Game.h"
 #include "Game.h"
+#include "Node.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -28,12 +29,251 @@ AnimationTarget::~AnimationTarget()
     }
     }
 }
 }
 
 
-void AnimationTarget::addChannel(Animation::Channel* channel)
+Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, Curve::InterpolationType type)
 {
 {
-    if (_animationChannels == NULL)
-        _animationChannels = new std::vector<Animation::Channel*>;
+    assert(type != Curve::BEZIER && type != Curve::HERMITE);
+    assert(keyCount >= 1 && keyTimes && keyValues);
 
 
-    _animationChannels->push_back(channel);
+    Animation* animation = new Animation(id, this, propertyId, keyCount, keyTimes, keyValues, type);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type)
+{
+    assert(keyCount >= 1 && keyTimes && keyValues && keyInValue && keyOutValue);
+    Animation* animation = new Animation(id, this, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimation(const char* id, const char* animationFile)
+{
+    assert(animationFile);
+    
+    Properties* p = Properties::create(animationFile);
+    assert(p);
+
+    Animation* animation = createAnimation(id, p->getNextNamespace());
+
+    SAFE_DELETE(p);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimationFromTo(const char* id, int propertyId, float* from, float* to, Curve::InterpolationType type, unsigned long duration)
+{
+    const unsigned int propertyComponentCount = getAnimationPropertyComponentCount(propertyId);
+    float* keyValues = new float[2 * propertyComponentCount];
+
+    memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
+    memcpy(keyValues + propertyComponentCount, to, sizeof(float) * propertyComponentCount);
+
+    unsigned long* keyTimes = new unsigned long[2];
+    keyTimes[0] = 0;
+    keyTimes[1] = duration;
+
+    Animation* animation = createAnimation(id, propertyId, 2, keyTimes, keyValues, type);
+
+    SAFE_DELETE_ARRAY(keyValues);
+    SAFE_DELETE_ARRAY(keyTimes);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimationFromBy(const char* id, int propertyId, float* from, float* by, Curve::InterpolationType type, unsigned long duration)
+{
+    const unsigned int propertyComponentCount = getAnimationPropertyComponentCount(propertyId);
+    float* keyValues = new float[2 * propertyComponentCount];
+
+    memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
+    memcpy(keyValues + propertyComponentCount, by, sizeof(float) * propertyComponentCount);
+
+    unsigned long* keyTimes = new unsigned long[2];
+    keyTimes[0] = 0;
+    keyTimes[1] = duration;
+
+    Animation* animation = createAnimation(id, propertyId, 2, keyTimes, keyValues, type);
+
+    SAFE_DELETE_ARRAY(keyValues);
+    SAFE_DELETE_ARRAY(keyTimes);
+
+    return animation;
+}
+
+Animation* AnimationTarget::createAnimation(const char* id, Properties* animationProperties)
+{
+    assert(animationProperties);
+    assert(std::strcmp(animationProperties->getNamespace(), "animation") == 0);
+    
+    const char* propertyIdStr = animationProperties->getString("property");
+    assert(propertyIdStr);
+    
+    // Get animation target property id
+    int propertyId = AnimationTarget::getPropertyId(_targetType, propertyIdStr);
+    assert(propertyId != -1);
+    
+    unsigned int keyCount = animationProperties->getInt("keyCount");
+    assert(keyCount > 0);
+
+    const char* keyTimesStr = animationProperties->getString("keyTimes");
+    assert(keyTimesStr);
+    
+    const char* keyValuesStr = animationProperties->getString("keyValues");
+    assert(keyValuesStr);
+    
+    const char* curveStr = animationProperties->getString("curve");
+    assert(curveStr);
+    
+    char delimeter = ' ';
+    unsigned int startOffset = 0;
+    unsigned int endOffset = (unsigned int)std::string::npos;
+    
+    unsigned long* keyTimes = new unsigned long[keyCount];
+    for (unsigned int i = 0; i < keyCount; i++)
+    {
+        endOffset = static_cast<std::string>(keyTimesStr).find_first_of(delimeter, startOffset);
+        if (endOffset != std::string::npos)
+        {
+            keyTimes[i] = std::strtoul(static_cast<std::string>(keyTimesStr).substr(startOffset, endOffset - startOffset).c_str(), NULL, 0);
+        }
+        else
+        {
+            keyTimes[i] = std::strtoul(static_cast<std::string>(keyTimesStr).substr(startOffset, static_cast<std::string>(keyTimesStr).length()).c_str(), NULL, 0);
+        }
+        startOffset = endOffset + 1;
+    }
+
+    startOffset = 0;
+    endOffset = (unsigned int)std::string::npos;
+    
+    int componentCount = getAnimationPropertyComponentCount(propertyId);
+    assert(componentCount > 0);
+    
+    unsigned int components = keyCount * componentCount;
+    
+    float* keyValues = new float[components];
+    for (unsigned int i = 0; i < components; i++)
+    {
+        endOffset = static_cast<std::string>(keyValuesStr).find_first_of(delimeter, startOffset);
+        if (endOffset != std::string::npos)
+        {   
+            keyValues[i] = std::atof(static_cast<std::string>(keyValuesStr).substr(startOffset, endOffset - startOffset).c_str());
+        }
+        else
+        {
+            keyValues[i] = std::atof(static_cast<std::string>(keyValuesStr).substr(startOffset, static_cast<std::string>(keyValuesStr).length()).c_str());
+        }
+        startOffset = endOffset + 1;
+    }
+
+    const char* keyInStr = animationProperties->getString("keyIn");
+    float* keyIn = NULL;
+    if (keyInStr)
+    {
+        keyIn = new float[components];
+        startOffset = 0;
+        endOffset = (unsigned int)std::string::npos;
+        for (unsigned int i = 0; i < components; i++)
+        {
+            endOffset = static_cast<std::string>(keyInStr).find_first_of(delimeter, startOffset);
+            if (endOffset != std::string::npos)
+            {   
+                keyIn[i] = std::atof(static_cast<std::string>(keyInStr).substr(startOffset, endOffset - startOffset).c_str());
+            }
+            else
+            {
+                keyIn[i] = std::atof(static_cast<std::string>(keyInStr).substr(startOffset, static_cast<std::string>(keyInStr).length()).c_str());
+            }
+            startOffset = endOffset + 1;
+        }
+    }
+    
+    const char* keyOutStr = animationProperties->getString("keyOut");
+    float* keyOut = NULL;
+    if (keyOutStr)
+    {   
+        keyOut = new float[components];
+        startOffset = 0;
+        endOffset = (unsigned int)std::string::npos;
+        for (unsigned int i = 0; i < components; i++)
+        {
+            endOffset = static_cast<std::string>(keyOutStr).find_first_of(delimeter, startOffset);
+            if (endOffset != std::string::npos)
+            {   
+                keyOut[i] = std::atof(static_cast<std::string>(keyOutStr).substr(startOffset, endOffset - startOffset).c_str());
+            }
+            else
+            {
+                keyOut[i] = std::atof(static_cast<std::string>(keyOutStr).substr(startOffset, static_cast<std::string>(keyOutStr).length()).c_str());
+            }
+            startOffset = endOffset + 1;
+        }
+    }
+
+    int curve = Curve::getInterpolationType(curveStr);
+
+    Animation* animation = NULL;
+    if (keyIn && keyOut)
+    {
+        animation = createAnimation(id, propertyId, keyCount, keyTimes, keyValues, keyIn, keyOut, (Curve::InterpolationType)curve);
+    }
+    else
+    {
+        animation = createAnimation(id, propertyId, keyCount, keyTimes, keyValues, (Curve::InterpolationType) curve);
+    }
+
+    SAFE_DELETE(keyOut);
+    SAFE_DELETE(keyIn);
+    SAFE_DELETE(keyValues);
+    SAFE_DELETE(keyTimes);
+
+    Properties* pClip = animationProperties->getNextNamespace();
+    if (pClip && std::strcmp(pClip->getNamespace(), "clip") == 0)
+    {
+        int frameCount = animationProperties->getInt("frameCount");
+        assert(frameCount > 0);
+        animation->createClips(animationProperties, (unsigned int) frameCount);
+    }
+
+    return animation;
+}
+
+void AnimationTarget::destroyAnimation(const char* id)
+{
+    // Find the animation with the specified ID.
+    Animation::Channel* channel = getChannel(id);
+    if (channel == NULL)
+        return;
+
+    // Remove this target's channel from animation, and from the target's list of channels.
+    channel->_animation->removeChannel(channel);
+    removeChannel(channel);
+
+    SAFE_DELETE(channel);
+}
+
+Animation* AnimationTarget::getAnimation(const char* id) const
+{
+    if (_animationChannels)
+    {
+        std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
+
+        if (id == NULL)
+            return (*itr)->_animation;
+
+        Animation::Channel* channel = NULL;
+        for (; itr != _animationChannels->end(); itr++)
+        {
+            channel = (Animation::Channel*)(*itr);
+            if (channel->_animation->_id.compare(id) == 0)
+            {
+                return channel->_animation;
+            }
+        }
+    }
+
+    return NULL;
 }
 }
 
 
 int AnimationTarget::getPropertyId(TargetType type, const char* propertyIdStr)
 int AnimationTarget::getPropertyId(TargetType type, const char* propertyIdStr)
@@ -96,7 +336,15 @@ int AnimationTarget::getPropertyId(TargetType type, const char* propertyIdStr)
     return -1;
     return -1;
 }
 }
 
 
-void AnimationTarget::deleteChannel(Animation::Channel* channel)
+void AnimationTarget::addChannel(Animation::Channel* channel)
+{
+    if (_animationChannels == NULL)
+        _animationChannels = new std::vector<Animation::Channel*>;
+
+    _animationChannels->push_back(channel);
+}
+
+void AnimationTarget::removeChannel(Animation::Channel* channel)
 {
 {
     if (_animationChannels)
     if (_animationChannels)
     {
     {
@@ -106,7 +354,6 @@ void AnimationTarget::deleteChannel(Animation::Channel* channel)
             Animation::Channel* temp = *itr;
             Animation::Channel* temp = *itr;
             if (channel == temp)
             if (channel == temp)
             {
             {
-                SAFE_DELETE(channel);
                 _animationChannels->erase(itr);
                 _animationChannels->erase(itr);
 
 
                 if (_animationChannels->empty())
                 if (_animationChannels->empty())
@@ -118,7 +365,30 @@ void AnimationTarget::deleteChannel(Animation::Channel* channel)
     }
     }
 }
 }
 
 
-void AnimationTarget::cloneInto(AnimationTarget* target, CloneContext &context) const
+Animation::Channel* AnimationTarget::getChannel(const char* id) const
+{
+    if (_animationChannels)
+    {
+        std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
+
+        if (id == NULL)
+            return (*itr);
+
+        Animation::Channel* channel = NULL;
+        for (; itr != _animationChannels->end(); itr++)
+        {
+            channel = (Animation::Channel*)(*itr);
+            if (channel->_animation->_id.compare(id) == 0)
+            {
+                return channel;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+void AnimationTarget::cloneInto(AnimationTarget* target, NodeCloneContext &context) const
 {
 {
     if (_animationChannels)
     if (_animationChannels)
     {
     {
@@ -129,7 +399,7 @@ void AnimationTarget::cloneInto(AnimationTarget* target, CloneContext &context)
 
 
             bool animationCloned = false;
             bool animationCloned = false;
 
 
-            // Don't clone the Animaton if it is already in the CloneContext.
+            // 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)
             {
             {

+ 111 - 7
gameplay/src/AnimationTarget.h

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

+ 2 - 1
gameplay/src/AudioBuffer.h

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

+ 3 - 3
gameplay/src/AudioController.cpp

@@ -38,9 +38,9 @@ void AudioController::initialize()
         return;  
         return;  
     }
     }
         
         
-	_alcContext = alcCreateContext(_alcDevice, NULL);
+    _alcContext = alcCreateContext(_alcDevice, NULL);
     ALCenum alcErr = alcGetError(_alcDevice);
     ALCenum alcErr = alcGetError(_alcDevice);
-	if (!_alcContext || alcErr != ALC_NO_ERROR)
+    if (!_alcContext || alcErr != ALC_NO_ERROR)
     {
     {
         alcCloseDevice (_alcDevice);
         alcCloseDevice (_alcDevice);
         LOG_ERROR_VARG("AudioController::initialize() error. Unable to create OpenAL context. Error: %d\n", alcErr);
         LOG_ERROR_VARG("AudioController::initialize() error. Unable to create OpenAL context. Error: %d\n", alcErr);
@@ -181,7 +181,7 @@ void AudioController::update(long elapsedTime)
             SLresult result = (*_engineEngine)->CreateListener(_engineEngine, &_listenerObject, 2, interfaces, required);
             SLresult result = (*_engineEngine)->CreateListener(_engineEngine, &_listenerObject, 2, interfaces, required);
             if (result != SL_RESULT_SUCCESS)
             if (result != SL_RESULT_SUCCESS)
             {
             {
-                WARN("AudioController: failed to create listener.");
+                WARN_VARG("AudioController: failed to create listener (%u).", result);
                 return;
                 return;
             }
             }
 
 

+ 7 - 3
gameplay/src/AudioSource.cpp

@@ -4,6 +4,7 @@
 #include "AudioController.h"
 #include "AudioController.h"
 #include "AudioSource.h"
 #include "AudioSource.h"
 #include "Game.h"
 #include "Game.h"
+#include "Node.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -464,7 +465,10 @@ void AudioSource::transformChanged(Transform* transform, long cookie)
 {
 {
 #ifndef __ANDROID__
 #ifndef __ANDROID__
     if (_node)
     if (_node)
-        alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&_node->getTranslationWorld());
+    {
+        Vector3 translation = _node->getTranslationWorld();
+        alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&translation.x);
+    }
 #else
 #else
     if (_playerLocation)
     if (_playerLocation)
     {
     {
@@ -481,7 +485,7 @@ void AudioSource::transformChanged(Transform* transform, long cookie)
 #endif
 #endif
 }
 }
 
 
-AudioSource* AudioSource::clone(CloneContext &context) const
+AudioSource* AudioSource::clone(NodeCloneContext &context) const
 {
 {
 #ifndef __ANDROID__
 #ifndef __ANDROID__
     ALuint alSource = 0;
     ALuint alSource = 0;
@@ -494,7 +498,7 @@ AudioSource* AudioSource::clone(CloneContext &context) const
     AudioSource* audioClone = new AudioSource(_buffer, alSource);
     AudioSource* audioClone = new AudioSource(_buffer, alSource);
 #else
 #else
     // TODO: Implement cloning audio source for Android
     // TODO: Implement cloning audio source for Android
-    AudioSource* audioClone = new AudioSource(AudioBuffer* buffer, const SLObjectItf& player);
+    AudioSource* audioClone = new AudioSource(_buffer, _playerObject);
 
 
 #endif
 #endif
     _buffer->addRef();
     _buffer->addRef();

+ 2 - 4
gameplay/src/AudioSource.h

@@ -10,6 +10,7 @@ namespace gameplay
 
 
 class AudioBuffer;
 class AudioBuffer;
 class Node;
 class Node;
+class NodeCloneContext;
 
 
 /**
 /**
  *  Declares an audio source in 3D space.
  *  Declares an audio source in 3D space.
@@ -151,16 +152,13 @@ private:
      * Constructor that takes an AudioBuffer.
      * Constructor that takes an AudioBuffer.
      */
      */
     AudioSource(AudioBuffer* buffer, ALuint source);
     AudioSource(AudioBuffer* buffer, ALuint source);
-
 #else
 #else
-
     /**
     /**
      * Constructor that takes an AudioBuffer.
      * Constructor that takes an AudioBuffer.
      */
      */
     AudioSource(AudioBuffer* buffer, const SLObjectItf& player);
     AudioSource(AudioBuffer* buffer, const SLObjectItf& player);
 #endif
 #endif
 
 
-
     /**
     /**
      * Destructor.
      * Destructor.
      */
      */
@@ -183,7 +181,7 @@ private:
      * 
      * 
      * @return The newly created audio source.
      * @return The newly created audio source.
      */
      */
-    AudioSource* clone(CloneContext &context) const;
+    AudioSource* clone(NodeCloneContext &context) const;
 
 
 #ifndef __ANDROID__
 #ifndef __ANDROID__
     ALuint _alSource;
     ALuint _alSource;

+ 1 - 3
gameplay/src/Base.h

@@ -143,7 +143,7 @@ extern void printError(const char* format, ...);
 #define MATH_LOG2E                  1.442695040888963387f
 #define MATH_LOG2E                  1.442695040888963387f
 #define MATH_PI                     3.14159265358979323846f
 #define MATH_PI                     3.14159265358979323846f
 #define MATH_PIOVER2                1.57079632679489661923f
 #define MATH_PIOVER2                1.57079632679489661923f
-#define MATH_PIOVER4                M_PI_4
+#define MATH_PIOVER4                0.785398163397448309616f
 #define MATH_PIX2                   6.28318530717958647693f
 #define MATH_PIX2                   6.28318530717958647693f
 #define MATH_EPSILON                0.000001f
 #define MATH_EPSILON                0.000001f
 #define MATH_CLAMP(x, lo, hi)       ((x < lo) ? lo : ((x > hi) ? hi : x))
 #define MATH_CLAMP(x, lo, hi)       ((x < lo) ? lo : ((x > hi) ? hi : x))
@@ -168,7 +168,6 @@ extern void printError(const char* format, ...);
 #include <SLES/OpenSLES.h>
 #include <SLES/OpenSLES.h>
 #include <SLES/OpenSLES_Android.h>
 #include <SLES/OpenSLES_Android.h>
 #else
 #else
-
 #ifdef __QNX__
 #ifdef __QNX__
 #include <AL/al.h>
 #include <AL/al.h>
 #include <AL/alc.h>
 #include <AL/alc.h>
@@ -179,7 +178,6 @@ extern void printError(const char* format, ...);
 #include <OpenAL/al.h>
 #include <OpenAL/al.h>
 #include <OpenAL/alc.h>
 #include <OpenAL/alc.h>
 #endif
 #endif
-
 #include <vorbis/vorbisfile.h>
 #include <vorbis/vorbisfile.h>
 #endif
 #endif
 
 

+ 3 - 3
gameplay/src/BoundingBox.cpp

@@ -57,9 +57,9 @@ void BoundingBox::getCorners(Vector3* dst) const
 
 
 Vector3 BoundingBox::getCenter() const
 Vector3 BoundingBox::getCenter() const
 {
 {
-	Vector3 center;
-	getCenter(&center);
-	return center;
+    Vector3 center;
+    getCenter(&center);
+    return center;
 }
 }
 
 
 void BoundingBox::getCenter(Vector3* dst) const
 void BoundingBox::getCenter(Vector3* dst) const

+ 1 - 1
gameplay/src/BoundingBox.h

@@ -53,7 +53,7 @@ public:
      */
      */
     static const BoundingBox& empty();
     static const BoundingBox& empty();
 
 
-	/**
+    /**
      * Gets the center point of the bounding box.
      * Gets the center point of the bounding box.
      *
      *
      * This method computes the center point of the box from its min and max.
      * This method computes the center point of the box from its min and max.

+ 1 - 1
gameplay/src/Button.cpp

@@ -14,7 +14,7 @@ namespace gameplay
     Button* Button::create(Theme::Style* style, Properties* properties)
     Button* Button::create(Theme::Style* style, Properties* properties)
     {
     {
         Button* button = new Button();
         Button* button = new Button();
-        button->init(style, properties);
+        button->initialize(style, properties);
 
 
         return button;
         return button;
     }
     }

+ 23 - 6
gameplay/src/Button.h

@@ -10,15 +10,20 @@ namespace gameplay
 {
 {
 
 
 /**
 /**
- * Defines a button UI control.  This is essentially a label that can have a callback method set on it.
+ * Defines a button UI control. This is essentially a label that can have a callback method set on it.
  *
  *
  * The following properties are available for buttons:
  * The following properties are available for buttons:
  *
  *
- * button <Button ID>
+ * button <buttonID>
  * {
  * {
- *      style       = <Style ID>
+ *      style       = <styleID>
+ *      alignment   = <Control::Alignment constant> // Note: 'position' will be ignored.
  *      position    = <x, y>
  *      position    = <x, y>
+ *      autoWidth   = <bool>
+ *      autoHeight  = <bool>
  *      size        = <width, height>
  *      size        = <width, height>
+ *      width       = <width>   // Can be used in place of 'size', e.g. with 'autoHeight = true'
+ *      height      = <height>  // Can be used in place of 'size', e.g. with 'autoWidth = true'
  *      text        = <string>
  *      text        = <string>
  * }
  * }
  */
  */
@@ -27,6 +32,17 @@ class Button : public Label
     friend class Container;
     friend class Container;
 
 
 protected:
 protected:
+
+    /**
+     * Constructor.
+     */
+    Button();
+
+    /**
+     * Destructor.
+     */
+    virtual ~Button();
+
     /**
     /**
      * Create a button with a given style and properties.
      * Create a button with a given style and properties.
      *
      *
@@ -51,10 +67,11 @@ protected:
      */
      */
     bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
     bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
 
-    Button();
-    virtual ~Button();
-
 private:
 private:
+
+    /*
+     * Constructor.
+     */
     Button(const Button& copy);
     Button(const Button& copy);
 };
 };
 
 

+ 12 - 34
gameplay/src/Camera.cpp

@@ -243,24 +243,13 @@ const Frustum& Camera::getFrustum() const
     return _bounds;
     return _bounds;
 }
 }
 
 
-void Camera::project(const Viewport* viewport, const Vector3& position, float* x, float* y, float* depth)
+void Camera::project(const Rectangle& viewport, const Vector3& position, float* x, float* y, float* depth)
 {
 {
     // Determine viewport coords to use.
     // Determine viewport coords to use.
-    float vpx, vpy, vpw, vph;
-    if (viewport)
-    {
-        vpx = viewport->getX();
-        vpy = viewport->getY();
-        vpw = viewport->getWidth();
-        vph = viewport->getHeight();
-    }
-    else
-    {
-        vpx = 0;
-        vpy = 0;
-        vpw = Game::getInstance()->getWidth();
-        vph = Game::getInstance()->getHeight();
-    }
+    float vpx = viewport.x;
+    float vpy = viewport.y;
+    float vpw = viewport.width;
+    float vph = viewport.height;
 
 
     // Transform the point to clip-space.
     // Transform the point to clip-space.
     Vector4 clipPos;
     Vector4 clipPos;
@@ -280,24 +269,13 @@ void Camera::project(const Viewport* viewport, const Vector3& position, float* x
     }
     }
 }
 }
 
 
-void Camera::unproject(const Viewport* viewport, float x, float y, float depth, Vector3* dst)
+void Camera::unproject(const Rectangle& viewport, float x, float y, float depth, Vector3* dst)
 {
 {
     // Determine viewport coords to use.
     // Determine viewport coords to use.
-    float vpx, vpy, vpw, vph;
-    if (viewport)
-    {
-        vpx = viewport->getX();
-        vpy = viewport->getY();
-        vpw = viewport->getWidth();
-        vph = viewport->getHeight();
-    }
-    else
-    {
-        vpx = 0;
-        vpy = 0;
-        vpw = Game::getInstance()->getWidth();
-        vph = Game::getInstance()->getHeight();
-    }
+    float vpx = viewport.x;
+    float vpy = viewport.y;
+    float vpw = viewport.width;
+    float vph = viewport.height;
     
     
     // Create our screen space position in NDC.
     // Create our screen space position in NDC.
     Vector4 screen(
     Vector4 screen(
@@ -325,7 +303,7 @@ void Camera::unproject(const Viewport* viewport, float x, float y, float depth,
     dst->set(screen.x, screen.y, screen.z);
     dst->set(screen.x, screen.y, screen.z);
 }
 }
 
 
-void Camera::pickRay(const Viewport* viewport, float x, float y, Ray* dst)
+void Camera::pickRay(const Rectangle& viewport, float x, float y, Ray* dst)
 {
 {
     // Get the world-space position at the near clip plane.
     // Get the world-space position at the near clip plane.
     Vector3 nearPoint;
     Vector3 nearPoint;
@@ -343,7 +321,7 @@ void Camera::pickRay(const Viewport* viewport, float x, float y, Ray* dst)
     dst->set(nearPoint, direction);
     dst->set(nearPoint, direction);
 }
 }
 
 
-Camera* Camera::clone(CloneContext &context) const
+Camera* Camera::clone(NodeCloneContext &context) const
 {
 {
     Camera* cameraClone = NULL;
     Camera* cameraClone = NULL;
     if (getCameraType() == PERSPECTIVE)
     if (getCameraType() == PERSPECTIVE)

+ 9 - 9
gameplay/src/Camera.h

@@ -4,12 +4,13 @@
 #include "Ref.h"
 #include "Ref.h"
 #include "Transform.h"
 #include "Transform.h"
 #include "Frustum.h"
 #include "Frustum.h"
-#include "Viewport.h"
+#include "Rectangle.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
 
 
 class Node;
 class Node;
+class NodeCloneContext;
 
 
 /**
 /**
  * Defines a camera which acts as a view of a scene to be rendered.
  * Defines a camera which acts as a view of a scene to be rendered.
@@ -196,13 +197,13 @@ public:
     /**
     /**
      * Projects the specified world position into the viewport coordinates.
      * Projects the specified world position into the viewport coordinates.
      *
      *
-     * @param viewport The viewport to use, or NULL to use a viewport the size of the window.
+     * @param viewport The viewport rectangle to use.
      * @param position The world space position.
      * @param position The world space position.
      * @param x The returned viewport x coordinate.
      * @param x The returned viewport x coordinate.
      * @param y The returned viewport y coordinate.
      * @param y The returned viewport y coordinate.
      * @param depth The returned pixel depth (can be NULL).
      * @param depth The returned pixel depth (can be NULL).
      */
      */
-    void project(const Viewport* viewport, const Vector3& position, float* x, float* y, float* depth = NULL);
+    void project(const Rectangle& viewport, const Vector3& position, float* x, float* y, float* depth = NULL);
 
 
     /**
     /**
      * Converts a viewport-space coordinate to a world-space position for the given depth value.
      * Converts a viewport-space coordinate to a world-space position for the given depth value.
@@ -210,23 +211,23 @@ public:
      * The depth parameter is a value ranging between 0 and 1, where 0 returns a point on the
      * The depth parameter is a value ranging between 0 and 1, where 0 returns a point on the
      * near clipping plane and 1 returns a point on the far clipping plane.
      * near clipping plane and 1 returns a point on the far clipping plane.
      *
      *
-     * @param viewport The viewport to use, or NULL to use a viewport the size of the window.
+     * @param viewport The viewport rectangle to use.
      * @param x The viewport-space x coordinate.
      * @param x The viewport-space x coordinate.
      * @param y The viewport-space y coordinate.
      * @param y The viewport-space y coordinate.
      * @param depth The depth range.
      * @param depth The depth range.
      * @param dst The world space position.
      * @param dst The world space position.
      */
      */
-    void unproject(const Viewport* viewport, float x, float y, float depth, Vector3* dst);
+    void unproject(const Rectangle& viewport, float x, float y, float depth, Vector3* dst);
 
 
     /**
     /**
      * Picks a ray that can be used for picking given the specified viewport-space coordinates.
      * Picks a ray that can be used for picking given the specified viewport-space coordinates.
      *
      *
-     * @param viewport The viewport to use, or NULL to use a viewport the size of the window.
+     * @param viewport The viewport rectangle to use.
      * @param x The viewport x-coordinate.
      * @param x The viewport x-coordinate.
      * @param y The viewport y-coordinate.
      * @param y The viewport y-coordinate.
      * @param dst The computed pick ray.
      * @param dst The computed pick ray.
      */
      */
-    void pickRay(const Viewport* viewport, float x, float y, Ray* dst);
+    void pickRay(const Rectangle& viewport, float x, float y, Ray* dst);
 
 
 private:
 private:
 
 
@@ -249,10 +250,9 @@ private:
      * Clones the camera and returns a new camera.
      * Clones the camera and returns a new camera.
      * 
      * 
      * @param context The clone context.
      * @param context The clone context.
-     * 
      * @return The newly created camera.
      * @return The newly created camera.
      */
      */
-    Camera* clone(CloneContext &context) const;
+    Camera* clone(NodeCloneContext &context) const;
 
 
     /**
     /**
      * @see Transform::Listener::transformChanged
      * @see Transform::Listener::transformChanged

+ 79 - 43
gameplay/src/CheckBox.cpp

@@ -1,5 +1,6 @@
 #include "Base.h"
 #include "Base.h"
 #include "CheckBox.h"
 #include "CheckBox.h"
+#include "Game.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -21,8 +22,8 @@ CheckBox::~CheckBox()
 CheckBox* CheckBox::create(Theme::Style* style, Properties* properties)
 CheckBox* CheckBox::create(Theme::Style* style, Properties* properties)
 {
 {
     CheckBox* checkBox = new CheckBox();
     CheckBox* checkBox = new CheckBox();
-    checkBox->init(style, properties);
-    properties->getVector2("iconSize", &checkBox->_iconSize);
+    checkBox->initialize(style, properties);
+    properties->getVector2("iconSize", &checkBox->_imageSize);
     checkBox->_checked = properties->getBool("checked");
     checkBox->_checked = properties->getBool("checked");
 
 
     return checkBox;
     return checkBox;
@@ -33,29 +34,31 @@ bool CheckBox::isChecked()
     return _checked;
     return _checked;
 }
 }
 
 
-void CheckBox::setIconSize(float width, float height)
+void CheckBox::setChecked(bool checked)
 {
 {
-    _iconSize.set(width, height);
+    if (_checked != checked)
+    {
+        _checked = checked;
+        notifyListeners(Control::Listener::VALUE_CHANGED);
+    }
 }
 }
 
 
-const Vector2& CheckBox::getIconSize() const
+void CheckBox::setImageSize(float width, float height)
 {
 {
-    Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-    Theme::Icon* icon = overlay->getCheckBoxIcon();
-    if (_iconSize.isZero() && icon)
-    {
-        return icon->getSize();
-    }
+    _imageSize.set(width, height);
+}
 
 
-    return _iconSize;
+const Vector2& CheckBox::getImageSize() const
+{
+    return _imageSize;
 }
 }
 
 
 void CheckBox::addListener(Control::Listener* listener, int eventFlags)
 void CheckBox::addListener(Control::Listener* listener, int eventFlags)
 {
 {
-    if ((eventFlags & Listener::TEXT_CHANGED) == Listener::TEXT_CHANGED)
+    if ((eventFlags & Control::Listener::TEXT_CHANGED) == Control::Listener::TEXT_CHANGED)
     {
     {
         assert("TEXT_CHANGED event is not applicable to CheckBox.");
         assert("TEXT_CHANGED event is not applicable to CheckBox.");
-        eventFlags &= ~Listener::TEXT_CHANGED;
+        eventFlags &= ~Control::Listener::TEXT_CHANGED;
     }
     }
 
 
     Control::addListener(listener, eventFlags);
     Control::addListener(listener, eventFlags);
@@ -74,11 +77,19 @@ bool CheckBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int cont
         {
         {
             if (_state == Control::ACTIVE)
             if (_state == Control::ACTIVE)
             {
             {
-                if (x > 0 && x <= _bounds.width &&
-                    y > 0 && y <= _bounds.height)
+                if (x > 0 && x <= _clipBounds.width &&
+                    y > 0 && y <= _clipBounds.height)
                 {
                 {
                     _checked = !_checked;
                     _checked = !_checked;
-                    notifyListeners(Listener::VALUE_CHANGED);
+                    notifyListeners(Control::Listener::VALUE_CHANGED);
+
+                    // Animate between icons.  Old fades out, then the new fades in.
+                    /*
+                    AnimationController* animationController = Game::getInstance()->getAnimationController();
+                    float from[1] = { 1.0f };
+                    float to[1] = { 0.0f };
+                    animationController->createAnimationFromTo("CheckBox::toggle", this, CheckBox::ANIMATE_SPRITE_ALPHA, from, to, Curve::QUADRATIC_IN_OUT, 200L);
+                    */
                 }
                 }
             }
             }
         }
         }
@@ -92,12 +103,23 @@ void CheckBox::update(const Rectangle& clip)
 {
 {
     Control::update(clip);
     Control::update(clip);
 
 
-    Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-    Theme::Icon* icon = overlay->getCheckBoxIcon();
-    Vector2& size = _iconSize;
-    if (_iconSize.isZero() && icon)
+    Vector2 size;
+    if (_imageSize.isZero())
     {
     {
-        size = icon->getSize();
+        if (_checked)
+        {
+            const Rectangle& selectedRegion = getImageRegion("checked", _state);
+            size.set(selectedRegion.width, selectedRegion.height);
+        }
+        else
+        {
+            const Rectangle& unselectedRegion = getImageRegion("unchecked", _state);
+            size.set(unselectedRegion.width, unselectedRegion.height);
+        }
+    }
+    else
+    {
+        size.set(_imageSize);
     }
     }
     float iconWidth = size.x;
     float iconWidth = size.x;
 
 
@@ -105,43 +127,57 @@ void CheckBox::update(const Rectangle& clip)
     _textBounds.width -= iconWidth;
     _textBounds.width -= iconWidth;
 }
 }
 
 
-void CheckBox::drawSprites(SpriteBatch* spriteBatch, const Rectangle& clip)
+void CheckBox::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
 {
 {
     // Left, v-center.
     // Left, v-center.
     // TODO: Set an alignment for icons.
     // TODO: Set an alignment for icons.
-    Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-    Theme::Icon* icon = overlay->getCheckBoxIcon();
-    if (icon)
+    const Theme::Border border = getBorder(_state);
+    const Theme::Padding padding = getPadding();
+    float opacity = getOpacity(_state);
+
+    if (_checked)
     {
     {
-        const Theme::ContainerRegion* containerRegion = overlay->getContainerRegion();
-        Theme::Border border;
-        if (containerRegion)
+        const Rectangle& selectedRegion = getImageRegion("checked", _state);
+        const Theme::UVs& selected = getImageUVs("checked", _state);
+        Vector4 selectedColor = getImageColor("checked", _state);
+        selectedColor.w *= opacity;
+
+        Vector2 size;
+        if (_imageSize.isZero())
         {
         {
-                border = containerRegion->getBorder();
+            size.set(selectedRegion.width, selectedRegion.height);
         }
         }
-        const Theme::Padding padding = _style->getPadding();
-
-        Vector2& size = _iconSize;
-        if (_iconSize.isZero())
+        else
         {
         {
-            size = icon->getSize();
+            size.set(_imageSize);
         }
         }
 
 
-        const Vector4 color = icon->getColor();
+        Vector2 pos(clip.x + _bounds.x + border.left + padding.left,
+            clip.y + _bounds.y + (_clipBounds.height - border.bottom - padding.bottom) / 2.0f - size.y / 2.0f);
 
 
-        Vector2 pos(clip.x + _position.x + border.left + padding.left,
-            clip.y + _position.y + (_bounds.height - border.bottom - padding.bottom) / 2.0f - size.y / 2.0f);
+        spriteBatch->draw(pos.x, pos.y, size.x, size.y, selected.u1, selected.v1, selected.u2, selected.v2, selectedColor, _clip);
+    }
+    else
+    {
+        const Rectangle& unselectedRegion = getImageRegion("unchecked", _state);
+        const Theme::UVs& unselected = getImageUVs("unchecked", _state);
+        Vector4 unselectedColor = getImageColor("unchecked", _state);
+        unselectedColor.w *= opacity;
 
 
-        if (_checked)
+        Vector2 size;
+        if (_imageSize.isZero())
         {
         {
-            const Theme::UVs on = icon->getOnUVs();
-            spriteBatch->draw(pos.x, pos.y, size.x, size.y, on.u1, on.v1, on.u2, on.v2, color, _clip);
+            size.set(unselectedRegion.width, unselectedRegion.height);
         }
         }
         else
         else
         {
         {
-            const Theme::UVs off = icon->getOffUVs();
-            spriteBatch->draw(pos.x, pos.y, size.x, size.y, off.u1, off.v1, off.u2, off.v2, color, _clip);
+            size.set(_imageSize);
         }
         }
+
+        Vector2 pos(clip.x + _bounds.x + border.left + padding.left,
+            clip.y + _bounds.y + (_clipBounds.height - border.bottom - padding.bottom) / 2.0f - size.y / 2.0f);
+
+        spriteBatch->draw(pos.x, pos.y, size.x, size.y, unselected.u1, unselected.v1, unselected.u2, unselected.v2, unselectedColor, _clip);
     }
     }
 }
 }
 
 

+ 28 - 8
gameplay/src/CheckBox.h

@@ -14,11 +14,16 @@ namespace gameplay
  *
  *
  * The following properties are available for checkboxes:
  * The following properties are available for checkboxes:
  *
  *
- * checkBox <CheckBox ID>
+ * checkBox <checkBoxID>
  * {
  * {
- *      style       = <Style ID>
+ *      style       = <styleID>
+ *      alignment   = <Control::Alignment constant> // Note: 'position' will be ignored.
  *      position    = <x, y>
  *      position    = <x, y>
+ *      autoWidth   = <bool>
+ *      autoHeight  = <bool>
  *      size        = <width, height>
  *      size        = <width, height>
+ *      width       = <width>   // Can be used in place of 'size', e.g. with 'autoHeight = true'
+ *      height      = <height>  // Can be used in place of 'size', e.g. with 'autoWidth = true'
  *      text        = <string>
  *      text        = <string>
  *      checked     = <bool>
  *      checked     = <bool>
  *      iconSize    = <width, height>   // The size to draw the checkbox icon, if different from its size in the texture.
  *      iconSize    = <width, height>   // The size to draw the checkbox icon, if different from its size in the texture.
@@ -29,6 +34,7 @@ class CheckBox : public Button
     friend class Container;
     friend class Container;
 
 
 public:
 public:
+
     /**
     /**
      * Gets whether this checkbox is checked.
      * Gets whether this checkbox is checked.
      *
      *
@@ -36,20 +42,22 @@ public:
      */
      */
     bool isChecked();
     bool isChecked();
 
 
+    void setChecked(bool checked);
+
     /**
     /**
      * Set the size to draw the checkbox icon.
      * Set the size to draw the checkbox icon.
      *
      *
      * @param width The width to draw the checkbox icon.
      * @param width The width to draw the checkbox icon.
      * @param height The height to draw the checkbox icon.
      * @param height The height to draw the checkbox icon.
      */
      */
-    void setIconSize(float width, float height);
+    void setImageSize(float width, float height);
 
 
     /**
     /**
      * Get the size at which the checkbox icon will be drawn.
      * Get the size at which the checkbox icon will be drawn.
      *
      *
      * @return The size of the checkbox icon.
      * @return The size of the checkbox icon.
      */
      */
-    const Vector2& getIconSize() const;
+    const Vector2& getImageSize() const;
 
 
     /**
     /**
      * Add a listener to be notified of specific events affecting
      * Add a listener to be notified of specific events affecting
@@ -64,7 +72,15 @@ public:
     virtual void addListener(Control::Listener* listener, int eventFlags);
     virtual void addListener(Control::Listener* listener, int eventFlags);
 
 
 protected:
 protected:
+
+    /**
+     * Constructor.
+     */
     CheckBox();
     CheckBox();
+
+    /**
+     * Destructor.
+     */
     ~CheckBox();
     ~CheckBox();
 
 
     /**
     /**
@@ -95,7 +111,7 @@ protected:
      * Called when a control's properties change.  Updates this control's internal rendering
      * Called when a control's properties change.  Updates this control's internal rendering
      * properties, such as its text viewport.
      * properties, such as its text viewport.
      *
      *
-     * @param position The control's position within its container.
+     * @param clip The clipping rectangle of this control's parent container.
      */
      */
     void update(const Rectangle& clip);
     void update(const Rectangle& clip);
 
 
@@ -103,14 +119,18 @@ protected:
      * Draw the checkbox icon associated with this control.
      * Draw the checkbox icon associated with this control.
      *
      *
      * @param spriteBatch The sprite batch containing this control's icons.
      * @param spriteBatch The sprite batch containing this control's icons.
-     * @param position The container position this control is relative to.
+     * @param clip The container position this control is relative to.
      */
      */
-    void drawSprites(SpriteBatch* spriteBatch, const Rectangle& clip);
+    void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
 
 
     bool _checked;      // Whether this checkbox is currently checked.
     bool _checked;      // Whether this checkbox is currently checked.
-    Vector2 _iconSize;  // The size to draw the checkbox icon, if different from its size in the texture.
+    Vector2 _imageSize;  // The size to draw the checkbox icon, if different from its size in the texture.
 
 
 private:
 private:
+
+    /*
+     * Constructor.
+     */
     CheckBox(const CheckBox& copy);
     CheckBox(const CheckBox& copy);
 };
 };
 
 

+ 0 - 38
gameplay/src/CloneContext.cpp

@@ -1,38 +0,0 @@
-#include "CloneContext.h"
-
-namespace gameplay
-{
-
-CloneContext::CloneContext()
-{
-    
-}
-
-CloneContext::~CloneContext()
-{
-
-}
-
-Animation* CloneContext::findClonedAnimation(const Animation* animation)
-{
-    AnimationMap::iterator it = _clonedAnimations.find(animation);
-    return it != _clonedAnimations.end() ? it->second : NULL;
-}
-
-void CloneContext::registerClonedAnimation(const Animation* original, Animation* clone)
-{
-    _clonedAnimations[original] = clone;
-}
-
-Node* CloneContext::findClonedNode(const Node* node)
-{
-    NodeMap::iterator it = _clonedNodes.find(node);
-    return it != _clonedNodes.end() ? it->second : NULL;
-}
-
-void CloneContext::registerClonedNode(const Node* original, Node* clone)
-{
-    _clonedNodes[original] = clone;
-}
-
-}

+ 0 - 86
gameplay/src/CloneContext.h

@@ -1,86 +0,0 @@
-#ifndef CLONECONTEXT_H_
-#define CLONECONTEXT_H_
-
-#include <map>
-
-namespace gameplay
-{
-    class Animation;
-    class Node;
-
-/**
- * CloneContext represents the context data that is kept when cloning a node.
- * 
- * The CloneContext is used to make sure objects don't get cloned twice.
- */
-class CloneContext
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    CloneContext();
-
-    /**
-     * Destructor.
-     */
-    ~CloneContext();
-
-    /**
-     * Finds the cloned animation of the given animation or NULL if this animation was not registered with this context.
-     * 
-     * @param animation The animation to search for the cloned copy of.
-     * 
-     * @return The cloned animation or NULL if not found.
-     */
-    Animation* findClonedAnimation(const Animation* animation);
-
-    /**
-     * Registers the cloned animation with this context so that it doesn't get cloned twice.
-     * 
-     * @param original The pointer to the original animation.
-     * @param clone The pointer to the cloned animation.
-     */
-    void registerClonedAnimation(const Animation* original, Animation* clone);
-
-    /**
-     * Finds the cloned node of the given node or NULL if this node was not registered with this context.
-     * 
-     * @param node The node to search for the cloned copy of.
-     * 
-     * @return The cloned node or NULL if not found.
-     */
-    Node* findClonedNode(const Node* node);
-
-    /**
-     * Registers the cloned node with this context so that it doens't get cloned twice.
-     * 
-     * @param original The pointer to the original node.
-     * @param clone The pointer to the cloned node.
-     */
-    void registerClonedNode(const Node* original, Node* clone);
-
-private:
-    
-    /**
-     * Hidden copy constructor.
-     */
-    CloneContext(const CloneContext&);
-
-    /**
-     * Hidden copy assignment operator.
-     */
-    CloneContext& operator=(const CloneContext&);
-
-private:
-    typedef std::map<const Animation*, Animation*> AnimationMap;
-    typedef std::map<const Node*, Node*> NodeMap;
-
-    AnimationMap _clonedAnimations;
-    NodeMap _clonedNodes;
-};
-
-}
-
-#endif

+ 31 - 20
gameplay/src/Container.cpp

@@ -56,7 +56,7 @@ namespace gameplay
     {
     {
         const char* layoutString = properties->getString("layout");
         const char* layoutString = properties->getString("layout");
         Container* container = Container::create(getLayoutType(layoutString));
         Container* container = Container::create(getLayoutType(layoutString));
-        container->init(style, properties);
+        container->initialize(style, properties);
         container->addControls(theme, properties);
         container->addControls(theme, properties);
 
 
         return container;
         return container;
@@ -202,15 +202,36 @@ namespace gameplay
         return _controls;
         return _controls;
     }
     }
 
 
+    Animation* Container::getAnimation(const char* id) const
+    {
+        std::vector<Control*>::const_iterator itr = _controls.begin();
+        std::vector<Control*>::const_iterator end = _controls.end();
+        
+        Control* control = NULL;
+        for (; itr != end; itr++)
+        {
+            control = *itr;
+            Animation* animation = control->getAnimation(id);
+            if (animation)
+                return animation;
+
+            if (control->isContainer())
+            {
+                animation = ((Container*)control)->getAnimation(id);
+                if (animation)
+                    return animation;
+            }
+        }
+
+        return NULL;
+    }
+
     void Container::update(const Rectangle& clip)
     void Container::update(const Rectangle& clip)
     {
     {
         // Update this container's viewport.
         // Update this container's viewport.
         Control::update(clip);
         Control::update(clip);
 
 
-        if (isDirty())
-        {
-            _layout->update(this);
-        }
+        _layout->update(this);
     }
     }
 
 
     void Container::drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip)
     void Container::drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip)
@@ -219,8 +240,6 @@ namespace gameplay
         Control::drawBorder(spriteBatch, clip);
         Control::drawBorder(spriteBatch, clip);
 
 
         // Now call drawBorder on all controls within this container.
         // Now call drawBorder on all controls within this container.
-        //Vector2 pos(clip.x + _position.x, clip.y + _position.y);
-        //const Rectangle newClip(clip.x + _position.x, clip.y + _position.y, _size.x, _size.y);
         std::vector<Control*>::const_iterator it;
         std::vector<Control*>::const_iterator it;
         for (it = _controls.begin(); it < _controls.end(); it++)
         for (it = _controls.begin(); it < _controls.end(); it++)
         {
         {
@@ -229,14 +248,13 @@ namespace gameplay
         }
         }
     }
     }
 
 
-    void Container::drawSprites(SpriteBatch* spriteBatch, const Rectangle& clip)
+    void Container::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
     {
     {
-        //const Rectangle newClip(clip.x + _position.x, clip.y + _position.y, _size.x, _size.y);
         std::vector<Control*>::const_iterator it;
         std::vector<Control*>::const_iterator it;
         for (it = _controls.begin(); it < _controls.end(); it++)
         for (it = _controls.begin(); it < _controls.end(); it++)
         {
         {
             Control* control = *it;
             Control* control = *it;
-            control->drawSprites(spriteBatch, _clip);
+            control->drawImages(spriteBatch, _clip);
         }
         }
 
 
         _dirty = false;
         _dirty = false;
@@ -244,7 +262,6 @@ namespace gameplay
 
 
     void Container::drawText(const Rectangle& clip)
     void Container::drawText(const Rectangle& clip)
     {
     {
-        //const Rectangle newClip(clip.x + _position.x, clip.y + _position.y, _size.x, _size.y);
         std::vector<Control*>::const_iterator it;
         std::vector<Control*>::const_iterator it;
         for (it = _controls.begin(); it < _controls.end(); it++)
         for (it = _controls.begin(); it < _controls.end(); it++)
         {
         {
@@ -285,14 +302,8 @@ namespace gameplay
 
 
         bool eventConsumed = false;
         bool eventConsumed = false;
 
 
-        Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-        Theme::Border border;
-        Theme::ContainerRegion* containerRegion = overlay->getContainerRegion();
-        if (containerRegion)
-        {
-            border = overlay->getContainerRegion()->getBorder();
-        }
-        Theme::Padding padding = _style->getPadding();
+        const Theme::Border& border = getBorder(_state);
+        const Theme::Padding& padding = getPadding();
         float xPos = border.left + padding.left;
         float xPos = border.left + padding.left;
         float yPos = border.top + padding.top;
         float yPos = border.top + padding.top;
 
 
@@ -305,7 +316,7 @@ namespace gameplay
                 continue;
                 continue;
             }
             }
 
 
-            const Rectangle& bounds = control->getBounds();
+            const Rectangle& bounds = control->getClipBounds();
             if (control->getState() != Control::NORMAL ||
             if (control->getState() != Control::NORMAL ||
                 (evt == Touch::TOUCH_PRESS &&
                 (evt == Touch::TOUCH_PRESS &&
                  x >= xPos + bounds.x &&
                  x >= xPos + bounds.x &&

+ 42 - 15
gameplay/src/Container.h

@@ -12,27 +12,37 @@ namespace gameplay
  *
  *
  * The following properties are available for containers:
  * The following properties are available for containers:
  *
  *
- * container <Container ID>
+ * container <containerID>
  * {
  * {
  *      // Container properties.
  *      // Container properties.
- *      layout   = <Layout Type>        // A value from the Layout::Type enum.  E.g.: LAYOUT_VERTICAL
- *      style    = <Style ID>           // A style from the form's theme.
- *      position = <x, y>               // Position of the container on-screen, measured in pixels.
- *      size     = <width, height>      // Size of the container, measured in pixels.
+ *      layout   = <Layout::Type>        // A value from the Layout::Type enum.  E.g.: LAYOUT_VERTICAL
+ *      style    = <styleID>           // A style from the form's theme.
+ *      alignment   = <Control::Alignment constant> // Note: 'position' will be ignored.
+ *      position    = <x, y>    // Position of the container on-screen, measured in pixels.
+ *      autoWidth   = <bool>
+ *      autoHeight  = <bool>
+ *      size        = <width, height>   // Size of the container, measured in pixels.
+ *      width       = <width>   // Can be used in place of 'size', e.g. with 'autoHeight = true'
+ *      height      = <height>  // Can be used in place of 'size', e.g. with 'autoWidth = true'
  *   
  *   
- *      // All the controls within this container.
- *      container{}
- *      label{}
- *      textBox{}
- *      button{}
- *      checkBox{}
- *      radioButton{}
- *      slider{}
+ *      // All the nested controls within this container.
+ *      container 
+ *      { 
+ *          ...
+ *      }
+ * 
+ *      label { }
+ *      textBox { }
+ *      button { }
+ *      checkBox { }
+ *      radioButton { }
+ *      slider { }
  * }
  * }
  */
  */
 class Container : public Control
 class Container : public Control
 {
 {
 public:
 public:
+
     /**
     /**
      * Get this container's layout.
      * Get this container's layout.
      *
      *
@@ -68,7 +78,7 @@ public:
     /**
     /**
      * Remove a control with the given ID.
      * Remove a control with the given ID.
      *
      *
-     * @param ID The ID of the control to remove.
+     * @param id The ID of the control to remove.
      */
      */
     void removeControl(const char* id);
     void removeControl(const char* id);
 
 
@@ -102,8 +112,24 @@ public:
      */
      */
     std::vector<Control*> getControls() const;
     std::vector<Control*> getControls() const;
 
 
+    /**
+     * Gets the first animation in the control with the specified ID.
+     *
+     * @param id The ID of the animation to get. Returns the first animation if ID is NULL.
+     * @return The first animation with the specified ID.
+     */
+    Animation* getAnimation(const char* id = NULL) const;
+
 protected:
 protected:
+
+    /**
+     * Constructor.
+     */
     Container();
     Container();
+
+    /**
+     * Destructor.
+     */
     virtual ~Container();
     virtual ~Container();
 
 
     /**
     /**
@@ -146,7 +172,7 @@ protected:
      * @param spriteBatch The sprite batch containing this control's icons.
      * @param spriteBatch The sprite batch containing this control's icons.
      * @param clip The clipping rectangle of this container's parent container.
      * @param clip The clipping rectangle of this container's parent container.
      */
      */
-    virtual void drawSprites(SpriteBatch* spriteBatch, const Rectangle& clip);
+    virtual void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
 
 
     /**
     /**
      * Draws the text of all controls within this container.
      * Draws the text of all controls within this container.
@@ -207,6 +233,7 @@ protected:
     std::vector<Control*> _controls;    // List of controls within this container.
     std::vector<Control*> _controls;    // List of controls within this container.
 
 
 private:
 private:
+
     Container(const Container& copy);
     Container(const Container& copy);
 };
 };
 
 

+ 724 - 101
gameplay/src/Control.cpp

@@ -1,11 +1,12 @@
 #include "Base.h"
 #include "Base.h"
+#include "Game.h"
 #include "Control.h"
 #include "Control.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
     Control::Control()
     Control::Control()
-        : _id(""), _state(Control::NORMAL), _position(Vector2::zero()), _size(Vector2::zero()), _bounds(Rectangle::empty()), _clip(Rectangle::empty()),
-          _autoWidth(true), _autoHeight(true), _dirty(true), _consumeTouchEvents(true), _listeners(NULL)
+        : _id(""), _state(Control::NORMAL), _bounds(Rectangle::empty()), _clipBounds(Rectangle::empty()), _clip(Rectangle::empty()),
+            _dirty(true), _consumeTouchEvents(true), _listeners(NULL), _styleOverridden(false)
     {
     {
     }
     }
 
 
@@ -17,29 +18,56 @@ namespace gameplay
     {
     {
         if (_listeners)
         if (_listeners)
         {
         {
-            for (ListenerMap::const_iterator itr = _listeners->begin(); itr != _listeners->end(); itr++)
+            for (std::map<Listener::EventType, std::list<Listener*>*>::const_iterator itr = _listeners->begin(); itr != _listeners->end(); itr++)
             {
             {
                 std::list<Listener*>* list = itr->second;
                 std::list<Listener*>* list = itr->second;
                 SAFE_DELETE(list);
                 SAFE_DELETE(list);
             }
             }
             SAFE_DELETE(_listeners);
             SAFE_DELETE(_listeners);
         }
         }
+
+        if (_styleOverridden)
+        {
+            SAFE_DELETE(_style);
+        }
     }
     }
 
 
-    void Control::init(Theme::Style* style, Properties* properties)
+    void Control::initialize(Theme::Style* style, Properties* properties)
     {
     {
         _style = style;
         _style = style;
 
 
-        properties->getVector2("position", &_position);
-        properties->getVector2("size", &_size);
+        _alignment = getAlignment(properties->getString("alignment"));
+        _autoWidth = properties->getBool("autoWidth");
+        _autoHeight = properties->getBool("autoHeight");
+
+        Vector2 position;
+        Vector2 size;
+        if (properties->exists("position"))
+        {
+            properties->getVector2("position", &position);
+        }
+        else
+        {
+            position.x = properties->getFloat("x");
+            position.y = properties->getFloat("y");
+        }
+        
+        if (properties->exists("size"))
+        {
+            properties->getVector2("size", &size);
+        }
+        else
+        {
+            size.x = properties->getFloat("width");
+            size.y = properties->getFloat("height");
+        }
+        _bounds.set(position.x, position.y, size.x, size.y);
 
 
-        _state = Control::getStateFromString(properties->getString("state"));
+        _state = Control::getState(properties->getString("state"));
 
 
         const char* id = properties->getId();
         const char* id = properties->getId();
         if (id)
         if (id)
-        {
             _id = id;
             _id = id;
-        }
     }
     }
 
 
     const char* Control::getID() const
     const char* Control::getID() const
@@ -49,22 +77,21 @@ namespace gameplay
 
 
     void Control::setPosition(float x, float y)
     void Control::setPosition(float x, float y)
     {
     {
-        _position.set(x, y);
-    }
-
-    const Vector2& Control::getPosition() const
-    {
-        return _position;
+        _bounds.x = x;
+        _bounds.y = y;
+        _dirty = true;
     }
     }
 
 
     void Control::setSize(float width, float height)
     void Control::setSize(float width, float height)
     {
     {
-        _size.set(width, height);
+        _bounds.width = width;
+        _bounds.height = height;
+        _dirty = true;
     }
     }
 
 
-    const Vector2& Control::getSize() const
+    void Control::setBounds(const Rectangle& bounds)
     {
     {
-        return _size;
+        _bounds.set(bounds);
     }
     }
 
 
     const Rectangle& Control::getBounds() const
     const Rectangle& Control::getBounds() const
@@ -72,15 +99,343 @@ namespace gameplay
         return _bounds;
         return _bounds;
     }
     }
 
 
-    const Rectangle& Control::getClip() const
+    float Control::getX() const
     {
     {
-        return _clip;
+        return _bounds.x;
+    }
+
+    float Control::getY() const
+    {
+        return _bounds.y;
     }
     }
 
 
-    void Control::setAutoSize(bool width, bool height)
+    float Control::getWidth() const
     {
     {
-        _autoWidth = width;
-        _autoHeight = height;
+        return _bounds.width;
+    }
+
+    float Control::getHeight() const
+    {
+        return _bounds.height;
+    }
+
+    void Control::setAlignment(Alignment alignment)
+    {
+        _alignment = alignment;
+    }
+
+    Control::Alignment Control::getAlignment() const
+    {
+        return _alignment;
+    }
+
+    void Control::setAutoWidth(bool autoWidth)
+    {
+        _autoWidth = autoWidth;
+    }
+
+    bool Control::getAutoWidth() const
+    {
+        return _autoWidth;
+    }
+
+    void Control::setAutoHeight(bool autoHeight)
+    {
+        _autoHeight = autoHeight;
+    }
+
+    void Control::setOpacity(float opacity, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setOpacity(opacity);
+        }
+        
+        _dirty = true;
+    }
+
+    float Control::getOpacity(State state) const
+    {
+        return getOverlay(state)->getOpacity();
+    }
+
+    void Control::setBorder(float top, float bottom, float left, float right, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setBorder(top, bottom, left, right);
+        }
+
+        _dirty = true;
+    }
+
+    const Theme::Border& Control::getBorder(State state) const
+    {
+        return getOverlay(state)->getBorder();
+    }
+
+    void Control::setSkinRegion(const Rectangle& region, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setSkinRegion(region, _style->_tw, _style->_th);
+        }
+
+        _dirty = true;
+    }
+
+    const Rectangle& Control::getSkinRegion(State state) const
+    {
+        return getOverlay(state)->getSkinRegion();
+    }
+
+    const Theme::UVs& Control::getSkinUVs(Theme::Skin::SkinArea area, State state) const
+    {
+        return getOverlay(state)->getSkinUVs(area);
+    }
+
+    void Control::setSkinColor(const Vector4& color, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setSkinColor(color);
+        }
+
+        _dirty = true;
+    }
+
+    const Vector4& Control::getSkinColor(State state) const
+    {
+        return getOverlay(state)->getSkinColor();
+    }
+
+    void Control::setMargin(float top, float bottom, float left, float right)
+    {
+        _style->setMargin(top, bottom, left, right);
+        _dirty = true;
+    }
+
+    const Theme::Margin& Control::getMargin() const
+    {
+        return _style->getMargin();
+    }
+
+    void Control::setPadding(float top, float bottom, float left, float right)
+    {
+        _style->setPadding(top, bottom, left, right);
+        _dirty = true;
+    }
+    
+    const Theme::Padding& Control::getPadding() const
+    {
+        return _style->getPadding();
+    }
+
+    void Control::setImageRegion(const char* id, const Rectangle& region, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setImageRegion(id, region, _style->_tw, _style->_th);
+        }
+
+        _dirty = true;
+    }
+
+    const Rectangle& Control::getImageRegion(const char* id, State state) const
+    {
+        return getOverlay(state)->getImageRegion(id);
+    }
+
+    void Control::setImageColor(const char* id, const Vector4& color, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setImageColor(id, color);
+        }
+
+        _dirty = true;
+    }
+
+    const Vector4& Control::getImageColor(const char* id, State state) const
+    {
+        return getOverlay(state)->getImageColor(id);
+    }
+
+    const Theme::UVs& Control::getImageUVs(const char* id, State state) const
+    {
+        return getOverlay(state)->getImageUVs(id);
+    }
+
+    void Control::setCursorRegion(const Rectangle& region, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setCursorRegion(region, _style->_tw, _style->_th);
+        }
+
+        _dirty = true;
+    }
+
+    const Rectangle& Control::getCursorRegion(State state) const
+    {
+        return getOverlay(state)->getCursorRegion();
+    }
+
+    void Control::setCursorColor(const Vector4& color, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setCursorColor(color);
+        }
+
+        _dirty = true;
+    }
+
+    const Vector4& Control::getCursorColor(State state)
+    {
+        return getOverlay(state)->getCursorColor();
+    }
+    
+    const Theme::UVs& Control::getCursorUVs(State state)
+    {
+        return getOverlay(state)->getCursorUVs();
+    }
+
+    void Control::setFont(Font* font, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setFont(font);
+        }
+
+        _dirty = true;
+    }
+
+    Font* Control::getFont(State state) const
+    {
+        return getOverlay(state)->getFont();
+    }
+
+    void Control::setFontSize(unsigned int fontSize, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setFontSize(fontSize);
+        }
+
+        _dirty = true;
+    }
+
+    unsigned int Control::getFontSize(State state) const
+    {
+        return getOverlay(state)->getFontSize();
+    }
+
+    void Control::setTextColor(const Vector4& color, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setTextColor(color);
+        }
+
+        _dirty = true;
+    }
+
+    const Vector4& Control::getTextColor(State state) const
+    {
+        return getOverlay(state)->getTextColor();
+    }
+
+    void Control::setTextAlignment(Font::Justify alignment, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setTextAlignment(alignment);
+        }
+
+        _dirty = true;
+    }
+
+    Font::Justify Control::getTextAlignment(State state) const
+    {
+        return getOverlay(state)->getTextAlignment();
+    }
+
+    void Control::setTextRightToLeft(bool rightToLeft, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setTextRightToLeft(rightToLeft);
+        }
+
+        _dirty = true;
+    }
+
+    bool Control::getTextRightToLeft(State state) const
+    {
+        return getOverlay(state)->getTextRightToLeft();
+    }
+
+    const Rectangle& Control::getClipBounds() const
+    {
+        return _clipBounds;
+    }
+
+    const Rectangle& Control::getClip() const
+    {
+        return _clip;
     }
     }
 
 
     void Control::setStyle(Theme::Style* style)
     void Control::setStyle(Theme::Style* style)
@@ -101,9 +456,10 @@ namespace gameplay
     void Control::setState(State state)
     void Control::setState(State state)
     {
     {
         _state = state;
         _state = state;
+        _dirty = true;
     }
     }
 
 
-    Control::State Control::getState()
+    Control::State Control::getState() const
     {
     {
         return _state;
         return _state;
     }
     }
@@ -111,11 +467,13 @@ namespace gameplay
     void Control::disable()
     void Control::disable()
     {
     {
         _state = DISABLED;
         _state = DISABLED;
+        _dirty = true;
     }
     }
 
 
     void Control::enable()
     void Control::enable()
     {
     {
         _state = NORMAL;
         _state = NORMAL;
+        _dirty = true;
     }
     }
 
 
     bool Control::isEnabled()
     bool Control::isEnabled()
@@ -185,7 +543,7 @@ namespace gameplay
             _listeners = new std::map<Listener::EventType, std::list<Listener*>*>();
             _listeners = new std::map<Listener::EventType, std::list<Listener*>*>();
         }
         }
 
 
-        ListenerMap::const_iterator itr = _listeners->find(eventType);
+        std::map<Listener::EventType, std::list<Listener*>*>::const_iterator itr = _listeners->find(eventType);
         if (itr == _listeners->end())
         if (itr == _listeners->end())
         {
         {
             _listeners->insert(std::make_pair(eventType, new std::list<Listener*>()));
             _listeners->insert(std::make_pair(eventType, new std::list<Listener*>()));
@@ -214,8 +572,8 @@ namespace gameplay
             notifyListeners(Listener::RELEASE);
             notifyListeners(Listener::RELEASE);
 
 
             // Only trigger Listener::CLICK if both PRESS and RELEASE took place within the control's bounds.
             // Only trigger Listener::CLICK if both PRESS and RELEASE took place within the control's bounds.
-            if (x > 0 && x <= _bounds.width &&
-                y > 0 && y <= _bounds.height)
+            if (x > 0 && x <= _clipBounds.width &&
+                y > 0 && y <= _clipBounds.height)
             {
             {
                 notifyListeners(Listener::CLICK);
                 notifyListeners(Listener::CLICK);
             }
             }
@@ -233,7 +591,7 @@ namespace gameplay
     {
     {
         if (_listeners)
         if (_listeners)
         {
         {
-            ListenerMap::const_iterator itr = _listeners->find(eventType);
+            std::map<Listener::EventType, std::list<Listener*>*>::const_iterator itr = _listeners->find(eventType);
             if (itr != _listeners->end())
             if (itr != _listeners->end())
             {
             {
                 std::list<Listener*>* listenerList = itr->second;
                 std::list<Listener*>* listenerList = itr->second;
@@ -248,10 +606,10 @@ namespace gameplay
     void Control::update(const Rectangle& clip)
     void Control::update(const Rectangle& clip)
     {
     {
         // Calculate the bounds.
         // Calculate the bounds.
-        float x = clip.x + _position.x;
-        float y = clip.y + _position.y;
-        float width = _size.x;
-        float height = _size.y;
+        float x = clip.x + _bounds.x;
+        float y = clip.y + _bounds.y;
+        float width = _bounds.width;
+        float height = _bounds.height;
 
 
         float clipX2 = clip.x + clip.width;
         float clipX2 = clip.x + clip.width;
         float x2 = x + width;
         float x2 = x + width;
@@ -267,22 +625,16 @@ namespace gameplay
             height = clipY2 - y;
             height = clipY2 - y;
         }
         }
 
 
-        _bounds.set(_position.x, _position.y, width, height);
+        _clipBounds.set(_bounds.x, _bounds.y, width, height);
 
 
         // Calculate the clipping viewport.
         // Calculate the clipping viewport.
-        Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-        Theme::Border border;
-        Theme::ContainerRegion* containerRegion = overlay->getContainerRegion();
-        if (containerRegion)
-        {
-            border = overlay->getContainerRegion()->getBorder();
-        }
-        Theme::Padding padding = _style->getPadding();
+        const Theme::Border& border = getBorder(_state);
+        const Theme::Padding& padding = getPadding();
 
 
         x +=  border.left + padding.left;
         x +=  border.left + padding.left;
         y +=  border.top + padding.top;
         y +=  border.top + padding.top;
-        width = _size.x - border.left - padding.left - border.right - padding.right;
-        height = _size.y - border.top - padding.top - border.bottom - padding.bottom;
+        width = _bounds.width - border.left - padding.left - border.right - padding.right;
+        height = _bounds.height - border.top - padding.top - border.bottom - padding.bottom;
 
 
         _textBounds.set(x, y, width, height);
         _textBounds.set(x, y, width, height);
 
 
@@ -315,68 +667,64 @@ namespace gameplay
 
 
     void Control::drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip)
     void Control::drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip)
     {
     {
-        Vector2 pos(clip.x + _position.x, clip.y + _position.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.
-        Theme::ContainerRegion* containerRegion = _style->getOverlay(getOverlayType())->getContainerRegion();
-        if (containerRegion)
-        {
-            // Get the UVs.
-            Theme::UVs topLeft, top, topRight, left, center, right, bottomLeft, bottom, bottomRight;
-            topLeft = containerRegion->getUVs(Theme::ContainerRegion::TOP_LEFT);
-            top = containerRegion->getUVs(Theme::ContainerRegion::TOP);
-            topRight = containerRegion->getUVs(Theme::ContainerRegion::TOP_RIGHT);
-            left = containerRegion->getUVs(Theme::ContainerRegion::LEFT);
-            center = containerRegion->getUVs(Theme::ContainerRegion::CENTER);
-            right = containerRegion->getUVs(Theme::ContainerRegion::RIGHT);
-            bottomLeft = containerRegion->getUVs(Theme::ContainerRegion::BOTTOM_LEFT);
-            bottom = containerRegion->getUVs(Theme::ContainerRegion::BOTTOM);
-            bottomRight = containerRegion->getUVs(Theme::ContainerRegion::BOTTOM_RIGHT);
-
-            // Calculate screen-space positions.
-            Theme::Border border = containerRegion->getBorder();
-            Theme::Padding padding = _style->getPadding();
-            Vector4 borderColor = containerRegion->getColor();
-
-            float midWidth = _size.x - border.left - border.right;
-            float midHeight = _size.y - border.top - border.bottom;
-            float midX = pos.x + border.left;
-            float midY = pos.y + border.top;
-            float rightX = pos.x + _size.x - border.right;
-            float bottomY = pos.y + _size.y - border.bottom;
-
-            // Draw themed border sprites.
-            if (!border.left && !border.right && !border.top && !border.bottom)
-            {
-                // No border, just draw the image.
-                spriteBatch->draw(pos.x, pos.y, _size.x, _size.y, center.u1, center.v1, center.u2, center.v2, borderColor, clip);
-            }
-            else
-            {
-                if (border.left && border.top)
-                    spriteBatch->draw(pos.x, pos.y, border.left, border.top, topLeft.u1, topLeft.v1, topLeft.u2, topLeft.v2, borderColor, clip);
-                if (border.top)
-                    spriteBatch->draw(pos.x + border.left, pos.y, midWidth, border.top, top.u1, top.v1, top.u2, top.v2, borderColor, clip);
-                if (border.right && border.top)
-                    spriteBatch->draw(rightX, pos.y, border.right, border.top, topRight.u1, topRight.v1, topRight.u2, topRight.v2, borderColor, clip);
-                if (border.left)
-                    spriteBatch->draw(pos.x, midY, border.left, midHeight, left.u1, left.v1, left.u2, left.v2, borderColor, clip);
-                if (border.left && border.right && border.top && border.bottom)
-                    spriteBatch->draw(pos.x + border.left, pos.y + border.top, _size.x - border.left - border.right, _size.y - border.top - border.bottom,
-                        center.u1, center.v1, center.u2, center.v2, borderColor, clip);
-                if (border.right)
-                    spriteBatch->draw(rightX, midY, border.right, midHeight, right.u1, right.v1, right.u2, right.v2, borderColor, clip);
-                if (border.bottom && border.left)
-                    spriteBatch->draw(pos.x, bottomY, border.left, border.bottom, bottomLeft.u1, bottomLeft.v1, bottomLeft.u2, bottomLeft.v2, borderColor, clip);
-                if (border.bottom)
-                    spriteBatch->draw(midX, bottomY, midWidth, border.bottom, bottom.u1, bottom.v1, bottom.u2, bottom.v2, borderColor, clip);
-                if (border.bottom && border.right)
-                    spriteBatch->draw(rightX, bottomY, border.right, border.bottom, bottomRight.u1, bottomRight.v1, bottomRight.u2, bottomRight.v2, borderColor, clip);
-            }
+        //Theme::UVs topLeft, top, topRight, left, center, right, bottomLeft, bottom, bottomRight;
+        const Theme::UVs& topLeft = getSkinUVs(Theme::Skin::TOP_LEFT, _state);
+        const Theme::UVs& top = getSkinUVs(Theme::Skin::TOP, _state);
+        const Theme::UVs& topRight = getSkinUVs(Theme::Skin::TOP_RIGHT, _state);
+        const Theme::UVs& left = getSkinUVs(Theme::Skin::LEFT, _state);
+        const Theme::UVs& center = getSkinUVs(Theme::Skin::CENTER, _state);
+        const Theme::UVs& right = getSkinUVs(Theme::Skin::RIGHT, _state);
+        const Theme::UVs& bottomLeft = getSkinUVs(Theme::Skin::BOTTOM_LEFT, _state);
+        const Theme::UVs& bottom = getSkinUVs(Theme::Skin::BOTTOM, _state);
+        const Theme::UVs& bottomRight = getSkinUVs(Theme::Skin::BOTTOM_RIGHT, _state);
+
+        // Calculate screen-space positions.
+        const Theme::Border& border = getBorder(_state);
+        const Theme::Padding& padding = getPadding();
+        Vector4 skinColor = getSkinColor(_state);
+        skinColor.w *= getOpacity(_state);
+
+        float midWidth = _bounds.width - border.left - border.right;
+        float midHeight = _bounds.height - border.top - border.bottom;
+        float midX = pos.x + border.left;
+        float midY = pos.y + border.top;
+        float rightX = pos.x + _bounds.width - border.right;
+        float bottomY = pos.y + _bounds.height - border.bottom;
+
+        // Draw themed border sprites.
+        if (!border.left && !border.right && !border.top && !border.bottom)
+        {
+            // No border, just draw the image.
+            spriteBatch->draw(pos.x, pos.y, _bounds.width, _bounds.height, center.u1, center.v1, center.u2, center.v2, skinColor, clip);
+        }
+        else
+        {
+            if (border.left && border.top)
+                spriteBatch->draw(pos.x, pos.y, border.left, border.top, topLeft.u1, topLeft.v1, topLeft.u2, topLeft.v2, skinColor, clip);
+            if (border.top)
+                spriteBatch->draw(pos.x + border.left, pos.y, midWidth, border.top, top.u1, top.v1, top.u2, top.v2, skinColor, clip);
+            if (border.right && border.top)
+                spriteBatch->draw(rightX, pos.y, border.right, border.top, topRight.u1, topRight.v1, topRight.u2, topRight.v2, skinColor, clip);
+            if (border.left)
+                spriteBatch->draw(pos.x, midY, border.left, midHeight, left.u1, left.v1, left.u2, left.v2, skinColor, clip);
+            if (border.left && border.right && border.top && border.bottom)
+                spriteBatch->draw(pos.x + border.left, pos.y + border.top, _bounds.width - border.left - border.right, _bounds.height - border.top - border.bottom,
+                    center.u1, center.v1, center.u2, center.v2, skinColor, clip);
+            if (border.right)
+                spriteBatch->draw(rightX, midY, border.right, midHeight, right.u1, right.v1, right.u2, right.v2, skinColor, clip);
+            if (border.bottom && border.left)
+                spriteBatch->draw(pos.x, bottomY, border.left, border.bottom, bottomLeft.u1, bottomLeft.v1, bottomLeft.u2, bottomLeft.v2, skinColor, clip);
+            if (border.bottom)
+                spriteBatch->draw(midX, bottomY, midWidth, border.bottom, bottom.u1, bottom.v1, bottom.u2, bottom.v2, skinColor, clip);
+            if (border.bottom && border.right)
+                spriteBatch->draw(rightX, bottomY, border.right, border.bottom, bottomRight.u1, bottomRight.v1, bottomRight.u2, bottomRight.v2, skinColor, clip);
         }
         }
     }
     }
 
 
-    void Control::drawSprites(SpriteBatch* spriteBatch, const Rectangle& position)
+    void Control::drawImages(SpriteBatch* spriteBatch, const Rectangle& position)
     {
     {
     }
     }
 
 
@@ -394,7 +742,7 @@ namespace gameplay
         return false;
         return false;
     }
     }
 
 
-    Control::State Control::getStateFromString(const char* state)
+    Control::State Control::getState(const char* state)
     {
     {
         if (!state)
         if (!state)
         {
         {
@@ -420,4 +768,279 @@ namespace gameplay
 
 
         return NORMAL;
         return NORMAL;
     }
     }
+
+    // Implementation of AnimationHandler
+    unsigned int Control::getAnimationPropertyComponentCount(int propertyId) const
+    {
+        switch(propertyId)
+        {
+        case ANIMATE_POSITION:
+        case ANIMATE_SIZE:
+            return 2;
+
+        case ANIMATE_POSITION_X:
+        case ANIMATE_POSITION_Y:
+        case ANIMATE_SIZE_WIDTH:
+        case ANIMATE_SIZE_HEIGHT:
+        case ANIMATE_OPACITY:
+            return 1;
+
+        default:
+            return -1;
+        }
+    }
+
+    void Control::getAnimationPropertyValue(int propertyId, AnimationValue* value)
+    {
+        switch(propertyId)
+        {
+        case ANIMATE_POSITION:
+            value->setFloat(0, _bounds.x);
+            value->setFloat(1, _bounds.y);
+            break;
+        case ANIMATE_SIZE:
+            value->setFloat(0, _clipBounds.width);
+            value->setFloat(1, _clipBounds.height);
+            break;
+        case ANIMATE_POSITION_X:
+            value->setFloat(0, _bounds.x);
+            break;
+        case ANIMATE_POSITION_Y:
+            value->setFloat(0, _bounds.y);
+            break;
+        case ANIMATE_SIZE_WIDTH:
+            value->setFloat(0, _clipBounds.width);
+            break;
+        case ANIMATE_SIZE_HEIGHT:
+            value->setFloat(0, _clipBounds.height);
+            break;
+        case ANIMATE_OPACITY:
+        default:
+            break;
+        }
+    }
+
+    void Control::setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight)
+    {
+        switch(propertyId)
+        {
+        case ANIMATE_POSITION:
+            applyAnimationValuePositionX(value->getFloat(0), blendWeight);
+            applyAnimationValuePositionY(value->getFloat(1), blendWeight);
+            break;
+        case ANIMATE_POSITION_X:
+            applyAnimationValuePositionX(value->getFloat(0), blendWeight);
+            break;
+        case ANIMATE_POSITION_Y:
+            applyAnimationValuePositionY(value->getFloat(0), blendWeight);
+            break;
+        case ANIMATE_SIZE:
+            applyAnimationValueSizeWidth(value->getFloat(0), blendWeight);
+            applyAnimationValueSizeHeight(value->getFloat(1), blendWeight);
+            break;
+        case ANIMATE_SIZE_WIDTH:
+            applyAnimationValueSizeWidth(value->getFloat(0), blendWeight);
+            break;
+        case ANIMATE_SIZE_HEIGHT:
+            applyAnimationValueSizeHeight(value->getFloat(0), blendWeight);
+            break;
+        case ANIMATE_OPACITY:
+            applyAnimationValueOpacity();
+        default:
+            break;
+        }
+    }
+
+    void Control::applyAnimationValuePositionX(float x, float blendWeight)
+    {
+        if ((_animationPropertyBitFlag & ANIMATION_POSITION_X_BIT) != ANIMATION_POSITION_X_BIT)
+        {
+            _animationPropertyBitFlag |= ANIMATION_POSITION_X_BIT;
+        }
+        else
+        {
+            x = Curve::lerp(blendWeight, _bounds.x, x);
+        }
+        _bounds.x = x;
+        _dirty = true;
+    }
+    
+    void Control::applyAnimationValuePositionY(float y, float blendWeight)
+    {
+        if ((_animationPropertyBitFlag & ANIMATION_POSITION_Y_BIT) != ANIMATION_POSITION_Y_BIT)
+        {
+            _animationPropertyBitFlag |= ANIMATION_POSITION_Y_BIT;
+        }
+        else
+        {
+            y = Curve::lerp(blendWeight, _bounds.y, y);
+        }
+        _bounds.y = y;
+        _dirty = true;
+    }
+    
+    void Control::applyAnimationValueSizeWidth(float width, float blendWeight)
+    {
+        if ((_animationPropertyBitFlag & ANIMATION_SIZE_WIDTH_BIT) != ANIMATION_SIZE_WIDTH_BIT)
+        {
+            _animationPropertyBitFlag |= ANIMATION_SIZE_WIDTH_BIT;
+        }
+        else
+        {
+            width = Curve::lerp(blendWeight, _clipBounds.width, width);
+        }
+        _clipBounds.width = width;
+        _dirty = true;
+    }
+
+    void Control::applyAnimationValueSizeHeight(float height, float blendWeight)
+    {
+        if ((_animationPropertyBitFlag & ANIMATION_SIZE_HEIGHT_BIT) != ANIMATION_SIZE_HEIGHT_BIT)
+        {
+            _animationPropertyBitFlag |= ANIMATION_SIZE_HEIGHT_BIT;
+        }
+        else
+        {
+            height = Curve::lerp(blendWeight, _clipBounds.height, height);
+        }
+        _clipBounds.height = height;
+        _dirty = true;
+    }
+
+    void Control::applyAnimationValueOpacity()
+    {
+        if ((_animationPropertyBitFlag & ANIMATION_OPACITY_BIT) != ANIMATION_OPACITY_BIT)
+        {
+            _animationPropertyBitFlag |= ANIMATION_OPACITY_BIT;
+        }
+        _dirty = true;
+    }
+    
+    Theme::Style::Overlay** Control::getOverlays(unsigned char overlayTypes, Theme::Style::Overlay** overlays)
+    {
+        unsigned int index = 0;
+        if ((overlayTypes & NORMAL) == NORMAL)
+        {
+            overlays[index++] = _style->getOverlay(Theme::Style::OVERLAY_NORMAL);
+        }
+
+        if ((overlayTypes & FOCUS) == FOCUS)
+        {
+            overlays[index++] = _style->getOverlay(Theme::Style::OVERLAY_FOCUS);
+        }
+
+        if ((overlayTypes & ACTIVE) == ACTIVE)
+        {
+            overlays[index++] = _style->getOverlay(Theme::Style::OVERLAY_ACTIVE);
+        }
+
+        if ((overlayTypes & DISABLED) == DISABLED)
+        {
+            overlays[index++] = _style->getOverlay(Theme::Style::OVERLAY_DISABLED);
+        }
+
+        return overlays;
+    }
+
+    Theme::Style::Overlay* Control::getOverlay(State state) const
+    {
+        switch(state)
+        {
+        case Control::NORMAL:
+            return _style->getOverlay(Theme::Style::OVERLAY_NORMAL);
+        case Control::FOCUS:
+            return _style->getOverlay(Theme::Style::OVERLAY_FOCUS);
+        case Control::ACTIVE:
+            return _style->getOverlay(Theme::Style::OVERLAY_ACTIVE);
+        case Control::DISABLED:
+            return _style->getOverlay(Theme::Style::OVERLAY_DISABLED);
+        default:
+            return NULL;
+        }
+    }
+
+    void Control::overrideStyle()
+    {
+        if (_styleOverridden)
+        {
+            return;
+        }
+
+        // Copy the style.
+        WARN_VARG("%d", sizeof(Theme::Style::Overlay));
+        _style = new Theme::Style(*_style);
+        _styleOverridden = true;
+    }
+
+    Control::Alignment Control::getAlignment(const char* alignment)
+    {
+        if (!alignment)
+        {
+            return Control::ALIGN_TOP_LEFT;
+        }
+
+        if (strcmp(alignment, "ALIGN_LEFT") == 0)
+        {
+            return Control::ALIGN_LEFT;
+        }
+        else if (strcmp(alignment, "ALIGN_HCENTER") == 0)
+        {
+            return Control::ALIGN_HCENTER;
+        }
+        else if (strcmp(alignment, "ALIGN_RIGHT") == 0)
+        {
+            return Control::ALIGN_RIGHT;
+        }
+        else if (strcmp(alignment, "ALIGN_TOP") == 0)
+        {
+            return Control::ALIGN_TOP;
+        }
+        else if (strcmp(alignment, "ALIGN_VCENTER") == 0)
+        {
+            return Control::ALIGN_VCENTER;
+        }
+        else if (strcmp(alignment, "ALIGN_BOTTOM") == 0)
+        {
+            return Control::ALIGN_BOTTOM;
+        }
+        else if (strcmp(alignment, "ALIGN_TOP_LEFT") == 0)
+        {
+            return Control::ALIGN_TOP_LEFT;
+        }
+        else if (strcmp(alignment, "ALIGN_VCENTER_LEFT") == 0)
+        {
+            return Control::ALIGN_VCENTER_LEFT;
+        }
+        else if (strcmp(alignment, "ALIGN_BOTTOM_LEFT") == 0)
+        {
+            return Control::ALIGN_BOTTOM_LEFT;
+        }
+        else if (strcmp(alignment, "ALIGN_TOP_HCENTER") == 0)
+        {
+            return Control::ALIGN_TOP_HCENTER;
+        }
+        else if (strcmp(alignment, "ALIGN_VCENTER_HCENTER") == 0)
+        {
+            return Control::ALIGN_VCENTER_HCENTER;
+        }
+        else if (strcmp(alignment, "ALIGN_BOTTOM_HCENTER") == 0)
+        {
+            return Control::ALIGN_BOTTOM_HCENTER;
+        }
+        else if (strcmp(alignment, "ALIGN_TOP_RIGHT") == 0)
+        {
+            return Control::ALIGN_TOP_RIGHT;
+        }
+        else if (strcmp(alignment, "ALIGN_VCENTER_RIGHT") == 0)
+        {
+            return Control::ALIGN_VCENTER_RIGHT;
+        }
+        else if (strcmp(alignment, "ALIGN_BOTTOM_RIGHT") == 0)
+        {
+            return Control::ALIGN_BOTTOM_RIGHT;
+        }
+
+        // Default.
+        return Control::ALIGN_TOP_LEFT;
+    }
 }
 }

+ 592 - 50
gameplay/src/Control.h

@@ -6,6 +6,7 @@
 #include "Vector2.h"
 #include "Vector2.h"
 #include "SpriteBatch.h"
 #include "SpriteBatch.h"
 #include "Theme.h"
 #include "Theme.h"
+#include "ThemeStyle.h"
 #include "Touch.h"
 #include "Touch.h"
 #include "Keyboard.h"
 #include "Keyboard.h"
 
 
@@ -15,7 +16,7 @@ namespace gameplay
 /**
 /**
  * Base class for UI controls.
  * Base class for UI controls.
  */
  */
-class Control : public Ref
+class Control : public Ref, public AnimationTarget
 {
 {
     friend class Form;
     friend class Form;
     friend class Container;
     friend class Container;
@@ -24,32 +25,147 @@ class Control : public Ref
     friend class VerticalLayout;
     friend class VerticalLayout;
 
 
 public:
 public:
+
     /**
     /**
      * The possible states a control can be in.
      * The possible states a control can be in.
      */
      */
     enum State
     enum State
     {
     {
-        NORMAL,
-        FOCUS,
-        ACTIVE,
-        DISABLED
+        /**
+         * State of an enabled but inactive control.
+         */
+        NORMAL = 0x01,
+
+        /**
+         * State of a control currently in focus.
+         */
+        FOCUS = 0x02,
+
+        /**
+         * State of a control that is currently being acted on,
+         * e.g. through touch or mouse-click events.
+         */
+        ACTIVE = 0x04,
+
+        /**
+         * State of a control that has been disabled.
+         */
+        DISABLED = 0x08,
     };
     };
 
 
+    /**
+     * Defines the set of alignments for positioning controls and justifying text.
+     */
+    enum Alignment
+    {
+        // Specify horizontal alignment, use default vertical alignment (ALIGN_TOP).
+        ALIGN_LEFT = 0x01,
+        ALIGN_HCENTER = 0x02,
+        ALIGN_RIGHT = 0x04,
+    
+        // Specify vertical alignment, use default horizontal alignment (ALIGN_LEFT).
+        ALIGN_TOP = 0x10,
+        ALIGN_VCENTER = 0x20,
+        ALIGN_BOTTOM = 0x40,
+
+        // Specify both vertical and horizontal alignment.
+        ALIGN_TOP_LEFT = ALIGN_TOP | ALIGN_LEFT,
+        ALIGN_VCENTER_LEFT = ALIGN_VCENTER | ALIGN_LEFT,
+        ALIGN_BOTTOM_LEFT = ALIGN_BOTTOM | ALIGN_LEFT,
+        ALIGN_TOP_HCENTER = ALIGN_TOP | ALIGN_HCENTER,
+        ALIGN_VCENTER_HCENTER = ALIGN_VCENTER | ALIGN_HCENTER,
+        ALIGN_BOTTOM_HCENTER = ALIGN_BOTTOM | ALIGN_HCENTER,
+        ALIGN_TOP_RIGHT = ALIGN_TOP | ALIGN_RIGHT,
+        ALIGN_VCENTER_RIGHT = ALIGN_VCENTER | ALIGN_RIGHT,
+        ALIGN_BOTTOM_RIGHT = ALIGN_BOTTOM | ALIGN_RIGHT
+    };
+
+    /**
+     * A constant used for setting themed attributes on all control states simultaneously.
+     */
+    static const unsigned char STATE_ALL = NORMAL | FOCUS | ACTIVE | DISABLED;
+
+    /**
+     * Implement Control::Listener and call Control::addListener()
+     * in order to listen for events on controls.
+     */
     class Listener
     class Listener
     {
     {
     public:
     public:
         enum EventType
         enum EventType
         {
         {
+            /**
+             * Mouse-down or touch-press event.
+             */
             PRESS           = 0x01,
             PRESS           = 0x01,
+
+            /**
+             * Mouse-up or touch-release event.
+             */
             RELEASE         = 0x02,
             RELEASE         = 0x02,
+
+            /**
+             * Event triggered after consecutive PRESS and RELEASE events take place
+             * within the bounds of a control.
+             */
             CLICK           = 0x04,
             CLICK           = 0x04,
+
+            /**
+             * Event triggered when the value of a slider, check box, or radio button
+             * changes.
+             */
             VALUE_CHANGED   = 0x08,
             VALUE_CHANGED   = 0x08,
+
+            /**
+             * Event triggered when the contents of a text box are modified.
+             */
             TEXT_CHANGED    = 0x10
             TEXT_CHANGED    = 0x10
         };
         };
 
 
+        /**
+         * Method called by controls when an event is triggered.
+         * 
+         * @param control The control triggering the event.
+         * @param evt The event triggered.
+         */
         virtual void controlEvent(Control* control, EventType evt) = 0;
         virtual void controlEvent(Control* control, EventType evt) = 0;
     };
     };
 
 
+    /**
+     * Position animation property. Data = x, y
+     */
+    static const int ANIMATE_POSITION = 1;
+
+    /**
+     * Position x animation property. Data = x
+     */
+    static const int ANIMATE_POSITION_X = 2;
+
+    /**
+     * Position y animation property. Data = y
+     */
+    static const int ANIMATE_POSITION_Y = 3;
+
+    /**
+     * Size animation property.  Data = width, height
+     */
+    static const int ANIMATE_SIZE = 4;
+
+    /**
+     * Size width animation property.  Data = width
+     */
+    static const int ANIMATE_SIZE_WIDTH = 5;
+
+    /**
+     * Size height animation property.  Data = height
+     */
+    static const int ANIMATE_SIZE_HEIGHT = 6;
+
+    /**
+     * Opacity property.  Data = opacity
+     */
+    static const int ANIMATE_OPACITY = 7;
+
     /**
     /**
      * Get this control's ID string.
      * Get this control's ID string.
      *
      *
@@ -65,13 +181,6 @@ public:
      */
      */
     void setPosition(float x, float y);
     void setPosition(float x, float y);
 
 
-    /**
-     * Get the position of this control relative to its parent container.
-     *
-     * @return The position of this control relative to its parent container.
-     */
-    const Vector2& getPosition() const;
-
     /**
     /**
      * Set the desired size of this control, including its border and padding, before clipping.
      * Set the desired size of this control, including its border and padding, before clipping.
      *
      *
@@ -81,37 +190,408 @@ public:
     void setSize(float width, float height);
     void setSize(float width, float height);
 
 
     /**
     /**
-     * Get the desired size of this control, including its border and padding, before clipping.
+     * Set the bounds of this control, relative to its parent container and including its
+     * border and padding, before clipping.
      *
      *
-     * @return The size of this control.
+     * @param bounds The new bounds to set.
      */
      */
-    const Vector2& getSize() const;
+    void setBounds(const Rectangle& bounds);
 
 
     /**
     /**
-     * Get the bounds of this control, relative to its parent container, after clipping.
+     * Get the bounds of this control, relative to its parent container and including its
+     * border and padding, before clipping.
      *
      *
      * @return The bounds of this control.
      * @return The bounds of this control.
      */
      */
     const Rectangle& getBounds() const;
     const Rectangle& getBounds() const;
 
 
     /**
     /**
-     * Get the content area of this control, in screen coordinates, after clipping.
+     * Get the x coordinate of this control's bounds.
      *
      *
-     * @return The clipping area of this control.
+     * @return The x coordinate of this control's bounds.
      */
      */
-    const Rectangle& getClip() const;
+    float getX() const;
+    
+    /**
+     * Get the y coordinate of this control's bounds.
+     *
+     * @return The y coordinate of this control's bounds.
+     */
+    float getY() const;
+
+    /**
+     * Get the width of this control's bounds.
+     *
+     * @return The width of this control's bounds.
+     */
+    float getWidth() const;
+
+    /**
+     * Get the height of this control's bounds.
+     *
+     * @return The height of this control's bounds.
+     */
+    float getHeight() const;
+
+    /**
+     * Set the alignment of this control within its parent container.
+     *
+     * @param alignment This control's alignment.
+     */
+    void setAlignment(Alignment alignment);
+
+    /**
+     * Get the alignment of this control within its parent container.
+     *
+     * @return The alignment of this control within its parent container.
+     */
+    Alignment getAlignment() const;
+
+    /**
+     * Set this control to fit horizontally within its parent container.
+     *
+     * @param autoWidth Whether to size this control to fit horizontally within its parent container.
+     */
+    void setAutoWidth(bool autoWidth);
+
+    /**
+     * Get whether this control's width is set to automatically adjust to
+     * fit horizontally within its parent container.
+     *
+     * @return Whether this control's width is set to automatically adjust.
+     */
+    bool getAutoWidth() const;
+
+    /**
+     * Set this control to fit vertically within its parent container.
+     *
+     * @param autoWidth Whether to size this control to fit vertically within its parent container.
+     */
+    void setAutoHeight(bool autoHeight);
+
+    /**
+     * Get whether this control's height is set to automatically adjust to
+     * fit vertically within its parent container.
+     *
+     * @return Whether this control's height is set to automatically adjust.
+     */
+    bool getAutoHeight() const;
+
+    /**
+     * Set the size of this control's border.
+     *
+     * @param top The height of the border's top side.
+     * @param bottom The height of the border's bottom side.
+     * @param left The width of the border's left side.
+     * @param right The width of the border's right side.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setBorder(float top, float bottom, float left, float right, unsigned char states = STATE_ALL);
+
+    /**
+     * Get the measurements of this control's border for a given state. 
+     *
+     * @return This control's border.
+     */
+    const Theme::Border& getBorder(State state = NORMAL) const;
+
+    /**
+     * Set the texture region of this control's skin.
+     *
+     * @param region The texture region, in pixels.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setSkinRegion(const Rectangle& region, unsigned char states = STATE_ALL);
+
+    /**
+     * Get the texture region of this control's skin for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return The texture region of this control's skin.
+     */
+    const Rectangle& getSkinRegion(State state = NORMAL) const;
+
+    /**
+     * Get the texture coordinates of an area of this control's skin for a given state.
+     *
+     * @param area The area of the skin to get the coordinates of.
+     * @param state The state to get this property from.
+     *
+     * @return The texture coordinates of an area of this control's skin.
+     */
+    const Theme::UVs& getSkinUVs(Theme::Skin::SkinArea area, State state = NORMAL) const;
+
+    /**
+     * Set the blend color of this control's skin.
+     *
+     * @param color The new blend color.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setSkinColor(const Vector4& color, unsigned char states = STATE_ALL);
+
+    /**
+     * Get the blend color of this control's skin for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return The blend color of this control's skin.
+     */
+    const Vector4& getSkinColor(State state = NORMAL) const;
+
+    /**
+     * Set this control's margin.
+     *
+     * @param top Height of top margin.
+     * @param bottom Height of bottom margin.
+     * @param left Width of left margin.
+     * @param right Width of right margin.
+     */
+    void setMargin(float top, float bottom, float left, float right);
+
+    /**
+     * Get this control's margin.
+     *
+     * @return This control's margin.
+     */
+    const Theme::Margin& getMargin() const;
+
+    /**
+     * Set this control's padding.
+     *
+     * @param top Height of top padding.
+     * @param bottom Height of bottom padding.
+     * @param left Width of left padding.
+     * @param right Width of right padding.
+     */
+    void setPadding(float top, float bottom, float left, float right);
+
+    /**
+     * Get this control's padding.
+     *
+     * @return This control's padding.
+     */
+    const Theme::Padding& getPadding() const;
+
+    /**
+     * Set the texture region of an image used by this control.
+     *
+     * @param id The ID of the image to modify.
+     * @param region The new texture region of the image.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setImageRegion(const char* id, const Rectangle& region, unsigned char states = STATE_ALL);
+
+    /**
+     * Get the texture region of an image used by this control for a given state.
+     *
+     * @param id The ID of the image.
+     * @param state The state to get this property from.
+     *
+     * @return The texture region of the specified image.
+     */
+    const Rectangle& getImageRegion(const char* id, State state) const;
+
+    /**
+     * Set the blend color of an image used by this control.
+     *
+     * @param id The ID of the image to modify.
+     * @param color The new blend color of the image.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setImageColor(const char* id, const Vector4& color, unsigned char states = STATE_ALL);
+
+    /**
+     * Get the blend color of an image used by this control for a given state.
+     *
+     * @param id The ID of the image.
+     * @param state The state to get this property from.
+     *
+     * @return The blend color of the specified image.
+     */
+    const Vector4& getImageColor(const char* id, State state) const;
+
+    /**
+     * Get the texture coordinates of an image used by this control for a given state.
+     *
+     * @param id The ID of the image.
+     * @param state The state to get this property from.
+     *
+     * @return The texture coordinates of the specified image.
+     */
+    const Theme::UVs& getImageUVs(const char* id, State state) const;
+
+    /**
+     * Set the texture region of this control's cursor.
+     *
+     * @param region The cursor region.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setCursorRegion(const Rectangle& region, unsigned char states);
+
+    /**
+     * Get the texture region of this control's cursor for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return The texture region of this control's cursor.
+     */
+    const Rectangle& getCursorRegion(State state) const;
+
+    /**
+     * Set the blend color of this control's cursor.
+     *
+     * @param color The new blend color.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setCursorColor(const Vector4& color, unsigned char states);
+
+    /**
+     * Get the blend color of this control's cursor for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return The blend color of this control's cursor.
+     */
+    const Vector4& getCursorColor(State state);
+    
+    /**
+     * Get the texture coordinates of this control's cursor for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return The texture coordinates of this control's cursor.
+     */
+    const Theme::UVs& getCursorUVs(State state);
+
+    /**
+     * Set the font used by this control.
+     *
+     * @param font The new font to use.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setFont(Font* font, unsigned char states = STATE_ALL);
+
+    /**
+     * Get the font used by this control for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return the font used by this control.
+     */
+    Font* getFont(State state = NORMAL) const;
+
+    /**
+     * Set this control's font size.
+     *
+     * @param size The new font size.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setFontSize(unsigned int size, unsigned char states = STATE_ALL);
+
+    /**
+     * Get this control's font size for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return This control's font size.
+     */
+    unsigned int getFontSize(State state = NORMAL) const;
+
+    /**
+     * Set this control's text color.
+     *
+     * @param color The new text color.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setTextColor(const Vector4& color, unsigned char states = STATE_ALL);
+
+    /**
+     * Get this control's text color for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return This control's text color.
+     */
+    const Vector4& getTextColor(State state = NORMAL) const;
+
+    /**
+     * Set this control's text alignment.
+     *
+     * @param alignment The new text alignment.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setTextAlignment(Font::Justify alignment, unsigned char states = STATE_ALL);
+
+    /**
+     * Get this control's text alignment for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return This control's text alignment for the given state.
+     */
+    Font::Justify getTextAlignment(State state = NORMAL) const;
 
 
     /**
     /**
-     * Set width and/or height to auto-size to size a Control to tightly fit
-     * its text and themed visual elements (CheckBox / RadioButton toggle etc.).
+     * Set whether text is drawn from right to left within this control.
      *
      *
-     * Similarly set this on the width and/or height of a Container to tightly fit
-     * the Container around all its children.
+     * @param rightToLeft Whether text is drawn from right to left within this control.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setTextRightToLeft(bool rightToLeft, unsigned char states = STATE_ALL);
+
+    /**
+     * Get whether text is drawn from right to left within this control, for a given state.
+     *
+     * @param state The state to get this property from.
+     *
+     * @return Whether text is drawn from right to left within this control, for the given state.
+     */
+    bool getTextRightToLeft(State state = NORMAL) const;
+
+    /**
+     * Set the opacity of this control.
+     *
+     * @param opacity The new opacity.
+     * @param states The states to set this property on.
+     *               One or more members of the Control::State enum, ORed together.
+     */
+    void setOpacity(float opacity, unsigned char states = STATE_ALL);
+
+    /**
+     * Get the opacity of this control for a given state. 
      *
      *
-     * @param width Whether to automatically determine this Control's width.
-     * @param height Whether to automatically determine this Control's height.
+     * @param state The state to get this property from.
+     *
+     * @return The opacity of this control for a given state.
      */
      */
-    void setAutoSize(bool width, bool height);
+    float getOpacity(State state = NORMAL) const;
+
+    /**
+     * Get the bounds of this control, relative to its parent container, after clipping.
+     *
+     * @return The bounds of this control.
+     */
+    const Rectangle& getClipBounds() const;
+
+    /**
+     * Get the content area of this control, in screen coordinates, after clipping.
+     *
+     * @return The clipping area of this control.
+     */
+    const Rectangle& getClip() const;
 
 
     /**
     /**
      * Change this control's state.
      * Change this control's state.
@@ -125,7 +605,7 @@ public:
      *
      *
      * @return This control's current state.
      * @return This control's current state.
      */
      */
-    State getState();
+    State getState() const;
 
 
     /**
     /**
      * Disable this control.
      * Disable this control.
@@ -185,8 +665,31 @@ public:
      */
      */
     virtual void addListener(Control::Listener* listener, int eventFlags);
     virtual void addListener(Control::Listener* listener, int eventFlags);
 
 
+    /**
+     * @see AnimationTarget#getAnimationPropertyComponentCount
+     */
+    unsigned int getAnimationPropertyComponentCount(int propertyId) const;
+
+    /**
+     * @see AnimationTarget#getAnimationProperty
+     */
+    void getAnimationPropertyValue(int propertyId, AnimationValue* value);
+
+    /**
+     * @see AnimationTarget#setAnimationProperty
+     */
+    void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f);
+
 protected:
 protected:
+
+    /**
+     * Constructor.
+     */
     Control();
     Control();
+
+    /**
+     * Destructor.
+     */
     virtual ~Control();
     virtual ~Control();
 
 
     /**
     /**
@@ -231,20 +734,12 @@ protected:
     virtual void update(const Rectangle& clip);
     virtual void update(const Rectangle& clip);
 
 
     /**
     /**
-     * Draws the themed border and background of a control.
-     *
-     * @param spriteBatch The sprite batch containing this control's border images.
-     * @param clip The clipping rectangle of this control's parent container.
-     */
-    virtual void drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip);
-
-    /**
-     * Draw the icons associated with this control.
+     * Draw the images associated with this control.
      *
      *
      * @param spriteBatch The sprite batch containing this control's icons.
      * @param spriteBatch The sprite batch containing this control's icons.
      * @param clip The clipping rectangle of this control's parent container.
      * @param clip The clipping rectangle of this control's parent container.
      */
      */
-    virtual void drawSprites(SpriteBatch* spriteBatch, const Rectangle& clip);
+    virtual void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
 
 
     /**
     /**
      * Draw this control's text.
      * Draw this control's text.
@@ -254,49 +749,96 @@ protected:
     virtual void drawText(const Rectangle& clip);
     virtual void drawText(const Rectangle& clip);
 
 
     /**
     /**
-     * Initialize properties common to all Controls.
+     * Initialize properties common to STATE_ALL Controls.
      */
      */
-    virtual void init(Theme::Style* style, Properties* properties);
+    virtual void initialize(Theme::Style* style, Properties* properties);
 
 
     /**
     /**
      * Container and classes that extend it should implement this and return true.
      * Container and classes that extend it should implement this and return true.
+     *
+     * @return true if this object is of class Container, false otherwise.
      */
      */
     virtual bool isContainer();
     virtual bool isContainer();
 
 
     /**
     /**
      * Returns whether this control has been modified and requires an update.
      * Returns whether this control has been modified and requires an update.
+     *
+     * @return Whether this control has been modified and requires an update.
      */
      */
     virtual bool isDirty();
     virtual bool isDirty();
 
 
     /**
     /**
      * Get a Control::State enum from a matching string.
      * Get a Control::State enum from a matching string.
+     *
+     * @param state The string to match.
+     *
+     * @return The Control::State enum that matches the given string.
      */
      */
-    static State getStateFromString(const char* state);
+    static State getState(const char* state);
 
 
     /**
     /**
-     * Notify all listeners of a specific event.
+     * Notify this control's listeners of a specific event.
+     *
+     * @param eventType The event to trigger.
      */
      */
     void notifyListeners(Listener::EventType eventType);
     void notifyListeners(Listener::EventType eventType);
 
 
-    void addSpecificListener(Control::Listener* listener, Listener::EventType eventType);
+    static Alignment getAlignment(const char* alignment);
 
 
     std::string _id;
     std::string _id;
     State _state;           // Determines overlay used during draw().
     State _state;           // Determines overlay used during draw().
-    Vector2 _position;      // Position, relative to parent container's clipping window.
-    Vector2 _size;          // Desired size.  Will be clipped.
-    Rectangle _bounds;      // The position and size of this control, relative to parent container's bounds, including border and padding, after clipping.
-    Rectangle _textBounds;  // The position and size of this control's content, before clipping.  Used for text alignment.
+    Rectangle _bounds;      // Position, relative to parent container's clipping window, and desired size.
+    Rectangle _clipBounds;  // The position and size of this control, relative to parent container's bounds, including border and padding, after clipping.
+    Rectangle _textBounds;  // The position and size of this control's text area, before clipping.  Used for text alignment.
     Rectangle _clip;        // Clipping window of this control's content, after clipping.
     Rectangle _clip;        // Clipping window of this control's content, after clipping.
-    bool _autoWidth;
-    bool _autoHeight;
     bool _dirty;
     bool _dirty;
     bool _consumeTouchEvents;
     bool _consumeTouchEvents;
+    Alignment _alignment;
+    bool _autoWidth;
+    bool _autoHeight;
     Theme::Style* _style;
     Theme::Style* _style;
-    typedef std::map<Listener::EventType, std::list<Listener*>*> ListenerMap;
-    ListenerMap* _listeners;
+    std::map<Listener::EventType, std::list<Listener*>*>* _listeners;
 
 
 private:
 private:
+
+    static const char ANIMATION_POSITION_X_BIT = 0x01;
+    static const char ANIMATION_POSITION_Y_BIT = 0x02;
+    static const char ANIMATION_SIZE_WIDTH_BIT = 0x04;
+    static const char ANIMATION_SIZE_HEIGHT_BIT = 0x08;
+    static const char ANIMATION_OPACITY_BIT = 0x10;
+
+    /*
+     * Constructor.
+     */    
     Control(const Control& copy);
     Control(const Control& copy);
+    
+    void applyAnimationValuePositionX(float x, float blendWeight);
+    
+    void applyAnimationValuePositionY(float y, float blendWeight);
+    
+    void applyAnimationValueSizeWidth(float width, float blendWeight);
+    
+    void applyAnimationValueSizeHeight(float height, float blendWeight);
+    
+    void applyAnimationValueOpacity();
+
+    Theme::Style::Overlay** getOverlays(unsigned char overlayTypes, Theme::Style::Overlay** overlays);
+
+    Theme::Style::Overlay* getOverlay(Control::State state) const;
+
+    void overrideStyle();
+    
+    void addSpecificListener(Control::Listener* listener, Listener::EventType eventType);
+    
+    /**
+     * Draws the themed border and background of a control.
+     *
+     * @param spriteBatch The sprite batch containing this control's border images.
+     * @param clip The clipping rectangle of this control's parent container.
+     */
+    virtual void drawBorder(SpriteBatch* spriteBatch, const Rectangle& clip);
+    
+    bool _styleOverridden;
 };
 };
 
 
 }
 }

+ 8 - 2
gameplay/src/Curve.cpp

@@ -54,6 +54,11 @@ using std::strcmp;
 namespace gameplay
 namespace gameplay
 {
 {
 
 
+Curve* Curve::create(unsigned int pointCount, unsigned int componentCount)
+{
+    return new Curve(pointCount, componentCount);
+}
+
 Curve::Curve(unsigned int pointCount, unsigned int componentCount)
 Curve::Curve(unsigned int pointCount, unsigned int componentCount)
     : _pointCount(pointCount), _componentCount(componentCount), _componentSize(sizeof(float)*componentCount), _quaternionOffset(NULL), _points(NULL)
     : _pointCount(pointCount), _componentCount(componentCount), _componentSize(sizeof(float)*componentCount), _quaternionOffset(NULL), _points(NULL)
 {
 {
@@ -114,7 +119,7 @@ void Curve::setPoint(unsigned int index, float time, float* value, Interpolation
 
 
 void Curve::setPoint(unsigned int index, float time, float* value, InterpolationType type, float* inValue, float* outValue)
 void Curve::setPoint(unsigned int index, float time, float* value, InterpolationType type, float* inValue, float* outValue)
 {
 {
-    assert(index < _pointCount && time >= 0.0f && time <= 1.0f && !(index == 0 && time != 0.0f) && !(index == _pointCount - 1 && time != 1.0f));
+    assert(index < _pointCount && time >= 0.0f && time <= 1.0f && !(index == 0 && time != 0.0f) && !(_pointCount != 1 && index == _pointCount - 1 && time != 1.0f));
 
 
     _points[index].time = time;
     _points[index].time = time;
     _points[index].type = type;
     _points[index].type = type;
@@ -146,8 +151,9 @@ void Curve::evaluate(float time, float* dst) const
 {
 {
     assert(dst && time >= 0 && time <= 1.0f);
     assert(dst && time >= 0 && time <= 1.0f);
 
 
+    // Check if the point count is 1.
     // Check if we are at or beyond the bounds of the curve.
     // Check if we are at or beyond the bounds of the curve.
-    if (time <= _points[0].time)
+    if (_pointCount == 1 || time <= _points[0].time)
     {
     {
         memcpy(dst, _points[0].value, _componentSize);
         memcpy(dst, _points[0].value, _componentSize);
         return;
         return;

+ 25 - 10
gameplay/src/Curve.h

@@ -1,14 +1,17 @@
 #ifndef CURVE_H_
 #ifndef CURVE_H_
 #define CURVE_H_
 #define CURVE_H_
 
 
+#include "Ref.h"
+
 namespace gameplay
 namespace gameplay
 {
 {
 
 
 /**
 /**
  * Represents an n-dimensional curve.
  * Represents an n-dimensional curve.
  */
  */
-class Curve
+class Curve : public Ref
 {
 {
+    friend class AnimationTarget;
     friend class Animation;
     friend class Animation;
     friend class AnimationClip;
     friend class AnimationClip;
     friend class AnimationController;
     friend class AnimationController;
@@ -272,19 +275,13 @@ public:
         BOUNCE_OUT_IN
         BOUNCE_OUT_IN
     };
     };
 
 
-
     /**
     /**
-     * Constructs a new curve and the specified parameters.
-     *
+     * Creates a new curve.
+     * 
      * @param pointCount The number of points in the curve.
      * @param pointCount The number of points in the curve.
      * @param componentCount The number of float component values per key value.
      * @param componentCount The number of float component values per key value.
      */
      */
-    Curve(unsigned int pointCount, unsigned int componentCount);
-
-    /**
-     * Destructor.
-     */
-    ~Curve();
+    static Curve* create(unsigned int pointCount, unsigned int componentCount);
 
 
     /**
     /**
      * Gets the number of points in the curve.
      * Gets the number of points in the curve.
@@ -395,11 +392,29 @@ private:
      */
      */
     Curve();
     Curve();
 
 
+    /**
+     * Constructs a new curve and the specified parameters.
+     *
+     * @param pointCount The number of points in the curve.
+     * @param componentCount The number of float component values per key value.
+     */
+    Curve(unsigned int pointCount, unsigned int componentCount);
+
     /**
     /**
      * Constructor.
      * Constructor.
      */
      */
     Curve(const Curve& copy);
     Curve(const Curve& copy);
 
 
+    /**
+     * Destructor.
+     */
+    ~Curve();
+
+    /**
+     * Copy assignment operator.
+     */
+    Curve& operator=(const Curve&);
+
     /**
     /**
      * Bezier interpolation function.
      * Bezier interpolation function.
      */
      */

+ 148 - 1
gameplay/src/DebugNew.cpp

@@ -5,6 +5,15 @@
 #include <cstdio>
 #include <cstdio>
 #include <cstdarg>
 #include <cstdarg>
 
 
+#ifdef WIN32
+#include <windows.h>
+#include <dbghelp.h>
+#pragma comment(lib,"dbghelp.lib")
+
+#define MAX_STACK_FRAMES 16
+bool __trackStackTrace = false;
+#endif
+
 struct MemoryAllocationRecord
 struct MemoryAllocationRecord
 {
 {
     unsigned long address;          // address returned to the caller after allocation
     unsigned long address;          // address returned to the caller after allocation
@@ -13,6 +22,10 @@ struct MemoryAllocationRecord
     int line;                       // source line of the allocation request
     int line;                       // source line of the allocation request
     MemoryAllocationRecord* next;
     MemoryAllocationRecord* next;
     MemoryAllocationRecord* prev;
     MemoryAllocationRecord* prev;
+#ifdef WIN32
+    bool trackStackTrace;
+    unsigned int pc[MAX_STACK_FRAMES];
+#endif
 };
 };
 
 
 MemoryAllocationRecord* __memoryAllocations = 0;
 MemoryAllocationRecord* __memoryAllocations = 0;
@@ -99,6 +112,54 @@ void* debugAlloc(std::size_t size, const char* file, int line)
     rec->next = __memoryAllocations;
     rec->next = __memoryAllocations;
     rec->prev = 0;
     rec->prev = 0;
 
 
+    // Capture the stack frame (up to MAX_STACK_FRAMES) if we 
+    // are running on Windows and the user has enabled it.
+#if defined(WIN32)
+    rec->trackStackTrace = __trackStackTrace;
+    if (rec->trackStackTrace)
+    {
+        static bool initialized = false;
+        if (!initialized)
+        {
+            if (!SymInitialize(GetCurrentProcess(), NULL, true))
+                gameplay::printError("Stack trace tracking will not work.");
+            initialized = true;
+        }
+    
+        // Get the current context (state of EBP, EIP, ESP registers).
+        static CONTEXT context;
+        RtlCaptureContext(&context);
+    
+        static STACKFRAME64 stackFrame;
+        memset(&stackFrame, 0, sizeof(STACKFRAME64));
+
+        // Initialize the stack frame based on the machine architecture.
+#ifdef _M_IX86
+        static const DWORD machineType = IMAGE_FILE_MACHINE_I386;
+        stackFrame.AddrPC.Offset = context.Eip;
+        stackFrame.AddrPC.Mode = AddrModeFlat;
+        stackFrame.AddrFrame.Offset = context.Ebp;
+        stackFrame.AddrFrame.Mode = AddrModeFlat;
+        stackFrame.AddrStack.Offset = context.Esp;
+        stackFrame.AddrStack.Mode = AddrModeFlat;
+#else
+#error "Machine architecture not supported!"
+#endif
+
+        // Walk up the stack and store the program counters.
+        memset(rec->pc, 0, sizeof(rec->pc));
+        for (int i = 0; i < MAX_STACK_FRAMES; i++)
+        {
+            rec->pc[i] = stackFrame.AddrPC.Offset;
+            if (!StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &stackFrame,
+                &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
+            {
+                break;
+            }
+        }
+    }
+#endif
+
     if (__memoryAllocations)
     if (__memoryAllocations)
         __memoryAllocations->prev = rec;
         __memoryAllocations->prev = rec;
     __memoryAllocations = rec;
     __memoryAllocations = rec;
@@ -137,6 +198,70 @@ void debugFree(void* p)
     free(mem);
     free(mem);
 }
 }
 
 
+#ifdef WIN32
+void printStackTrace(MemoryAllocationRecord* rec)
+{
+    const unsigned int bufferSize = 512;
+
+    // Resolve the program counter to the corresponding function names.
+    unsigned int pc;
+    for (int i = 0; i < MAX_STACK_FRAMES; i++)
+    {
+        // Check to see if we are at the end of the stack trace.
+        pc = rec->pc[i];
+        if (pc == 0)
+            break;
+
+        // Get the function name.
+        unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + bufferSize];
+        IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)buffer;
+        DWORD64 displacement;
+        memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + bufferSize);
+        symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+        symbol->MaxNameLength = bufferSize;
+        if (!SymGetSymFromAddr64(GetCurrentProcess(), pc, &displacement, symbol))
+        {
+            gameplay::printError("[memory] STACK TRACE: <unknown location>");
+        }
+        else
+        {
+            symbol->Name[bufferSize - 1] = '\0';
+
+            // Check if we need to go further up the stack.
+            if (strncmp(symbol->Name, "operator new", 12) == 0)
+            {
+                // In operator new or new[], keep going...
+            }
+            else
+            {
+                // Get the file and line number.
+                if (pc != 0)
+                {
+                    IMAGEHLP_LINE64 line;
+                    DWORD displacement;
+                    memset(&line, 0, sizeof(line));
+                    line.SizeOfStruct = sizeof(line);
+                    if (!SymGetLineFromAddr64(GetCurrentProcess(), pc, &displacement, &line))
+                    {
+                        gameplay::printError("[memory] STACK TRACE: %s - <unknown file>:<unknown line number>", symbol->Name);
+                    }
+                    else
+                    {
+                        const char* file = strrchr(line.FileName, '\\');
+                        if(!file) 
+                            file = line.FileName;
+                        else
+                            file++;
+                        
+                        gameplay::printError("[memory] STACK TRACE: %s - %s:%d", symbol->Name, file, line.LineNumber);
+                    }
+                }
+            }
+        }
+    }
+}
+#endif
+
 extern void printMemoryLeaks()
 extern void printMemoryLeaks()
 {
 {
     // Dump general heap memory leaks
     // Dump general heap memory leaks
@@ -150,10 +275,32 @@ extern void printMemoryLeaks()
         MemoryAllocationRecord* rec = __memoryAllocations;
         MemoryAllocationRecord* rec = __memoryAllocations;
         while (rec)
         while (rec)
         {
         {
-            gameplay::printError("[memory] LEAK: HEAP allocation leak of size %d leak from line %d in file '%s'.", rec->size, rec->line, rec->file);
+#ifdef WIN32
+            if (rec->trackStackTrace)
+            {
+                gameplay::printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d:", rec->address, rec->size);
+                printStackTrace(rec);
+            }
+            else
+                gameplay::printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d from line %d in file '%s'.", rec->address, rec->size, rec->line, rec->file);
+#else
+            gameplay::printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d from line %d in file '%s'.", rec->address, rec->size, rec->line, rec->file);
+#endif
             rec = rec->next;
             rec = rec->next;
         }
         }
     }
     }
 }
 }
 
 
+#if defined(WIN32)
+void setTrackStackTrace(bool trackStackTrace)
+{
+    __trackStackTrace = trackStackTrace;
+}
+
+void toggleTrackStackTrace()
+{
+    __trackStackTrace = !__trackStackTrace;
+}
+#endif
+
 #endif
 #endif

+ 15 - 0
gameplay/src/DebugNew.h

@@ -89,4 +89,19 @@ T* bullet_new(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
 #endif
 #endif
 }
 }
 
 
+#if defined(WIN32)
+
+/**
+ * Sets whether stack traces are tracked on memory allocations or not.
+ * 
+ * @param trackStackTrace Whether to track the stack trace on memory allocations.
+ */
+void setTrackStackTrace(bool trackStackTrace);
+
+/**
+ * Toggles stack trace tracking on memory allocations.
+ */
+void toggleTrackStackTrace();
+#endif
+
 #endif
 #endif

+ 19 - 19
gameplay/src/FileSystem.cpp

@@ -117,9 +117,9 @@ bool FileSystem::listFiles(const char* dirPath, std::vector<std::string>& files)
 #else
 #else
     std::string path(FileSystem::getResourcePath());
     std::string path(FileSystem::getResourcePath());
     if (dirPath && strlen(dirPath) > 0)
     if (dirPath && strlen(dirPath) > 0)
-	{
-		path.append(dirPath);
-	}
+    {
+        path.append(dirPath);
+    }
     path.append("/.");
     path.append("/.");
     struct dirent* dp;
     struct dirent* dp;
     DIR* dir = opendir(path.c_str());
     DIR* dir = opendir(path.c_str());
@@ -127,23 +127,23 @@ bool FileSystem::listFiles(const char* dirPath, std::vector<std::string>& files)
     {
     {
         return false;
         return false;
     }
     }
-	while ((dp = readdir(dir)) != NULL)
-	{
-		std::string filepath(path);
-		filepath.append("/");
-		filepath.append(dp->d_name);
-
-		struct stat buf;
-		if (!stat(filepath.c_str(), &buf))
-		{
+    while ((dp = readdir(dir)) != NULL)
+    {
+        std::string filepath(path);
+        filepath.append("/");
+        filepath.append(dp->d_name);
+
+        struct stat buf;
+        if (!stat(filepath.c_str(), &buf))
+        {
             // Add to the list if this is not a directory
             // Add to the list if this is not a directory
-			if (!S_ISDIR(buf.st_mode))
-			{
-				files.push_back(dp->d_name);
-			}
-		}
-	}
-	closedir(dir);
+            if (!S_ISDIR(buf.st_mode))
+            {
+                files.push_back(dp->d_name);
+            }
+        }
+    }
+    closedir(dir);
     return true;
     return true;
 #endif
 #endif
 }
 }

+ 0 - 24
gameplay/src/FlowLayout.h

@@ -1,24 +0,0 @@
-#ifndef FLOWLAYOUT_H_
-#define FLOWLAYOUT_H_
-
-#include "Layout.h"
-
-namespace gameplay
-{
-
-class FlowLayout : public Layout
-{
-public:
-    static FlowLayout* create();
-
-    void setRightToLeft(bool rightToLeft);
-
-private:
-    FlowLayout();
-    FlowLayout(const FlowLayout& copy);
-    virtual ~FlowLayout();
-};
-
-}
-
-#endif

+ 25 - 25
gameplay/src/Font.cpp

@@ -689,7 +689,7 @@ void Font::measureText(const char* text, unsigned int size, unsigned int* width,
     }
     }
 }
 }
 
 
-void Font::measureText(const char* text, const Rectangle& viewport, unsigned int size, Rectangle* out, Justify justify, bool wrap, bool ignoreClip)
+void Font::measureText(const char* text, const Rectangle& clip, unsigned int size, Rectangle* out, Justify justify, bool wrap, bool ignoreClip)
 {
 {
     float scale = (float)size / _size;
     float scale = (float)size / _size;
     Justify vAlign = static_cast<Justify>(justify & 0xF0);
     Justify vAlign = static_cast<Justify>(justify & 0xF0);
@@ -709,8 +709,8 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
     std::vector<Vector2> lines;
     std::vector<Vector2> lines;
 
 
     unsigned int lineWidth = 0;
     unsigned int lineWidth = 0;
-    int yPos = viewport.y;
-    const float viewportHeight = viewport.height - size;
+    int yPos = clip.y;
+    const float viewportHeight = clip.height - size;
 
 
     if (wrap)
     if (wrap)
     {
     {
@@ -739,8 +739,8 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
                         if (lineWidth > 0)
                         if (lineWidth > 0)
                         {
                         {
                             // Determine horizontal position and width.
                             // Determine horizontal position and width.
-                            int hWhitespace = viewport.width - lineWidth;
-                            int xPos = viewport.x;
+                            int hWhitespace = clip.width - lineWidth;
+                            int xPos = clip.x;
                             if (hAlign == ALIGN_HCENTER)
                             if (hAlign == ALIGN_HCENTER)
                             {
                             {
                                 xPos += hWhitespace / 2;
                                 xPos += hWhitespace / 2;
@@ -791,14 +791,14 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
             unsigned int tokenWidth = getTokenWidth(token, tokenLength, size, scale);
             unsigned int tokenWidth = getTokenWidth(token, tokenLength, size, scale);
 
 
             // Wrap if necessary.
             // Wrap if necessary.
-            if (lineWidth + tokenWidth + delimWidth > viewport.width)
+            if (lineWidth + tokenWidth + delimWidth > clip.width)
             {
             {
                 // Add line-height to vertical cursor.
                 // Add line-height to vertical cursor.
                 yPos += size;
                 yPos += size;
 
 
                 // Determine horizontal position and width.
                 // Determine horizontal position and width.
-                int hWhitespace = viewport.width - lineWidth;
-                int xPos = viewport.x;
+                int hWhitespace = clip.width - lineWidth;
+                int xPos = clip.x;
                 if (hAlign == ALIGN_HCENTER)
                 if (hAlign == ALIGN_HCENTER)
                 {
                 {
                     xPos += hWhitespace / 2;
                     xPos += hWhitespace / 2;
@@ -857,8 +857,8 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
             lineWidth = getTokenWidth(token, tokenLength, size, scale);
             lineWidth = getTokenWidth(token, tokenLength, size, scale);
             
             
             // Determine horizontal position and width.
             // Determine horizontal position and width.
-            int xPos = viewport.x;
-            int hWhitespace = viewport.width - lineWidth;
+            int xPos = clip.x;
+            int hWhitespace = clip.width - lineWidth;
             if (hAlign == ALIGN_HCENTER)
             if (hAlign == ALIGN_HCENTER)
             {
             {
                 xPos += hWhitespace / 2;
                 xPos += hWhitespace / 2;
@@ -880,8 +880,8 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
     if (wrap)
     if (wrap)
     {
     {
         // Record the size of the last line.
         // Record the size of the last line.
-        int hWhitespace = viewport.width - lineWidth;
-        int xPos = viewport.x;
+        int hWhitespace = clip.width - lineWidth;
+        int xPos = clip.x;
         if (hAlign == ALIGN_HCENTER)
         if (hAlign == ALIGN_HCENTER)
         {
         {
             xPos += hWhitespace / 2;
             xPos += hWhitespace / 2;
@@ -895,9 +895,9 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
     }
     }
 
 
     int x = INT_MAX;
     int x = INT_MAX;
-    int y = viewport.y;
+    int y = clip.y;
     unsigned int width = 0;
     unsigned int width = 0;
-    int height = yPos - viewport.y;
+    int height = yPos - clip.y;
 
 
     // Calculate top of text without clipping.
     // Calculate top of text without clipping.
     int vWhitespace = viewportHeight - height;
     int vWhitespace = viewportHeight - height;
@@ -914,10 +914,10 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
     int clippedBottom = 0;
     int clippedBottom = 0;
     if (!ignoreClip)
     if (!ignoreClip)
     {
     {
-        // Trim rect to fit text that would actually be drawn within the given viewport.
-        if (y >= viewport.y)
+        // Trim rect to fit text that would actually be drawn within the given clip.
+        if (y >= clip.y)
         {
         {
-            // Text goes off the bottom of the viewport.
+            // Text goes off the bottom of the clip.
             clippedBottom = (height - viewportHeight) / size + 1;
             clippedBottom = (height - viewportHeight) / size + 1;
             if (clippedBottom > 0)
             if (clippedBottom > 0)
             {
             {
@@ -938,8 +938,8 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
         }
         }
         else
         else
         {
         {
-            // Text goes above the top of the viewport.
-            clippedTop = (viewport.y - y) / size + 1;
+            // Text goes above the top of the clip.
+            clippedTop = (clip.y - y) / size + 1;
             if (clippedTop < 0)
             if (clippedTop < 0)
             {
             {
                 clippedTop = 0;
                 clippedTop = 0;
@@ -995,10 +995,10 @@ void Font::measureText(const char* text, const Rectangle& viewport, unsigned int
 
 
     if (!ignoreClip)
     if (!ignoreClip)
     {
     {
-        // Guarantee that the output rect will fit within the viewport.
-        out->x = (x >= viewport.x)? x : viewport.x;
-        out->y = (y >= viewport.y)? y : viewport.y;
-        out->width = (width <= viewport.width)? width : viewport.width;
+        // Guarantee that the output rect will fit within the clip.
+        out->x = (x >= clip.x)? x : clip.x;
+        out->y = (y >= clip.y)? y : clip.y;
+        out->width = (width <= clip.width)? width : clip.width;
         out->height = (height <= viewportHeight)? height : viewportHeight;
         out->height = (height <= viewportHeight)? height : viewportHeight;
     }
     }
     else
     else
@@ -1563,12 +1563,12 @@ void Font::addLineInfo(const Rectangle& area, int lineWidth, int lineLength, Jus
     }
     }
 }
 }
 
 
-SpriteBatch* Font::getSpriteBatch()
+SpriteBatch* Font::getSpriteBatch() const
 {
 {
     return _batch;
     return _batch;
 }
 }
 
 
-Font::Justify Font::getJustifyFromString(const char* justify)
+Font::Justify Font::getJustify(const char* justify)
 {
 {
     if (!justify)
     if (!justify)
     {
     {

+ 27 - 13
gameplay/src/Font.h

@@ -133,6 +133,7 @@ public:
      * @param y The viewport y position to draw text at.
      * @param y The viewport y position to draw text at.
      * @param color The color of text.
      * @param color The color of text.
      * @param size The size to draw text (0 for default size).
      * @param size The size to draw text (0 for default size).
+     * @param rightToLeft Whether to draw text from right to left.
      */
      */
     void drawText(const char* text, int x, int y, const Vector4& color, unsigned int size = 0, bool rightToLeft = false);
     void drawText(const char* text, int x, int y, const Vector4& color, unsigned int size = 0, bool rightToLeft = false);
 
 
@@ -149,14 +150,14 @@ public:
      * @param rightToLeft Whether to draw text from right to left.
      * @param rightToLeft Whether to draw text from right to left.
      * @param clip A region to clip text within after applying justification to the viewport area.
      * @param clip A region to clip text within after applying justification to the viewport area.
      */
      */
-    void drawText(const char* text, const Rectangle& area, const Vector4& color,
-        unsigned int size = 0, Justify justify = ALIGN_TOP_LEFT, bool wrap = true, bool rightToLeft = false, const Rectangle* clip = NULL);
+    void drawText(const char* text, const Rectangle& area, const Vector4& color, unsigned int size = 0, 
+                  Justify justify = ALIGN_TOP_LEFT, bool wrap = true, bool rightToLeft = false, const Rectangle* clip = NULL);
 
 
     /**
     /**
      * Measures a string's width and height without alignment, wrapping or clipping.
      * Measures a string's width and height without alignment, wrapping or clipping.
      *
      *
      * @param text The text to measure.
      * @param text The text to measure.
-     * @param size
+     * @param size The font height to scale to.
      * @param widthOut Destination for the text's width.
      * @param widthOut Destination for the text's width.
      * @param heightOut Destination for the text's height.
      * @param heightOut Destination for the text's height.
      */
      */
@@ -166,9 +167,9 @@ public:
      * Measures a string's bounding box after alignment, wrapping and clipping within a viewport.
      * Measures a string's bounding box after alignment, wrapping and clipping within a viewport.
      *
      *
      * @param text The text to measure.
      * @param text The text to measure.
+     * @param clip The clip rectangle.
+     * @param size The font height to scale to.
      * @param out Destination rectangle to store the bounds in.
      * @param out Destination rectangle to store the bounds in.
-     * @param viewport The viewport area to align, wrap and clip text within while measuring.
-     * @param scale The scaling factor to apply.
      * @param justify Justification of text within the viewport.
      * @param justify Justification of text within the viewport.
      * @param wrap Whether to measure text with wrapping applied.
      * @param wrap Whether to measure text with wrapping applied.
      * @param ignoreClip Whether to clip 'out' to the viewport.  Set false for the bounds of what would actually be drawn
      * @param ignoreClip Whether to clip 'out' to the viewport.  Set false for the bounds of what would actually be drawn
@@ -189,9 +190,22 @@ public:
     void getLocationAtIndex(const char* text, const Rectangle& clip, unsigned int size, Vector2* outLocation, const unsigned int destIndex,
     void getLocationAtIndex(const char* text, const Rectangle& clip, unsigned int size, Vector2* outLocation, const unsigned int destIndex,
                             Justify justify = ALIGN_TOP_LEFT, bool wrap = true, bool rightToLeft = false);
                             Justify justify = ALIGN_TOP_LEFT, bool wrap = true, bool rightToLeft = false);
 
 
-    SpriteBatch* getSpriteBatch();
+    /**
+     * Gets the sprite batch for this Font.
+     * 
+     * @return The sprite batch for this Font.
+     */
+    SpriteBatch* getSpriteBatch() const;
 
 
-    static Justify getJustifyFromString(const char* justify);
+    /**
+     * Gets the Justify value from the given string.
+     * Returns ALIGN_TOP_LEFT if the string is unrecognized.
+     * 
+     * @param justify The string such as "ALIGN_HCENTER" or "ALIGN_VCENTER_RIGHT".
+     * 
+     * @return The Justify value.
+     */
+    static Justify getJustify(const char* justify);
 
 
 
 
 private:
 private:
@@ -202,7 +216,7 @@ private:
     Font();
     Font();
 
 
     /**
     /**
-     * Copy constructor.
+     * Constructor.
      */
      */
     Font(const Font& copy);
     Font(const Font& copy);
 
 
@@ -211,18 +225,17 @@ private:
      */
      */
     ~Font();
     ~Font();
 
 
-    // Used by both getIndexAtLocation and getLocationAtIndex.
     unsigned int getIndexOrLocation(const char* text, const Rectangle& clip, unsigned int size, const Vector2& inLocation, Vector2* outLocation,
     unsigned int getIndexOrLocation(const char* text, const Rectangle& clip, unsigned int size, const Vector2& inLocation, Vector2* outLocation,
                                     const int destIndex = -1, Justify justify = ALIGN_TOP_LEFT, bool wrap = true, bool rightToLeft = false);
                                     const int destIndex = -1, Justify justify = ALIGN_TOP_LEFT, bool wrap = true, bool rightToLeft = false);
 
 
-    // Utilities
     unsigned int getTokenWidth(const char* token, unsigned int length, unsigned int size, float scale);
     unsigned int getTokenWidth(const char* token, unsigned int length, unsigned int size, float scale);
+
     unsigned int getReversedTokenLength(const char* token, const char* bufStart);
     unsigned int getReversedTokenLength(const char* token, const char* bufStart);
 
 
-    // Returns 0 if EOF was reached, 1 if delimiters were handles correctly, and 2 if the stopAtPosition was reached while handling delimiters.
     int handleDelimiters(const char** token, const unsigned int size, const int iteration, const int areaX, int* xPos, int* yPos, unsigned int* lineLength,
     int handleDelimiters(const char** token, const unsigned int size, const int iteration, const int areaX, int* xPos, int* yPos, unsigned int* lineLength,
-                          std::vector<int>::const_iterator* xPositionsIt, std::vector<int>::const_iterator xPositionsEnd, unsigned int* charIndex = NULL,
-                          const Vector2* stopAtPosition = NULL, const int currentIndex = -1, const int destIndex = -1);
+                         std::vector<int>::const_iterator* xPositionsIt, std::vector<int>::const_iterator xPositionsEnd, unsigned int* charIndex = NULL,
+                         const Vector2* stopAtPosition = NULL, const int currentIndex = -1, const int destIndex = -1);
+
     void addLineInfo(const Rectangle& area, int lineWidth, int lineLength, Justify hAlign,
     void addLineInfo(const Rectangle& area, int lineWidth, int lineLength, Justify hAlign,
                      std::vector<int>* xPositions, std::vector<unsigned int>* lineLengths, bool rightToLeft);
                      std::vector<int>* xPositions, std::vector<unsigned int>* lineLengths, bool rightToLeft);
 
 
@@ -235,6 +248,7 @@ private:
     unsigned int _glyphCount;
     unsigned int _glyphCount;
     Texture* _texture;
     Texture* _texture;
     SpriteBatch* _batch;
     SpriteBatch* _batch;
+    Rectangle _viewport;
 };
 };
 
 
 }
 }

+ 45 - 39
gameplay/src/Form.cpp

@@ -13,7 +13,7 @@ namespace gameplay
 {
 {
     static std::vector<Form*> __forms;
     static std::vector<Form*> __forms;
 
 
-    Form::Form() : _theme(NULL), _quad(NULL), _node(NULL), _frameBuffer(NULL), _viewport(NULL)
+    Form::Form() : _theme(NULL), _quad(NULL), _node(NULL), _frameBuffer(NULL)
     {
     {
     }
     }
 
 
@@ -27,7 +27,6 @@ namespace gameplay
         SAFE_RELEASE(_node);
         SAFE_RELEASE(_node);
         SAFE_RELEASE(_frameBuffer);
         SAFE_RELEASE(_frameBuffer);
         SAFE_RELEASE(_theme);
         SAFE_RELEASE(_theme);
-        SAFE_DELETE(_viewport);
 
 
         // Remove this Form from the global list.
         // Remove this Form from the global list.
         std::vector<Form*>::iterator it = std::find(__forms.begin(), __forms.end(), this);
         std::vector<Form*>::iterator it = std::find(__forms.begin(), __forms.end(), this);
@@ -45,9 +44,7 @@ namespace gameplay
         Properties* properties = Properties::create(path);
         Properties* properties = Properties::create(path);
         assert(properties);
         assert(properties);
         if (properties == NULL)
         if (properties == NULL)
-        {
             return NULL;
             return NULL;
-        }
 
 
         // Check if the Properties is valid and has a valid namespace.
         // Check if the Properties is valid and has a valid namespace.
         Properties* formProperties = properties->getNextNamespace();
         Properties* formProperties = properties->getNextNamespace();
@@ -61,24 +58,9 @@ namespace gameplay
         // Create new form with given ID, theme and layout.
         // Create new form with given ID, theme and layout.
         const char* themeFile = formProperties->getString("theme");
         const char* themeFile = formProperties->getString("theme");
         const char* layoutString = formProperties->getString("layout");
         const char* layoutString = formProperties->getString("layout");
-        Form* form = Form::create(themeFile, getLayoutType(layoutString));
-
-        Theme* theme = form->_theme;
-        const char* styleName = formProperties->getString("style");
-        form->init(theme->getStyle(styleName), formProperties);
-
-        // Add all the controls to the form.
-        form->addControls(theme, formProperties);
-
-        SAFE_DELETE(properties);
-
-        return form;
-    }
-
-    Form* Form::create(const char* themeFile, Layout::Type type)
-    {
+        
         Layout* layout;
         Layout* layout;
-        switch (type)
+        switch (getLayoutType(layoutString))
         {
         {
         case Layout::LAYOUT_ABSOLUTE:
         case Layout::LAYOUT_ABSOLUTE:
             layout = AbsoluteLayout::create();
             layout = AbsoluteLayout::create();
@@ -98,6 +80,25 @@ namespace gameplay
         form->_layout = layout;
         form->_layout = layout;
         form->_theme = theme;
         form->_theme = theme;
 
 
+        //Theme* theme = form->_theme;
+        const char* styleName = formProperties->getString("style");
+        form->initialize(theme->getStyle(styleName), formProperties);
+
+        if (form->_autoWidth)
+        {
+            form->_bounds.width = Game::getInstance()->getWidth();
+        }
+
+        if (form->_autoHeight)
+        {
+            form->_bounds.height = Game::getInstance()->getHeight();
+        }
+
+        // Add all the controls to the form.
+        form->addControls(theme, formProperties);
+
+        SAFE_DELETE(properties);
+
         __forms.push_back(form);
         __forms.push_back(form);
 
 
         return form;
         return form;
@@ -121,14 +122,14 @@ namespace gameplay
     void Form::setQuad(const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& p4)
     void Form::setQuad(const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& p4)
     {
     {
         Mesh* mesh = Mesh::createQuad(p1, p2, p3, p4);
         Mesh* mesh = Mesh::createQuad(p1, p2, p3, p4);
-        initQuad(mesh);
+        initializeQuad(mesh);
         SAFE_RELEASE(mesh);
         SAFE_RELEASE(mesh);
     }
     }
 
 
     void Form::setQuad(float x, float y, float width, float height)
     void Form::setQuad(float x, float y, float width, float height)
     {
     {
         Mesh* mesh = Mesh::createQuad(x, y, width, height);
         Mesh* mesh = Mesh::createQuad(x, y, width, height);
-        initQuad(mesh);
+        initializeQuad(mesh);
         SAFE_RELEASE(mesh);
         SAFE_RELEASE(mesh);
     }
     }
 
 
@@ -139,11 +140,10 @@ namespace gameplay
         if (_node && !_quad)
         if (_node && !_quad)
         {
         {
             // Set this Form up to be 3D by initializing a quad, projection matrix and viewport.
             // Set this Form up to be 3D by initializing a quad, projection matrix and viewport.
-            setQuad(0.0f, 0.0f, _size.x, _size.y);
+            setQuad(0.0f, 0.0f, _bounds.width, _bounds.height);
 
 
-            Matrix::createOrthographicOffCenter(0, _size.x, _size.y, 0, 0, 1, &_projectionMatrix);
+            Matrix::createOrthographicOffCenter(0, _bounds.width, _bounds.height, 0, 0, 1, &_projectionMatrix);
             _theme->setProjectionMatrix(_projectionMatrix);
             _theme->setProjectionMatrix(_projectionMatrix);
-            _viewport = new Viewport(0, 0, _size.x, _size.y);
             
             
             _node->setModel(_quad);
             _node->setModel(_quad);
         }
         }
@@ -151,7 +151,10 @@ namespace gameplay
 
 
     void Form::update()
     void Form::update()
     {
     {
-        Container::update(Rectangle(0, 0, _size.x, _size.y));
+        if (isDirty())
+        {
+            Container::update(Rectangle(0, 0, _bounds.width, _bounds.height));
+        }
     }
     }
 
 
     void Form::draw()
     void Form::draw()
@@ -171,14 +174,19 @@ namespace gameplay
             if (isDirty())
             if (isDirty())
             {
             {
                 _frameBuffer->bind();
                 _frameBuffer->bind();
-                _viewport->bind();
+
+                Game* game = Game::getInstance();
+                Rectangle prevViewport = game->getViewport();
+                
+                game->setViewport(Rectangle(_bounds.x, _bounds.y, _bounds.width, _bounds.height));
 
 
                 draw(_theme->getSpriteBatch(), _clip);
                 draw(_theme->getSpriteBatch(), _clip);
 
 
                 // Rebind the default framebuffer and game viewport.
                 // Rebind the default framebuffer and game viewport.
                 FrameBuffer::bindDefault();
                 FrameBuffer::bindDefault();
-                Game* game = Game::getInstance();
-                GL_ASSERT( glViewport(0, 0, game->getWidth(), game->getHeight()) );
+
+                // restore the previous game viewport
+                game->setViewport(prevViewport);
             }
             }
 
 
             _quad->draw();
             _quad->draw();
@@ -198,7 +206,7 @@ namespace gameplay
 
 
         // 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, _size.x, _size.y));
+        Control::drawBorder(spriteBatch, Rectangle(0, 0, _bounds.width, _bounds.height));
 
 
         // Draw each control's border and background.
         // Draw each control's border and background.
         for (it = _controls.begin(); it < _controls.end(); it++)
         for (it = _controls.begin(); it < _controls.end(); it++)
@@ -210,7 +218,7 @@ namespace gameplay
                 control->drawBorder(spriteBatch, clip);
                 control->drawBorder(spriteBatch, clip);
 
 
                 // Add all themed foreground sprites (checkboxes etc.) to the same batch.
                 // Add all themed foreground sprites (checkboxes etc.) to the same batch.
-                control->drawSprites(spriteBatch, clip);
+                control->drawImages(spriteBatch, clip);
             }
             }
         }
         }
         spriteBatch->end();
         spriteBatch->end();
@@ -229,7 +237,7 @@ namespace gameplay
         _dirty = false;
         _dirty = false;
     }
     }
 
 
-    void Form::initQuad(Mesh* mesh)
+    void Form::initializeQuad(Mesh* mesh)
     {
     {
         // Release current model.
         // Release current model.
         SAFE_RELEASE(_quad);
         SAFE_RELEASE(_quad);
@@ -243,7 +251,6 @@ namespace gameplay
         // Set the common render state block for the material
         // Set the common render state block for the material
         RenderState::StateBlock* stateBlock = _theme->getSpriteBatch()->getStateBlock();
         RenderState::StateBlock* stateBlock = _theme->getSpriteBatch()->getStateBlock();
         stateBlock->setDepthWrite(true);
         stateBlock->setDepthWrite(true);
-        //material->setStateBlock(_theme->getSpriteBatch()->getStateBlock());
         material->setStateBlock(stateBlock);
         material->setStateBlock(stateBlock);
 
 
         // Bind the WorldViewProjection matrix
         // Bind the WorldViewProjection matrix
@@ -258,7 +265,7 @@ namespace gameplay
         // Use the FrameBuffer to texture the quad.
         // Use the FrameBuffer to texture the quad.
         if (!_frameBuffer->getRenderTarget())
         if (!_frameBuffer->getRenderTarget())
         {
         {
-            RenderTarget* rt = RenderTarget::create(_id.c_str(), _size.x, _size.y);
+            RenderTarget* rt = RenderTarget::create(_id.c_str(), _bounds.width, _bounds.height);
             _frameBuffer->setRenderTarget(rt);
             _frameBuffer->setRenderTarget(rt);
             SAFE_RELEASE(rt);
             SAFE_RELEASE(rt);
         }
         }
@@ -266,7 +273,6 @@ namespace gameplay
         Texture::Sampler* sampler = Texture::Sampler::create(_frameBuffer->getRenderTarget()->getTexture());
         Texture::Sampler* sampler = Texture::Sampler::create(_frameBuffer->getRenderTarget()->getTexture());
         sampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
         sampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
         material->getParameter("u_texture")->setValue(sampler);
         material->getParameter("u_texture")->setValue(sampler);
-
         material->getParameter("u_textureRepeat")->setValue(Vector2::one());
         material->getParameter("u_textureRepeat")->setValue(Vector2::one());
         material->getParameter("u_textureTransform")->setValue(Vector2::zero());
         material->getParameter("u_textureTransform")->setValue(Vector2::zero());
 
 
@@ -299,7 +305,7 @@ namespace gameplay
 
 
                         // Unproject point into world space.
                         // Unproject point into world space.
                         Ray ray;
                         Ray ray;
-                        camera->pickRay(NULL, x, y, &ray);
+                        camera->pickRay(Game::getInstance()->getViewport(), x, y, &ray);
 
 
                         // Find the quad's plane.
                         // Find the quad's plane.
                         // We know its normal is the quad's forward vector.
                         // We know its normal is the quad's forward vector.
@@ -327,7 +333,7 @@ namespace gameplay
                             m.transformPoint(&point);
                             m.transformPoint(&point);
 
 
                             // Pass the touch event on.
                             // Pass the touch event on.
-                            const Rectangle& bounds = form->getBounds();
+                            const Rectangle& bounds = form->getClipBounds();
                             if (form->getState() == Control::FOCUS ||
                             if (form->getState() == Control::FOCUS ||
                                 (evt == Touch::TOUCH_PRESS &&
                                 (evt == Touch::TOUCH_PRESS &&
                                  point.x >= bounds.x &&
                                  point.x >= bounds.x &&
@@ -346,7 +352,7 @@ namespace gameplay
                 else
                 else
                 {
                 {
                     // Simply compare with the form's bounds.
                     // Simply compare with the form's bounds.
-                    const Rectangle& bounds = form->getBounds();
+                    const Rectangle& bounds = form->getClipBounds();
                     if (form->getState() == Control::FOCUS ||
                     if (form->getState() == Control::FOCUS ||
                         (evt == Touch::TOUCH_PRESS &&
                         (evt == Touch::TOUCH_PRESS &&
                          x >= bounds.x &&
                          x >= bounds.x &&

+ 39 - 22
gameplay/src/Form.h

@@ -22,27 +22,37 @@ class Form : public Container
     friend class Platform;
     friend class Platform;
 
 
 public:
 public:
+
     /**
     /**
      * Create from properties file.
      * Create from properties file.
      * The top-most namespace in the file must be named 'form'.  The following properties are available for forms:
      * The top-most namespace in the file must be named 'form'.  The following properties are available for forms:
      *
      *
-     * form <Form ID>
+     * form <formID>
      * {
      * {
      *      // Form properties.
      *      // Form properties.
-     *      theme    = <Path to Theme File> // See Theme.h.
-     *      layout   = <Layout Type>        // A value from the Layout::Type enum.  E.g.: LAYOUT_VERTICAL
-     *      style    = <Style ID>           // A style from the referenced theme.
-     *      position = <x, y>               // Position of the form on-screen, measured in pixels.
-     *      size     = <width, height>      // Size of the form, measured in pixels.
+     *      theme    = <Path to .theme File>    // See Theme.h.
+     *      layout   = <Layout::Type>           // A value from the Layout::Type enum.  e.g.: LAYOUT_VERTICAL
+     *      style    = <styleID>                // A style from the referenced theme.
+     *      position = <x, y>                   // Position of the form on-screen, measured in pixels.
+     *      size     = <width, height>          // Size of the form, measured in pixels.
+     *      alignment   = <Control::Alignment constant> // Note: 'position' will be ignored.
+     *      autoWidth   = <bool>                // Will result in a form the width of the display.
+     *      autoHeight  = <bool>                // Will result in a form the height of the display.
+     *      size        = <width, height>
+     *      width       = <width>               // Can be used in place of 'size', e.g. with 'autoHeight = true'
+     *      height      = <height>              // Can be used in place of 'size', e.g. with 'autoWidth = true'
      *   
      *   
-     *      // All the controls within this form.
-     *      container{}
-     *      label{}
-     *      textBox{}
-     *      button{}
-     *      checkBox{}
-     *      radioButton{}
-     *      slider{}
+     *      // All the nested controls within this form.
+     *      container 
+     *      {
+     *          ...
+     *      }
+     *      label { }
+     *      textBox { }
+     *      button { }
+     *      checkBox { }
+     *      radioButton { }
+     *      slider { }
      * }
      * }
      *
      *
      * @param path Path to the properties file to create a new form from.
      * @param path Path to the properties file to create a new form from.
@@ -104,18 +114,29 @@ public:
      */
      */
     void draw();
     void draw();
 
 
-protected:
+private:
+    
+    /**
+     * Constructor.
+     */
     Form();
     Form();
-    virtual ~Form();
 
 
-    static Form* create(const char* textureFile, Layout::Type type);
+    /**
+     * Constructor.
+     */
+    Form(const Form& copy);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Form();
 
 
     /**
     /**
      * Initialize a quad for this form in order to draw it in 3D.
      * Initialize a quad for this form in order to draw it in 3D.
      *
      *
      * @param mesh The mesh to create a model from.
      * @param mesh The mesh to create a model from.
      */
      */
-    void initQuad(Mesh* mesh);
+    void initializeQuad(Mesh* mesh);
 
 
     /**
     /**
      * Draw this form into the current framebuffer.
      * Draw this form into the current framebuffer.
@@ -142,10 +163,6 @@ protected:
     Node* _node;                // Node for transforming this Form in world-space.
     Node* _node;                // Node for transforming this Form in world-space.
     FrameBuffer* _frameBuffer;  // FBO the Form is rendered into for texturing the quad.
     FrameBuffer* _frameBuffer;  // FBO the Form is rendered into for texturing the quad.
     Matrix _projectionMatrix;   // Orthographic projection matrix to be set on SpriteBatch objects when rendering into the FBO.
     Matrix _projectionMatrix;   // Orthographic projection matrix to be set on SpriteBatch objects when rendering into the FBO.
-    Viewport* _viewport;        // Viewport for setting before rendering into the FBO.
-
-private:
-    Form(const Form& copy);
 };
 };
 
 
 }
 }

+ 4 - 1
gameplay/src/FrameBuffer.h

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

+ 17 - 7
gameplay/src/Game.cpp

@@ -21,6 +21,7 @@ Game::Game()
 {
 {
     assert(__gameInstance == NULL);
     assert(__gameInstance == NULL);
     __gameInstance = this;
     __gameInstance = this;
+    _timeEvents = new std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >();
 }
 }
 
 
 Game::Game(const Game& copy)
 Game::Game(const Game& copy)
@@ -31,7 +32,7 @@ Game::~Game()
 {
 {
     // Do not call any virtual functions from the destructor.
     // Do not call any virtual functions from the destructor.
     // Finalization is done from outside this class.
     // Finalization is done from outside this class.
-
+    delete _timeEvents;
 #ifdef GAMEPLAY_MEM_LEAK_DETECTION
 #ifdef GAMEPLAY_MEM_LEAK_DETECTION
     Ref::printLeaks();
     Ref::printLeaks();
     printMemoryLeaks();
     printMemoryLeaks();
@@ -92,6 +93,8 @@ bool Game::startup()
     if (_state != UNINITIALIZED)
     if (_state != UNINITIALIZED)
         return false;
         return false;
 
 
+    setViewport(Rectangle(0.0f, 0.0f, (float)_width, (float)_height));
+
     RenderState::initialize();
     RenderState::initialize();
 
 
     _animationController = new AnimationController();
     _animationController = new AnimationController();
@@ -113,6 +116,7 @@ void Game::shutdown()
     // Call user finalization.
     // Call user finalization.
     if (_state != UNINITIALIZED)
     if (_state != UNINITIALIZED)
     {
     {
+        Platform::signalShutdown();
         finalize();
         finalize();
 
 
         _animationController->finalize();
         _animationController->finalize();
@@ -127,9 +131,9 @@ void Game::shutdown()
         SAFE_DELETE(_audioListener);
         SAFE_DELETE(_audioListener);
 
 
         RenderState::finalize();
         RenderState::finalize();
+        
+        _state = UNINITIALIZED;
     }
     }
-
-    _state = UNINITIALIZED;
 }
 }
 
 
 void Game::pause()
 void Game::pause()
@@ -212,6 +216,12 @@ void Game::frame()
     }
     }
 }
 }
 
 
+void Game::setViewport(const Rectangle& viewport)
+{
+    _viewport = viewport;
+    glViewport((GLuint)viewport.x, (GLuint)viewport.y, (GLuint)viewport.width, (GLuint)viewport.height); 
+}
+
 void Game::clear(ClearFlags flags, const Vector4& clearColor, float clearDepth, int clearStencil)
 void Game::clear(ClearFlags flags, const Vector4& clearColor, float clearDepth, int clearStencil)
 {
 {
     GLbitfield bits = 0;
     GLbitfield bits = 0;
@@ -280,7 +290,7 @@ void Game::schedule(long timeOffset, TimeListener* timeListener, void* cookie)
 {
 {
     assert(timeListener);
     assert(timeListener);
     TimeEvent timeEvent(getGameTime() + timeOffset, timeListener, cookie);
     TimeEvent timeEvent(getGameTime() + timeOffset, timeListener, cookie);
-    _timeEvents.push(timeEvent);
+    _timeEvents->push(timeEvent);
 }
 }
 
 
 bool Game::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
 bool Game::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
@@ -304,15 +314,15 @@ void Game::updateOnce()
 
 
 void Game::fireTimeEvents(long frameTime)
 void Game::fireTimeEvents(long frameTime)
 {
 {
-    while (_timeEvents.size() > 0)
+    while (_timeEvents->size() > 0)
     {
     {
-        const TimeEvent* timeEvent = &_timeEvents.top();
+        const TimeEvent* timeEvent = &_timeEvents->top();
         if (timeEvent->time > frameTime)
         if (timeEvent->time > frameTime)
         {
         {
             break;
             break;
         }
         }
         timeEvent->listener->timeEvent(frameTime - timeEvent->time, timeEvent->cookie);
         timeEvent->listener->timeEvent(frameTime - timeEvent->time, timeEvent->cookie);
-        _timeEvents.pop();
+        _timeEvents->pop();
     }
     }
 }
 }
 
 

+ 21 - 33
gameplay/src/Game.h

@@ -10,6 +10,7 @@
 #include "AnimationController.h"
 #include "AnimationController.h"
 #include "PhysicsController.h"
 #include "PhysicsController.h"
 #include "AudioListener.h"
 #include "AudioListener.h"
+#include "Rectangle.h"
 #include "Vector4.h"
 #include "Vector4.h"
 #include "TimeListener.h"
 #include "TimeListener.h"
 
 
@@ -151,6 +152,22 @@ public:
      */
      */
     inline unsigned int getHeight() const;
     inline unsigned int getHeight() const;
 
 
+    /**
+     * Gets the game current viewport.
+     *
+     * The default viewport is Rectangle(0, 0, Game::getWidth(), Game::getHeight()).
+     */
+    inline const Rectangle& getViewport() const;
+
+    /**
+     * Set the game current viewport.
+     *
+     * The x, y, width and height of the viewport must all be positive.
+     *
+     * viewport The custom viewport to be set on the game.
+     */
+    void setViewport(const Rectangle& viewport);
+
     /**
     /**
      * Clears the specified resource buffers to the specified clear values. 
      * Clears the specified resource buffers to the specified clear values. 
      *
      *
@@ -385,6 +402,7 @@ private:
     unsigned int _frameRate;                    // The current frame rate.
     unsigned int _frameRate;                    // The current frame rate.
     unsigned int _width;                        // The game's display width.
     unsigned int _width;                        // The game's display width.
     unsigned int _height;                       // The game's display height.
     unsigned int _height;                       // The game's display height.
+    Rectangle _viewport;                        // the games's current viewport.
     Vector4 _clearColor;                        // The clear color value last used for clearing the color buffer.
     Vector4 _clearColor;                        // The clear color value last used for clearing the color buffer.
     float _clearDepth;                          // The clear depth value last used for clearing the depth buffer.
     float _clearDepth;                          // The clear depth value last used for clearing the depth buffer.
     int _clearStencil;                          // The clear stencil value last used for clearing the stencil buffer.
     int _clearStencil;                          // The clear stencil value last used for clearing the stencil buffer.
@@ -392,43 +410,13 @@ private:
     AudioController* _audioController;          // Controls audio sources that are playing in the game.
     AudioController* _audioController;          // Controls audio sources that are playing in the game.
     PhysicsController* _physicsController;      // Controls the simulation of a physics scene and entities.
     PhysicsController* _physicsController;      // Controls the simulation of a physics scene and entities.
     AudioListener* _audioListener;              // The audio listener in 3D space.
     AudioListener* _audioListener;              // The audio listener in 3D space.
-    std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> > _timeEvents; // Contains the scheduled time events.
-
-    friend class SplashDisplayer;
-};
-
-/**
- * Used for displaying splash screens.
- */
-class SplashDisplayer
-{
-public:
+    std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >* _timeEvents; // Contains the scheduled time events.
 
 
-    /**
-     * Displays a splash screen using the {@link Game#renderOnce} mechanism for at least the given amount of time.
-     * 
-     * @param instance See {@link Game#renderOnce}.
-     * @param method See {@link Game#renderOnce}.
-     * @param cookie See {@link Game#renderOnce}.
-     * @param time The minimum amount of time to display the splash screen (in milliseconds).
-     */
-    template <typename T> void run(T* instance, void (T::*method) (void*), void* cookie, long time);
+    // Note: Do not add STL object member variables on the stack; this will cause false memory leaks to be reported.
 
 
-    /**
-     * Destructor.
-     */
-    ~SplashDisplayer();
-
-private:
-
-    long _time;
-    long _startTime;
+    friend class ScreenDisplayer;
 };
 };
 
 
-#define displaySplash(instance, method, cookie, time) \
-    SplashDisplayer __##instance##SplashDisplayer; \
-    __##instance##SplashDisplayer.run(instance, method, cookie, time)
-
 }
 }
 
 
 #include "Game.inl"
 #include "Game.inl"

+ 5 - 14
gameplay/src/Game.inl

@@ -24,6 +24,11 @@ inline unsigned int Game::getHeight() const
     return _height;
     return _height;
 }
 }
 
 
+inline const Rectangle& Game::getViewport() const
+{
+    return _viewport;
+}
+
 inline AnimationController* Game::getAnimationController() const
 inline AnimationController* Game::getAnimationController() const
 {
 {
     return _animationController;
     return _animationController;
@@ -66,18 +71,4 @@ inline void Game::displayKeyboard(bool display)
     Platform::displayKeyboard(display);
     Platform::displayKeyboard(display);
 }
 }
 
 
-template <typename T> void SplashDisplayer::run(T* instance, void (T::*method) (void*), void* cookie, long time)
-{
-    _time = time;
-    Game::getInstance()->renderOnce(instance, method, cookie);
-    _startTime = Game::getInstance()->getGameTime();
-}
-
-inline SplashDisplayer::~SplashDisplayer()
-{
-    long elapsedTime = Game::getInstance()->getGameTime() - _startTime;
-    if (elapsedTime < _time)
-        Platform::sleep(_time - (Game::getInstance()->getGameTime() - _startTime));
-}
-
 }
 }

+ 1 - 1
gameplay/src/Joint.cpp

@@ -19,7 +19,7 @@ Joint* Joint::create(const char* id)
     return new Joint(id);
     return new Joint(id);
 }
 }
 
 
-Node* Joint::cloneSingleNode(CloneContext &context) const
+Node* Joint::cloneSingleNode(NodeCloneContext &context) const
 {
 {
     Joint* copy = Joint::create(getId());
     Joint* copy = Joint::create(getId());
     context.registerClonedNode(this, copy);
     context.registerClonedNode(this, copy);

+ 12 - 3
gameplay/src/Joint.h

@@ -61,7 +61,7 @@ protected:
      * 
      * 
      * @return Pointer to the newly created joint.
      * @return Pointer to the newly created joint.
      */
      */
-    virtual Node* cloneSingleNode(CloneContext &context) const;
+    virtual Node* cloneSingleNode(NodeCloneContext &context) const;
 
 
     /**
     /**
      * Sets the inverse bind pose matrix.
      * Sets the inverse bind pose matrix.
@@ -70,19 +70,28 @@ protected:
      */
      */
     void setInverseBindPose(const Matrix& m);
     void setInverseBindPose(const Matrix& m);
 
 
+    /**
+     * Updates the joint matrix.
+     * 
+     * @param bindShape The bind shape matrix.
+     * @param matrixPalette The matrix palette to update.
+     */
     void updateJointMatrix(const Matrix& bindShape, Vector4* matrixPalette);
     void updateJointMatrix(const Matrix& bindShape, Vector4* matrixPalette);
 
 
+    /**
+     * Called when this Joint's transform changes.
+     */
     void transformChanged();
     void transformChanged();
 
 
 private:
 private:
 
 
     /**
     /**
-     * Hidden copy constructor.
+     * Constructor.
      */
      */
     Joint(const Joint& copy);
     Joint(const Joint& copy);
 
 
     /**
     /**
-     * Hidden copy assignment operator.
+     * Copy assignment operator.
      */
      */
     Joint& operator=(const Joint&);
     Joint& operator=(const Joint&);
 
 

+ 7 - 7
gameplay/src/Label.cpp

@@ -18,14 +18,14 @@ namespace gameplay
     Label* Label::create(Theme::Style* style, Properties* properties)
     Label* Label::create(Theme::Style* style, Properties* properties)
     {
     {
         Label* label = new Label();
         Label* label = new Label();
-        label->init(style, properties);
+        label->initialize(style, properties);
 
 
         return label;
         return label;
     }
     }
 
 
-    void Label::init(Theme::Style* style, Properties* properties)
+    void Label::initialize(Theme::Style* style, Properties* properties)
     {
     {
-        Control::init(style, properties);
+        Control::initialize(style, properties);
 
 
         const char* text = properties->getString("text");
         const char* text = properties->getString("text");
         if (text)
         if (text)
@@ -69,13 +69,13 @@ namespace gameplay
         if (_text.size() <= 0)
         if (_text.size() <= 0)
             return;
             return;
 
 
-        // TODO: Batch all labels that use the same font.
-        Theme::Style::Overlay* overlay = _style->getOverlay(getOverlayType());
-        Font* font = overlay->getFont();
+        Font* font = getFont(_state);
+        Vector4 textColor = getTextColor(_state);
+        textColor.w *= getOpacity(_state);
 
 
         // Draw the text.
         // Draw the text.
         font->begin();
         font->begin();
-        font->drawText(_text.c_str(), _textBounds, overlay->getTextColor(), overlay->getFontSize(), overlay->getTextAlignment(), true, overlay->getTextRightToLeft(), &_clip);
+        font->drawText(_text.c_str(), _textBounds, textColor, getFontSize(_state), getTextAlignment(_state), true, getTextRightToLeft(_state), &_clip);
         font->end();
         font->end();
 
 
         _dirty = false;
         _dirty = false;

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff