Explorar o código

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

Conflicts:
	gameplay/gameplay.vcxproj.filters
	gameplay/src/Control.cpp
	gameplay/src/Control.h
	gameplay/src/FlowLayout.cpp
	gameplay/src/FlowLayout.h
	gameplay/src/Label.h
	gameplay/src/Slider.h
	gameplay/src/TextBox.h
Adam Blake %!s(int64=13) %!d(string=hai) anos
pai
achega
a14944ba60
Modificáronse 96 ficheiros con 1678 adicións e 944 borrados
  1. 2 1
      .gitignore
  2. 5 3
      README.md
  3. 5 0
      gameplay-api/gameplay.html
  4. 10 8
      gameplay-newproject.bat
  5. 10 14
      gameplay-newproject.sh
  6. 4 2
      gameplay-template/TEMPLATE_PROJECT-ios.plist
  7. 1 1
      gameplay-template/TEMPLATE_PROJECT-macosx.plist
  8. 6 6
      gameplay-template/android/jni/template.Android.mk
  9. 1 1
      gameplay-template/android/template.AndroidManifest.xml
  10. 2 2
      gameplay-template/android/template.build.xml
  11. 11 0
      gameplay-template/gameplay-template.vcxproj
  12. 21 0
      gameplay-template/gameplay-template.vcxproj.filters
  13. 8 2
      gameplay-template/gameplay-template.xcodeproj/project.pbxproj
  14. BIN=BIN
      gameplay-template/icon.png
  15. 2 2
      gameplay-template/res/box.material
  16. 111 0
      gameplay-template/res/colored.fsh
  17. 183 0
      gameplay-template/res/colored.vsh
  18. 7 4
      gameplay-template/src/TemplateGame.cpp
  19. 2 2
      gameplay-template/src/TemplateGame.h
  20. 1 32
      gameplay.doxyfile
  21. 7 7
      gameplay.sln
  22. 12 0
      gameplay/gameplay.xcodeproj/project.pbxproj
  23. BIN=BIN
      gameplay/res/icon.png
  24. 0 0
      gameplay/res/icon_128.ico
  25. 0 0
      gameplay/res/icon_16.ico
  26. 0 0
      gameplay/res/icon_32.ico
  27. 0 0
      gameplay/res/icon_64.ico
  28. BIN=BIN
      gameplay/res/icon_black.psd
  29. BIN=BIN
      gameplay/res/icon_black128.ico
  30. BIN=BIN
      gameplay/res/icon_black16.ico
  31. BIN=BIN
      gameplay/res/icon_black32.ico
  32. BIN=BIN
      gameplay/res/icon_black64.ico
  33. BIN=BIN
      gameplay/res/icon_black_transparent.psd
  34. BIN=BIN
      gameplay/res/icon_white_transparent.psd
  35. BIN=BIN
      gameplay/res/icon_white_transparent128.ico
  36. BIN=BIN
      gameplay/res/icon_white_transparent16.ico
  37. BIN=BIN
      gameplay/res/icon_white_transparent32.ico
  38. BIN=BIN
      gameplay/res/icon_white_transparent64.ico
  39. 13 0
      gameplay/src/Animation.cpp
  40. 12 0
      gameplay/src/Animation.h
  41. 1 7
      gameplay/src/AnimationClip.cpp
  42. 3 3
      gameplay/src/AnimationClip.h
  43. 1 11
      gameplay/src/AnimationController.cpp
  44. 0 1
      gameplay/src/AnimationController.h
  45. 1 1
      gameplay/src/AnimationTarget.cpp
  46. 7 2
      gameplay/src/AnimationTarget.h
  47. 7 10
      gameplay/src/Base.h
  48. 19 3
      gameplay/src/CheckBox.h
  49. 9 2
      gameplay/src/Container.h
  50. 15 73
      gameplay/src/Control.cpp
  51. 45 20
      gameplay/src/Control.h
  52. 1 1
      gameplay/src/Game.inl
  53. 11 0
      gameplay/src/Joint.h
  54. 19 1
      gameplay/src/Label.h
  55. 9 46
      gameplay/src/MaterialParameter.cpp
  56. 1 3
      gameplay/src/MaterialParameter.h
  57. 1 11
      gameplay/src/Model.cpp
  58. 19 5
      gameplay/src/Node.cpp
  59. 110 0
      gameplay/src/Node.h
  60. 3 0
      gameplay/src/ParticleEmitter.h
  61. 117 181
      gameplay/src/PhysicsCharacter.cpp
  62. 12 113
      gameplay/src/PhysicsCharacter.h
  63. 9 1
      gameplay/src/PhysicsCollisionObject.cpp
  64. 12 0
      gameplay/src/PhysicsCollisionObject.h
  65. 4 4
      gameplay/src/PhysicsCollisionShape.cpp
  66. 19 0
      gameplay/src/PhysicsCollisionShape.h
  67. 11 0
      gameplay/src/PhysicsConstraint.h
  68. 17 4
      gameplay/src/PhysicsController.cpp
  69. 55 4
      gameplay/src/PhysicsController.h
  70. 1 1
      gameplay/src/PhysicsGhostObject.cpp
  71. 3 0
      gameplay/src/PhysicsGhostObject.h
  72. 2 2
      gameplay/src/PhysicsRigidBody.cpp
  73. 1 1
      gameplay/src/PhysicsRigidBody.h
  74. 98 57
      gameplay/src/PlatformAndroid.cpp
  75. 11 2
      gameplay/src/PlatformMacOSX.mm
  76. 54 20
      gameplay/src/PlatformQNX.cpp
  77. 64 61
      gameplay/src/PlatformWin32.cpp
  78. 26 5
      gameplay/src/PlatformiOS.mm
  79. 15 0
      gameplay/src/RadioButton.h
  80. 19 0
      gameplay/src/RenderState.h
  81. 37 2
      gameplay/src/Scene.cpp
  82. 57 8
      gameplay/src/Scene.h
  83. 25 15
      gameplay/src/SceneLoader.cpp
  84. 3 2
      gameplay/src/SceneLoader.h
  85. 37 0
      gameplay/src/Slider.h
  86. 47 4
      gameplay/src/SpriteBatch.cpp
  87. 19 0
      gameplay/src/TextBox.h
  88. 31 31
      gameplay/src/Texture.cpp
  89. 3 3
      gameplay/src/Texture.h
  90. 79 2
      gameplay/src/Theme.h
  91. 1 10
      gameplay/src/ThemeStyle.cpp
  92. 1 4
      gameplay/src/ThemeStyle.h
  93. 20 97
      gameplay/src/Transform.cpp
  94. 39 16
      gameplay/src/Transform.h
  95. 7 7
      gameplay/src/VertexAttributeBinding.cpp
  96. 4 0
      gameplay/src/VerticalLayout.h

+ 2 - 1
.gitignore

@@ -155,4 +155,5 @@ Thumbs.db
 
 /gameplay-samples/sample04-particles/Device-Debug
 /gameplay-samples/sample04-particles/Debug
-/gameplay-samples/sample04-particles/DebugMem
+/gameplay-samples/sample04-particles/DebugMem
+/gameplay-samples/sample03-character/res/gamepad.xcf

+ 5 - 3
README.md

@@ -1,5 +1,5 @@
 ## gameplay v1.2.0
-An open-source, cross-platform 3D native game framework making it easy to learn and write mobile and desktop games. 
+An open-source, cross-platform 3D native C++ game framework making it easy to learn and write mobile and desktop games. 
 
 ## Supported Mobile Platforms
 - BlackBerry PlayBook 2 (using BlackBerry Native SDK 2)
@@ -10,10 +10,12 @@ An open-source, cross-platform 3D native game framework making it easy to learn
 - Microsoft Windows 7 (using Microsoft Visual Studio 2010)
 - Apple MacOS X (using Apple XCode 4.3.2)
 
-## Roadmap for 'next' branch
-- Lua Scripting
+## Roadmap for 'next' branch
+- Shadows
+- Lua Script Bindings
 - Terrain
 - Editor
+- Performance/Optimizations
 
 ## Licence
 The project is open sourced under the Apache 2.0 license.

+ 5 - 0
gameplay-api/gameplay.html

@@ -0,0 +1,5 @@
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Refresh" CONTENT="0; URL=html/index.html">
+</HEAD>
+</HTML>

+ 10 - 8
gameplay-newproject.bat

@@ -177,10 +177,15 @@ 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 TEMPLATE_PROJECT "%projName%"
 
-copy gameplay-template\gameplay-template-macosx.plist %projPath%\%projName%-macosx.plist
+copy gameplay-template\TEMPLATE_PROJECT-macosx.plist %projPath%\%projName%-macosx.plist
 call:replace %projPath%\%projName%-macosx.plist TEMPLATE_UUID "%uuid%"
 call:replace %projPath%\%projName%-macosx.plist TEMPLATE_AUTHOR "%author%"
 
+copy gameplay-template\TEMPLATE_PROJECT-ios.plist %projPath%\%projName%-ios.plist
+call:replace %projPath%\%projName%-ios.plist TEMPLATE_TITLE "%title%"
+call:replace %projPath%\%projName%-ios.plist TEMPLATE_UUID "%uuid%"
+call:replace %projPath%\%projName%-ios.plist TEMPLATE_AUTHOR "%author%"
+
 REM Copy BlackBerry NDK project files
 copy gameplay-template\template.cproject %projPath%\.cproject
 call:replace %projPath%\.cproject TEMPLATE_PROJECT "%projName%"
@@ -207,11 +212,6 @@ call:replace %projPath%\android\AndroidManifest.xml TEMPLATE_UUID "%uuid%"
 copy gameplay-template\android\template.build.xml %projPath%\android\build.xml
 call:replace %projPath%\android\build.xml TEMPLATE_PROJECT "%projName%"
 
-copy gameplay-template\android\template.project %projPath%\android\.project
-call:replace %projPath%\android\.project TEMPLATE_PROJECT "%projName%"
-
-copy gameplay-template\android\template.classpath %projPath%\android\.classpath
-
 mkdir %projPath%\android\jni
 
 copy gameplay-template\android\jni\Application.mk %projPath%\android\jni\Application.mk
@@ -219,8 +219,11 @@ copy gameplay-template\android\jni\Application.mk %projPath%\android\jni\Applica
 copy gameplay-template\android\jni\template.Android.mk %projPath%\android\jni\Android.mk
 call:replace %projPath%\android\jni\Android.mk TemplateGame "%className%"
 call:replace %projPath%\android\jni\Android.mk TEMPLATE_PROJECT "%projName%"
+call:replace %projPath%\android\jni\Android.mk GAMEPLAY_PATH "%gpPath%"
+
+mkdir %projPath%\android\res\drawable
 
-copy gameplay-template\android\jni\main.cpp %projPath%\android\jni\main.cpp
+copy gameplay-template\icon.png %projPath%\android\res\drawable\icon.png
 
 mkdir %projPath%\android\res\values
 
@@ -236,7 +239,6 @@ call:replace %projPath%\src\%className%.cpp TemplateGame "%className%"
 
 REM Copy resource files
 copy gameplay-template\res\* %projPath%\res\
-copy gameplay\res\shaders\colored.* %projPath%\res\
 
 REM Copy icon
 copy gameplay-template\icon.png %projPath%\icon.png

+ 10 - 14
gameplay-newproject.sh

@@ -153,12 +153,9 @@ if [[ ${gpPathAbs} == ${common_path} ]]; then
 fi
 
 
-# Below does copy, then uses 'sed' with -i for inplace editing
-# Alternative below uses sed to do a input then output skipping the copy
-# sed "s/TEMPLATE_PROJECT/$projectName/g" "gameplay-template/gameplay-template.vcxproj" > "$projPath/$projName.vcxproj"
-
 #############################################
-# Copy Microsoft Virtual Studio project files
+# Copy Microsoft Visual Studio project files
+#############################################
 cp "gameplay-template/gameplay-template.vcxproj" "$projPath/$projName.vcxproj"
 sed -i "" "s*TEMPLATE_PROJECT*$projectName*g" "$projPath/$projName.vcxproj"
 sed -i "" "s*TemplateGame*$className*g" "$projPath/$projName.vcxproj"
@@ -172,7 +169,8 @@ sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.vcxproj.user"
 
 
 #############################################
-# Copy Apple XCode project files
+# Copy Apple Xcode project files
+#############################################
 mkdir -p "$projPath/$projName.xcodeproj"
 cp "gameplay-template/gameplay-template.xcodeproj/project.pbxproj" "$projPath/$projName.xcodeproj/project.pbxproj"
 sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/$projName.xcodeproj/project.pbxproj"
@@ -184,11 +182,13 @@ 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"
+sed -i "" "s*TEMPLATE_TITLE*$title*g" "$projPath/$projName-ios.plist"
 sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/$projName-ios.plist"
 sed -i "" "s*TEMPLATE_AUTHOR*$author*g" "$projPath/$projName-ios.plist"
 
 #############################################
 # Copy BlackBerry NDK project files
+#############################################
 cp "gameplay-template/template.cproject" "$projPath/.cproject"
 sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/.cproject"
 sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/.cproject"
@@ -206,9 +206,11 @@ sed -i "" "s*TEMPLATE_DESCRIPTION*$desc*g" "$projPath/bar-descriptor.xml"
 
 #############################################
 # Copy Android NDK project files
+#############################################
 mkdir -p "$projPath/android"
 mkdir -p "$projPath/android/jni"
 mkdir -p "$projPath/android/res/values"
+mkdir -p "$projPath/android/res/drawable"
 
 cp "gameplay-template/android/template.AndroidManifest.xml" "$projPath/android/AndroidManifest.xml"
 sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/android/AndroidManifest.xml"
@@ -217,20 +219,15 @@ sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/android/AndroidManifest.xml"
 cp "gameplay-template/android/template.build.xml" "$projPath/android/build.xml"
 sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/android/build.xml"
 
-# Does not exist
-#cp "gameplay-template/android/template.project" "$projPath/android/.project"
-#sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/android/.project"
-
-#cp "gameplay-template/android/template.classpath" "$projPath/android/.classpath"
-
 cp "gameplay-template/android/jni/Application.mk" "$projPath/android/jni/Application.mk"
 
 cp "gameplay-template/android/jni/template.Android.mk" "$projPath/android/jni/Android.mk"
 sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/android/jni/Android.mk"
 sed -i "" "s*TemplateGame*$className*g" "$projPath/android/jni/Android.mk"
+sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/android/jni/Android.mk"
 
-#cp "gameplay-template/android/jni/main.cpp" "$projPath/android/jni/main.cpp"
 
+cp "gameplay-template/icon.png" "$projPath/android/res/drawable/icon.png"
 cp "gameplay-template/android/res/values/template.strings.xml" "$projPath/android/res/values/strings.xml"
 sed -i "" "s*TEMPLATE_TITLE*$title*g" "$projPath/android/res/values/strings.xml"
 
@@ -245,7 +242,6 @@ sed -i "" "s*TemplateGame*$className*g" "$projPath/src/$className.cpp"
 
 # Copy resource files
 cp "gameplay-template/res/"* "$projPath/res/"
-#cp "gameplay-template/res/shaders/colored."* "$projPath/res/"
 
 # Copy icon
 cp "gameplay-template/icon.png" "$projPath/icon.png"

+ 4 - 2
gameplay-template/TEMPLATE_PROJECT-ios.plist

@@ -4,10 +4,10 @@
 <dict>
 	<key>CFBundleDevelopmentRegion</key>
 	<string>en</string>
+    <key>CFBundleDisplayName</key>
+	<string>TEMPLATE_TITLE</string>
 	<key>CFBundleExecutable</key>
 	<string>${EXECUTABLE_NAME}</string>
-	<key>CFBundleIconFile</key>
-	<string>icon.png</string>
 	<key>CFBundleIdentifier</key>
 	<string>TEMPLATE_UUID</string>
 	<key>CFBundleInfoDictionaryVersion</key>
@@ -28,5 +28,7 @@
 	<array>
 		<string>UIInterfaceOrientationLandscapeRight</string>
 	</array>
+    <key>CFBundleIconFile</key>
+	<string>icon.png</string>
 </dict>
 </plist>

+ 1 - 1
gameplay-template/TEMPLATE_PROJECT-macosx.plist

@@ -27,7 +27,7 @@
 	<key>LSMinimumSystemVersion</key>
 	<string>${MACOSX_DEPLOYMENT_TARGET}</string>
 	<key>NSHumanReadableCopyright</key>
-	<string>Copyright © 2011 TEMPLATE_AUTHOR. All rights reserved.</string>
+	<string>Copyright © 2012 TEMPLATE_AUTHOR. All rights reserved.</string>
 	<key>NSPrincipalClass</key>
 	<string>NSApplication</string>
 </dict>

+ 6 - 6
gameplay-template/android/jni/template.Android.mk

@@ -14,12 +14,12 @@
 #
 
 SAMPLE_PATH := $(call my-dir)/../../src
-LIBPNG_PATH := $(call my-dir)/../../../../external-deps/libpng/lib/android/arm
-ZLIB_PATH := $(call my-dir)/../../../../external-deps/zlib/lib/android/arm
-BULLET_PATH := $(call my-dir)/../../../../external-deps/bullet/lib/android/arm
+LIBPNG_PATH := ../GAMEPLAY_PATH/external-deps/libpng/lib/android/arm
+ZLIB_PATH := ../GAMEPLAY_PATH/external-deps/zlib/lib/android/arm
+BULLET_PATH := ../GAMEPLAY_PATH/external-deps/bullet/lib/android/arm
 
 # gameplay
-LOCAL_PATH := $(call my-dir)/../../../../gameplay/android/obj/local/armeabi
+LOCAL_PATH := ../GAMEPLAY_PATH/gameplay/android/obj/local/armeabi
 include $(CLEAR_VARS)
 LOCAL_MODULE    := libgameplay
 LOCAL_SRC_FILES := libgameplay.a
@@ -51,10 +51,10 @@ LOCAL_PATH := $(SAMPLE_PATH)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE    := TEMPLATE_PROJECT
-LOCAL_SRC_FILES := ../../../gameplay/src/gameplay-main-android.cpp TemplateGame.cpp
+LOCAL_SRC_FILES := ../GAMEPLAY_PATH/gameplay/src/gameplay-main-android.cpp TemplateGame.cpp
 
 LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv2 -lOpenSLES
-LOCAL_CFLAGS    := -D__ANDROID__ -I"../../../external-deps/bullet/include" -I"../../../external-deps/libpng/include" -I"../../../gameplay/src"
+LOCAL_CFLAGS    := -D__ANDROID__ -I"../GAMEPLAY_PATH/external-deps/bullet/include" -I"../GAMEPLAY_PATH/external-deps/libpng/include" -I"../GAMEPLAY_PATH/gameplay/src"
 
 LOCAL_STATIC_LIBRARIES := android_native_app_glue libgameplay libpng libzlib libbullet
 

+ 1 - 1
gameplay-template/android/template.AndroidManifest.xml

@@ -10,7 +10,7 @@
     <uses-sdk android:minSdkVersion="9" />
 	<uses-feature android:glEsVersion="0x00020000"/>
 
-    <application android:label="@string/app_name" android:hasCode="true">
+    <application android:icon="@drawable/icon" android:label="@string/app_name" android:hasCode="true">
 
         <!-- Our activity is the built-in NativeActivity framework class.
              This will take care of integrating with our NDK code. -->

+ 2 - 2
gameplay-template/android/template.build.xml

@@ -64,8 +64,8 @@
     <target name="-post-compile">
         <copy file="../res/box.gpb" tofile="assets/res/box.gpb"/>
         <copy file="../res/box.material" tofile="assets/res/box.material"/>
-        <copy file="../../../gameplay/res/shaders/colored.vsh" tofile="assets/res/shaders/colored.vsh"/>
-        <copy file="../../../gameplay/res/shaders/colored.fsh" tofile="assets/res/shaders/colored.fsh"/>
+        <copy file="../res/colored.vsh" tofile="assets/res/colored.vsh"/>
+        <copy file="../res/colored.fsh" tofile="assets/res/colored.fsh"/>
     </target>
 
     <!-- Import the actual build file.

+ 11 - 0
gameplay-template/gameplay-template.vcxproj

@@ -159,6 +159,17 @@
       </Outputs>
     </CustomBuildStep>
   </ItemDefinitionGroup>
+  <ItemGroup>
+    <None Include="bar-descriptor.xml" >
+        <SubType>Designer</SubType>
+    </None>
+    <None Include="icon.png" />
+    <None Include="res\box.dae" />
+    <None Include="res\box.gpb" />
+    <None Include="res\box.material" />
+    <None Include="res\colored.fsh" />
+    <None Include="res\colored.vsh" />
+  </ItemGroup> 
   <ItemGroup>
     <ClCompile Include="src\TemplateGame.cpp" />
   </ItemGroup>

+ 21 - 0
gameplay-template/gameplay-template.vcxproj.filters

@@ -1,9 +1,30 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
+    <Filter Include="res">
+    </Filter>
     <Filter Include="src">
     </Filter>
   </ItemGroup>
+  <ItemGroup>
+    <None Include="icon.png" />
+    <None Include="bar-descriptor.xml" />
+    <None Include="res\box.dae">
+      <Filter>res</Filter>
+    </None>
+    <None Include="res\box.gpb">
+      <Filter>res</Filter>
+    </None>
+    <None Include="res\box.material">
+      <Filter>res</Filter>
+    </None>
+    <None Include="res\colored.fsh">
+      <Filter>res</Filter>
+    </None>
+    <None Include="res\colored.vsh">
+      <Filter>res</Filter>
+    </None>
+  </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\TemplateGame.h">
       <Filter>src</Filter>

+ 8 - 2
gameplay-template/gameplay-template.xcodeproj/project.pbxproj

@@ -70,7 +70,6 @@
 		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; };
 		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; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -202,7 +201,6 @@
 			isa = PBXGroup;
 			children = (
 				5BC4E849150F911D00CBE1C0 /* shaders */,
-				5BC4E84A150F911D00CBE1C0 /* textures */,
 				5BC4E77F150F879E00CBE1C0 /* gameplay.xcodeproj */,
 			);
 			name = GamePlay;
@@ -479,6 +477,8 @@
 		5B61612A14CCC24C0073B857 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+                ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CODE_SIGN_IDENTITY = "iPhone Developer";
 				GCC_PRECOMPILE_PREFIX_HEADER = NO;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 				GCC_WARN_UNUSED_VARIABLE = NO;
@@ -489,6 +489,7 @@
 					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
 				);
 				INFOPLIST_FILE = "TEMPLATE_PROJECT-ios.plist";
+                IPHONEOS_DEPLOYMENT_TARGET = 5.1;
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"GAMEPLAY_PATH/external-deps/libpng/lib/ios/$(CURRENT_ARCH)\"",
@@ -496,6 +497,7 @@
 					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/ios/$(CURRENT_ARCH)\"",
 				);
 				SDKROOT = iphoneos;
+                TARGETED_DEVICE_FAMILY = "1,2";
 				USER_HEADER_SEARCH_PATHS = "";
 				WRAPPER_EXTENSION = app;
 			};
@@ -504,6 +506,8 @@
 		5B61612B14CCC24C0073B857 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+                ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CODE_SIGN_IDENTITY = "iPhone Developer";
 				GCC_PRECOMPILE_PREFIX_HEADER = NO;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
 				GCC_WARN_UNUSED_VARIABLE = NO;
@@ -514,6 +518,7 @@
 					"GAMEPLAY_PATH/external-deps/oggvorbis/include",
 				);
 				INFOPLIST_FILE = "TEMPLATE_PROJECT-ios.plist";
+                IPHONEOS_DEPLOYMENT_TARGET = 5.1;
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"GAMEPLAY_PATH/external-deps/libpng/lib/ios/$(CURRENT_ARCH)\"",
@@ -521,6 +526,7 @@
 					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/ios/$(CURRENT_ARCH)\"",
 				);
 				SDKROOT = iphoneos;
+                TARGETED_DEVICE_FAMILY = "1,2";
 				USER_HEADER_SEARCH_PATHS = "";
 				WRAPPER_EXTENSION = app;
 			};

BIN=BIN
gameplay-template/icon.png


+ 2 - 2
gameplay-template/res/box.material

@@ -5,8 +5,8 @@ material box
         pass
         {
             // shaders
-            vertexShader = res/shaders/colored.vsh
-            fragmentShader = res/shaders/colored.fsh
+            vertexShader = res/colored.vsh
+            fragmentShader = res/colored.fsh
             
             // uniforms
             u_worldViewProjectionMatrix = WORLD_VIEW_PROJECTION_MATRIX

+ 111 - 0
gameplay-template/res/colored.fsh

@@ -0,0 +1,111 @@
+#ifdef OPENGL_ES
+precision highp float;
+#endif
+
+// Uniforms
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_ambientColor;                    // Ambient color
+uniform vec4 u_diffuseColor;                    // Diffuse color
+#if defined(GLOBAL_ALPHA)
+uniform float u_globalAlpha;                    // Global alpha value
+#endif
+
+// Inputs
+varying vec3 v_normalVector;                    // NormalVector in view space.
+
+// Global variables
+vec4 _baseColor;                                // Base color
+vec3 _ambientColor;                             // Ambient Color
+vec3 _diffuseColor;                             // Diffuse Color
+
+void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
+{
+    // Ambient
+    _ambientColor = _baseColor.rgb * u_ambientColor;
+
+    // Diffuse
+    float ddot = dot(normalVector, lightDirection);
+    float diffuseIntensity = attenuation * ddot;
+    diffuseIntensity = max(0.0, diffuseIntensity);
+    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec4 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex.
+
+void applyLight()
+{
+    // Normalize the vectors.
+    vec3 normalVector = normalize(v_normalVector);
+    
+    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection.xyz);
+    
+    // Fetch point light attenuation.
+    float pointLightAttenuation = v_vertexToPointLightDirection.w;
+    lighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform vec3 u_spotLightDirection;              // Direction of the spot light.
+uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
+varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;           // Attenuation of spot light.
+
+float lerpstep( float lower, float upper, float s)
+{
+    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
+}
+
+void applyLight()
+{
+    // Normalize the vectors.
+    vec3 normalVector = normalize(v_normalVector);
+    vec3 spotLightDirection = u_spotLightDirection; 
+    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
+
+    // "-lightDirection" is used because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
+
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+
+    lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
+}
+
+#else
+
+uniform vec3 u_lightDirection;       	        // Light direction
+
+void applyLight()
+{
+    // Normalize the vectors.
+    vec3 normalVector = normalize(v_normalVector);
+    vec3 lightDirection = normalize(u_lightDirection);
+
+    lighting(normalVector, -lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+    // Fetch diffuse color from texture.
+    _baseColor = u_diffuseColor;
+
+    // Apply light
+    applyLight();
+
+    // Light the pixel
+    gl_FragColor.a = _baseColor.a;
+    gl_FragColor.rgb = _ambientColor + _diffuseColor;
+
+#if defined(GLOBAL_ALPHA)
+    gl_FragColor.a *= u_globalAlpha;
+#endif
+}

+ 183 - 0
gameplay-template/res/colored.vsh

@@ -0,0 +1,183 @@
+// Uniforms
+uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
+
+// Inputs
+attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
+attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
+
+// Outputs
+varying vec3 v_normalVector;                        // NormalVector in view space.
+
+#if defined(SKINNING)
+
+attribute vec4 a_blendWeights;
+attribute vec4 a_blendIndices;
+
+// 32 4x3 matrices as an array of floats
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
+
+// Common vectors.
+vec4 _skinnedPosition;
+vec3 _skinnedNormal;
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[3]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+void skinNormal(float blendWeight, int matrixIndex)
+{
+    vec3 tmp;
+
+    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
+    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
+    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
+
+    _skinnedNormal += blendWeight * tmp;
+}
+
+vec3 getNormal()
+{
+    _skinnedNormal = vec3(0.0);
+
+    // Transform normal to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[3]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    return _skinnedNormal;
+}
+
+#else
+
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+vec3 getNormal()
+{
+    return a_normal;
+}
+
+#endif
+
+#if defined(POINT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
+uniform vec3 u_pointLightPosition;                  // Position
+uniform float u_pointLightRangeInverse;             // Inverse of light range.
+varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+    
+    // Compute the light direction.
+    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+    
+    vec4 vertexToPointLightDirection;
+    vertexToPointLightDirection.xyz = lightDirection;
+    
+    // Attenuation.
+    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToPointLightDirection =  vertexToPointLightDirection;
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
+uniform vec3 u_spotLightPosition;                   // Position
+uniform float u_spotLightRangeInverse;              // Inverse of light range.
+varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
+varying float v_spotLightAttenuation;               // Attenuation of spot light.
+
+void applyLight(vec4 position)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+
+    // Compute the light direction.
+    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToSpotLightDirection = lightDirection;
+}
+
+#else
+
+void applyLight(vec4 position)
+{
+}
+
+#endif
+
+void main()
+{
+    vec4 position = getPosition();
+    vec3 normal = getNormal();
+        
+    // Transform position to clip space.
+    gl_Position = u_worldViewProjectionMatrix * position;
+
+    // Transform normal to view space.
+    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
+                                                u_inverseTransposeWorldViewMatrix[1].xyz,
+                                                u_inverseTransposeWorldViewMatrix[2].xyz);
+    v_normalVector = inverseTransposeWorldViewMatrix * normal;
+
+    // Apply light.
+    applyLight(position);
+}

+ 7 - 4
gameplay-template/src/TemplateGame.cpp

@@ -11,10 +11,13 @@ TemplateGame::TemplateGame()
 void TemplateGame::initialize()
 {
     // Load game scene from file
-    Package* pkg = Package::create("res/box.gpb");
-    _scene = pkg->loadScene();
-    SAFE_RELEASE(pkg);
+    Bundle* bundle = Bundle::create("res/box.gpb");
+    _scene = bundle->loadScene();
+    SAFE_RELEASE(bundle);
 
+    // Set the aspect ratio for the scene's camera to match the current resolution
+    _scene->getActiveCamera()->setAspectRatio((float)getWidth() / (float)getHeight());
+    
     // Get light node
     Node* lightNode = _scene->findNode("directionalLight");
     Light* light = lightNode->getLight();
@@ -47,7 +50,7 @@ void TemplateGame::render(long elapsedTime)
     _scene->visit(this, &TemplateGame::drawScene);
 }
 
-bool TemplateGame::drawScene(Node* node, void* cookie)
+bool TemplateGame::drawScene(Node* node)
 {
     // If the node visited contains a model, draw it
     Model* model = node->getModel(); 

+ 2 - 2
gameplay-template/src/TemplateGame.h

@@ -18,7 +18,7 @@ public:
     TemplateGame();
 
     /**
-     * Touch event handler.
+     * @see Game::touchEvent
      */
     void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
@@ -49,7 +49,7 @@ private:
     /**
      * Draws the scene each frame.
      */
-    bool drawScene(Node* node, void* cookie);
+    bool drawScene(Node* node);
 
     Scene* _scene;
 };

+ 1 - 32
gameplay.doxyfile

@@ -689,38 +689,7 @@ INPUT_ENCODING         = UTF-8
 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py 
 # *.f90 *.f *.for *.vhd *.vhdl
 
-FILE_PATTERNS          = *.c \
-                         *.cc \
-                         *.cxx \
-                         *.cpp \
-                         *.c++ \
-                         *.d \
-                         *.java \
-                         *.ii \
-                         *.ixx \
-                         *.ipp \
-                         *.i++ \
-                         *.inl \
-                         *.h \
-                         *.hh \
-                         *.hxx \
-                         *.hpp \
-                         *.h++ \
-                         *.idl \
-                         *.odl \
-                         *.cs \
-                         *.php \
-                         *.php3 \
-                         *.inc \
-                         *.m \
-                         *.mm \
-                         *.dox \
-                         *.py \
-                         *.f90 \
-                         *.f \
-                         *.for \
-                         *.vhd \
-                         *.vhdl
+FILE_PATTERNS          = *.h
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories 
 # should be searched for input files as well. Possible values are YES and NO. 

+ 7 - 7
gameplay.sln

@@ -20,7 +20,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample03-character", "gamep
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay-encoder", "gameplay-encoder\gameplay-encoder.vcxproj", "{9D69B743-4872-4DD1-8E30-0087C64298D7}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-particles", "gameplay-samples\sample04-particles\sample04-particles.vcxproj", "{F47B5740-3C0C-BACE-4C2B-EE23A358D499}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-particles", "gameplay-samples\sample04-particles\sample04-particles.vcxproj", "{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}"
 	ProjectSection(ProjectDependencies) = postProject
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 	EndProjectSection
@@ -67,12 +67,12 @@ Global
 		{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.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
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|Win32.ActiveCfg = Debug|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|Win32.Build.0 = Debug|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|Win32.ActiveCfg = Release|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.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

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

@@ -28,6 +28,10 @@
 		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 */; };
+		426878AC153F4BB300844500 /* FlowLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 426878AA153F4BB300844500 /* FlowLayout.cpp */; };
+		426878AD153F4BB300844500 /* FlowLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 426878AA153F4BB300844500 /* FlowLayout.cpp */; };
+		426878AE153F4BB300844500 /* FlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 426878AB153F4BB300844500 /* FlowLayout.h */; };
+		426878AF153F4BB300844500 /* FlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 426878AB153F4BB300844500 /* FlowLayout.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 */; };
@@ -400,6 +404,8 @@
 		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; };
+		426878AA153F4BB300844500 /* FlowLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FlowLayout.cpp; path = src/FlowLayout.cpp; sourceTree = SOURCE_ROOT; };
+		426878AB153F4BB300844500 /* FlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlowLayout.h; path = src/FlowLayout.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; };
 		428390981489D6E800E2B2F5 /* SceneLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SceneLoader.h; path = src/SceneLoader.h; sourceTree = SOURCE_ROOT; };
@@ -730,6 +736,8 @@
 				42CD0DD3147D8FF50000361E /* Effect.h */,
 				42CD0DD4147D8FF50000361E /* FileSystem.cpp */,
 				42CD0DD5147D8FF50000361E /* FileSystem.h */,
+				426878AA153F4BB300844500 /* FlowLayout.cpp */,
+				426878AB153F4BB300844500 /* FlowLayout.h */,
 				42CD0DD6147D8FF50000361E /* Font.cpp */,
 				42CD0DD7147D8FF50000361E /* Font.h */,
 				5BD5263F150F822A004C9099 /* Form.cpp */,
@@ -1055,6 +1063,7 @@
 				4251B131152D049B002F6199 /* ScreenDisplayer.h in Headers */,
 				4251B135152D049B002F6199 /* ThemeStyle.h in Headers */,
 				422260D81537790F0011E3AB /* Bundle.h in Headers */,
+				426878AE153F4BB300844500 /* FlowLayout.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1151,6 +1160,7 @@
 				4251B132152D049B002F6199 /* ScreenDisplayer.h in Headers */,
 				4251B136152D049B002F6199 /* ThemeStyle.h in Headers */,
 				422260D91537790F0011E3AB /* Bundle.h in Headers */,
+				426878AF153F4BB300844500 /* FlowLayout.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1306,6 +1316,7 @@
 				4251B133152D049B002F6199 /* ThemeStyle.cpp in Sources */,
 				4271C08E15337C8200B89DA7 /* Layout.cpp in Sources */,
 				422260D61537790F0011E3AB /* Bundle.cpp in Sources */,
+				426878AC153F4BB300844500 /* FlowLayout.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1397,6 +1408,7 @@
 				4251B134152D049B002F6199 /* ThemeStyle.cpp in Sources */,
 				4271C08F15337C8200B89DA7 /* Layout.cpp in Sources */,
 				422260D71537790F0011E3AB /* Bundle.cpp in Sources */,
+				426878AD153F4BB300844500 /* FlowLayout.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

BIN=BIN
gameplay/res/icon.png


+ 0 - 0
gameplay/res/icon_black_transparent128.ico → gameplay/res/icon_128.ico


+ 0 - 0
gameplay/res/icon_black_transparent16.ico → gameplay/res/icon_16.ico


+ 0 - 0
gameplay/res/icon_black_transparent32.ico → gameplay/res/icon_32.ico


+ 0 - 0
gameplay/res/icon_black_transparent64.ico → gameplay/res/icon_64.ico


BIN=BIN
gameplay/res/icon_black.psd


BIN=BIN
gameplay/res/icon_black128.ico


BIN=BIN
gameplay/res/icon_black16.ico


BIN=BIN
gameplay/res/icon_black32.ico


BIN=BIN
gameplay/res/icon_black64.ico


BIN=BIN
gameplay/res/icon_black_transparent.psd


BIN=BIN
gameplay/res/icon_white_transparent.psd


BIN=BIN
gameplay/res/icon_white_transparent128.ico


BIN=BIN
gameplay/res/icon_white_transparent16.ico


BIN=BIN
gameplay/res/icon_white_transparent32.ico


BIN=BIN
gameplay/res/icon_white_transparent64.ico


+ 13 - 0
gameplay/src/Animation.cpp

@@ -146,6 +146,19 @@ AnimationClip* Animation::getClip(const char* id)
     }
 }
 
+AnimationClip* Animation::getClip(unsigned int index) const
+{
+    if (_clips)
+        return _clips->at(index);
+
+    return NULL;
+}
+
+unsigned int Animation::getClipCount() const
+{
+    return _clips ? _clips->size() : 0;
+}
+
 void Animation::play(const char* clipId)
 {
     // If id is NULL, play the default clip.

+ 12 - 0
gameplay/src/Animation.h

@@ -66,6 +66,18 @@ public:
      * @return The AnimationClip with the specified ID; NULL if an AnimationClip with the given ID is not found.
      */
     AnimationClip* getClip(const char* clipId = NULL);
+
+    /**
+     * Returns the AnimationClip at the given index.
+     *
+     * @param index Index of the clip to return.
+     */
+    AnimationClip* getClip(unsigned int index) const;
+
+    /**
+     * Returns the number of animation clips in this animation.
+     */
+    unsigned int getClipCount() const;
     
     /**
      * Plays the AnimationClip with the specified name. 

+ 1 - 7
gameplay/src/AnimationClip.cpp

@@ -304,7 +304,7 @@ void AnimationClip::addEndListener(AnimationClip::Listener* listener)
     _endListeners->push_back(listener);
 }
 
-bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
+bool AnimationClip::update(unsigned long elapsedTime)
 {
     if (isClipStateBitSet(CLIP_IS_PAUSED_BIT))
     {
@@ -439,12 +439,6 @@ bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*
         target = channel->_target;
         value = _values[i];
 
-        // If the target's _animationPropertyBitFlag is clear, we can assume that this is the first
-        // animation channel to act on the target and we can add the target to the list of
-        // active targets stored by the AnimationController.
-        if (target->_animationPropertyBitFlag == 0x00)
-            activeTargets->push_front(target);
-
         // Evaluate the point on Curve
         channel->getCurve()->evaluate(percentComplete, value->_value);
         // Set the animation value on the target property.

+ 3 - 3
gameplay/src/AnimationClip.h

@@ -108,7 +108,7 @@ public:
     /**
      * Sets the AnimationClip's repeat count. Overrides repeat duration.
      *
-     * Use ANIMATION_REPEAT_INDEFINITE to play the AnimationClip indefinitely.
+     * Use REPEAT_INDEFINITE to play the AnimationClip indefinitely.
      * 
      * @param repeatCount The repeat count to set on the AnimationClip.
      */
@@ -124,7 +124,7 @@ public:
     /**
      * Sets the AnimationClip's active duration. Overrides repeat count.
      *
-     * Use ANIMATION_REPEAT_INDEFINITE to play the AnimationClip indefinitely.
+     * Use REPEAT_INDEFINITE to play the AnimationClip indefinitely.
      *
      * @param duration The active duration that is set on the AnimationClip.
      */
@@ -283,7 +283,7 @@ private:
     /**
      * Updates the animation with the elapsed time.
      */
-    bool update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets);
+    bool update(unsigned long elapsedTime);
 
     /**
      * Handles when the AnimationClip begins.

+ 1 - 11
gameplay/src/AnimationController.cpp

@@ -109,7 +109,7 @@ void AnimationController::update(long elapsedTime)
             _runningClips.push_back(clip);
             clipIter = _runningClips.erase(clipIter);
         }
-        else if (clip->update(elapsedTime, &_activeTargets))
+        else if (clip->update(elapsedTime))
         {
             SAFE_RELEASE(clip);
             clipIter = _runningClips.erase(clipIter);
@@ -120,16 +120,6 @@ void AnimationController::update(long elapsedTime)
         }
     }
 
-    // Loop through active AnimationTarget's and reset their _animationPropertyBitFlag for the next frame.
-    std::list<AnimationTarget*>::iterator targetItr = _activeTargets.begin();
-    while (targetItr != _activeTargets.end())
-    {
-        AnimationTarget* target = (*targetItr);
-        target->_animationPropertyBitFlag = 0x00;
-        targetItr++;
-    }
-    _activeTargets.clear();
-    
     if (_runningClips.empty())
         _state = IDLE;
 }

+ 0 - 1
gameplay/src/AnimationController.h

@@ -98,7 +98,6 @@ private:
     
     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.
 };
 
 }

+ 1 - 1
gameplay/src/AnimationTarget.cpp

@@ -8,7 +8,7 @@ namespace gameplay
 {
 
 AnimationTarget::AnimationTarget()
-    : _targetType(SCALAR), _animationPropertyBitFlag(0x00), _animationChannels(NULL)
+    : _targetType(SCALAR), _animationChannels(NULL)
 {
 }
 

+ 7 - 2
gameplay/src/AnimationTarget.h

@@ -194,8 +194,13 @@ protected:
      */
     void cloneInto(AnimationTarget* target, NodeCloneContext &context) const;
 
-    TargetType _targetType;                     // The type of target this is.
-    unsigned char _animationPropertyBitFlag;    // Bit flag used to indicate which properties on the AnimationTarget are currently animating.
+    /**
+     * The target's type. 
+     *
+     * @see TargetType::SCALAR
+     * @see TargetType::TRANSFORM
+     */
+    TargetType _targetType;
 
 private:
 

+ 7 - 10
gameplay/src/Base.h

@@ -198,14 +198,11 @@ extern void printError(const char* format, ...);
     extern PFNGLISVERTEXARRAYOESPROC glIsVertexArray;
     #define glClearDepth glClearDepthf
     #define OPENGL_ES
-    #define OPENGL_ES_PVR    
+    #define USE_PVRTC
 #elif WIN32
     #define WIN32_LEAN_AND_MEAN
-    #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
-    #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
-    #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
-    #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
     #include <GL/glew.h>
+    #define USE_VAO
 #elif __APPLE__
     #include "TargetConditionals.h"
     #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
@@ -217,7 +214,8 @@ extern void printError(const char* format, ...);
         #define glIsVertexArray glIsVertexArrayOES
         #define glClearDepth glClearDepthf
         #define OPENGL_ES
-        #define OPENGL_ES_PVR    
+        #define USE_PVRTC
+        #define USE_VAO
     #elif TARGET_OS_MAC
         #include <OpenGL/gl.h>
         #include <OpenGL/glext.h>
@@ -225,13 +223,12 @@ extern void printError(const char* format, ...);
         #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
         #define glGenVertexArrays glGenVertexArraysAPPLE
         #define glIsVertexArray glIsVertexArrayAPPLE
+        #define USE_VAO
     #else
         #error "Unsupported Apple Device"
     #endif
 #endif
 
-
-
 // Graphics (GLSL)
 #define VERTEX_ATTRIBUTE_POSITION_NAME              "a_position"
 #define VERTEX_ATTRIBUTE_NORMAL_NAME                "a_normal"
@@ -240,9 +237,9 @@ extern void printError(const char* format, ...);
 #define VERTEX_ATTRIBUTE_BINORMAL_NAME              "a_binormal"
 #define VERTEX_ATTRIBUTE_BLENDWEIGHTS_NAME          "a_blendWeights"
 #define VERTEX_ATTRIBUTE_BLENDINDICES_NAME          "a_blendIndices"
-#define VERTEX_ATTRIBUTE_TEXCOORD_PREFIX            "a_texCoord"
+#define VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME       "a_texCoord"
 
-// Hardware Resources
+// Hardware buffer
 namespace gameplay
 {
 typedef GLint VertexAttribute;

+ 19 - 3
gameplay/src/CheckBox.h

@@ -44,6 +44,11 @@ public:
      */
     bool isChecked();
 
+    /**
+     * Sets whether the checkbox is checked.
+     *
+     * @param checked TRUE if the checkbox is checked; FALSE if the checkbox is not checked.
+     */
     void setChecked(bool checked);
 
     /**
@@ -124,10 +129,21 @@ protected:
      * @param clip The container position this control is relative to.
      */
     void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
+
+    /**
+     * Whether this checkbox is currently checked.
+     */
+    bool _checked;
 
-    bool _checked;      // Whether this checkbox is currently checked.
-    Vector2 _imageSize;  // The size to draw the checkbox icon, if different from its size in the texture.
-    Theme::ThemeImage* _image;
+    /**
+     * The size to draw the checkbox icon, if different from its size in the texture.
+     */
+    Vector2 _imageSize;
+
+    /**
+     * The Theme::ThemeImage to display for the checkbox.
+     */
+    Theme::ThemeImage* _image;
 
 private:
 

+ 9 - 2
gameplay/src/Container.h

@@ -231,8 +231,15 @@ protected:
      */
     void addControls(Theme* theme, Properties* properties);
 
-    Layout* _layout;                    // This container's layout.
-    std::vector<Control*> _controls;    // List of controls within this container.
+    /**
+     * The container's layout.
+     */
+    Layout* _layout;
+
+    /**
+     * List of controls within the container.
+     */
+    std::vector<Control*> _controls;
 
 private:
 

+ 15 - 73
gameplay/src/Control.cpp

@@ -900,97 +900,39 @@ namespace gameplay
         switch(propertyId)
         {
         case ANIMATE_POSITION:
-            applyAnimationValuePositionX(value->getFloat(0), blendWeight);
-            applyAnimationValuePositionY(value->getFloat(1), blendWeight);
+            _bounds.x = Curve::lerp(blendWeight, _bounds.x, value->getFloat(0));
+            _bounds.y = Curve::lerp(blendWeight, _bounds.y, value->getFloat(1));
+            _dirty = true;
             break;
         case ANIMATE_POSITION_X:
-            applyAnimationValuePositionX(value->getFloat(0), blendWeight);
+            _bounds.x = Curve::lerp(blendWeight, _bounds.x, value->getFloat(0));
+            _dirty = true;
             break;
         case ANIMATE_POSITION_Y:
-            applyAnimationValuePositionY(value->getFloat(0), blendWeight);
+            _bounds.y = Curve::lerp(blendWeight, _bounds.y, value->getFloat(0));
+            _dirty = true;
             break;
         case ANIMATE_SIZE:
-            applyAnimationValueSizeWidth(value->getFloat(0), blendWeight);
-            applyAnimationValueSizeHeight(value->getFloat(1), blendWeight);
+            _bounds.width = Curve::lerp(blendWeight, _bounds.width, value->getFloat(0));
+            _bounds.height = Curve::lerp(blendWeight, _bounds.height, value->getFloat(1));
+            _dirty = true;
             break;
         case ANIMATE_SIZE_WIDTH:
-            applyAnimationValueSizeWidth(value->getFloat(0), blendWeight);
+            _bounds.width = Curve::lerp(blendWeight, _bounds.width, value->getFloat(0));
+            _dirty = true;
             break;
         case ANIMATE_SIZE_HEIGHT:
-            applyAnimationValueSizeHeight(value->getFloat(0), blendWeight);
+            _bounds.height = Curve::lerp(blendWeight, _bounds.height, value->getFloat(0));
+            _dirty = true;
             break;
         case ANIMATE_OPACITY:
-            applyAnimationValueOpacity();
+            _dirty = true;
         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, _bounds.width, width);
-        }
-        _bounds.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, _bounds.height, height);
-        }
-        _bounds.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;

+ 45 - 20
gameplay/src/Control.h

@@ -94,6 +94,10 @@ public:
     class Listener
     {
     public:
+
+        /**
+         * Defines the Listener's event types.
+         */
         enum EventType
         {
             /**
@@ -267,7 +271,7 @@ public:
     /**
      * Set this control to fit vertically within its parent container.
      *
-     * @param autoWidth Whether to size this control to fit vertically within its parent container.
+     * @param autoHeight Whether to size this control to fit vertically within its parent container.
      */
     void setAutoHeight(bool autoHeight);
 
@@ -782,12 +786,12 @@ protected:
     static State getState(const char* state);
 
     /**
-     * Get a ThemeImage from its ID, for a given state.
+     * Get a Theme::ThemeImage from its ID, for a given state.
      *
      * @param id The ID of the image to retrieve.
      * @param state The state to get this image from.
      *
-     * @return The requested image, or NULL if none was found.
+     * @return The requested Theme::ThemeImage, or NULL if none was found.
      */
     Theme::ThemeImage* getImage(const char* id, State state);
 
@@ -798,8 +802,17 @@ protected:
      */
     void notifyListeners(Listener::EventType eventType);
 
+    /**
+     * Gets the Alignment by string.
+     *
+     * @param alignment The string representation of the Alignment type.
+     * @return The Alignment enum value corresponding to the given string.
+     */
     static Alignment getAlignment(const char* alignment);
 
+    /** 
+     * The Control's ID.
+     */ 
     std::string _id;
     State _state;           // Determines overlay used during draw().
     Rectangle _bounds;      // Position, relative to parent container's clipping window, and desired size.
@@ -807,38 +820,50 @@ protected:
     Rectangle _absoluteBounds;
     Rectangle _viewportBounds;
     Rectangle _clip;        // Clipping window of this control's content, after clipping.
+
     bool _dirty;
+    
+    /**
+     * Flag for whether the Control consume's touch events.
+     */
     bool _consumeTouchEvents;
+    
+    /**
+     * The Control's Alignmnet
+     */
     Alignment _alignment;
+    
+    /**
+     * Whether the Control's width is auto-sized.
+     */
     bool _autoWidth;
+    
+    /**
+     * Whether the Control's height is auto-sized.
+     */
     bool _autoHeight;
+    
+    /**
+     * The Control's Theme::Style.
+     */
     Theme::Style* _style;
+    
+    /**
+     * Listeners map of EventType's to a list of Listeners.
+     */
     std::map<Listener::EventType, std::list<Listener*>*>* _listeners;
 
-    float _opacity;         // Current opacity.
+    /**
+     * The current opacity of the control.
+     */
+    float _opacity;
 
 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);
-    
-    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);
 

+ 1 - 1
gameplay/src/Game.inl

@@ -56,7 +56,7 @@ inline void Game::setMultiTouch(bool enabled)
     Platform::setMultiTouch(enabled);
 }
 
-inline bool isMultiTouch()
+inline bool Game::isMultiTouch() const
 {
     return Platform::isMultiTouch();
 }

+ 11 - 0
gameplay/src/Joint.h

@@ -97,8 +97,19 @@ private:
 
 protected:
 
+    /** 
+     * The Matrix representation of the Joint's bind pose.
+     */
     Matrix _bindPose;
+    
+    /** 
+     * Flag used to mark if the Joint's matrix is dirty.
+     */
     bool _jointMatrixDirty;
+    
+    /** 
+     * The number of MeshSkin's influencing the Joint.
+     */
     unsigned int _skinCount;
 };
 

+ 19 - 1
gameplay/src/Label.h

@@ -86,6 +86,13 @@ protected:
      */
     virtual void initialize(Theme::Style* style, Properties* properties);
 
+    /**
+     * Called when a label's properties change. Updates this label's internal rendering
+     * properties, such as its text viewport.
+     *
+     * @param clip The clipping rectangle of this label's parent container.
+     * @param offset The scroll offset of this label's parent container.
+     */
     void update(const Rectangle& clip, const Vector2& offset);
 
     /**
@@ -95,8 +102,19 @@ protected:
      */
     void drawText(const Rectangle& clip);
 
-    std::string _text;      // The text displayed by this label.
+    /**
+     * The text displayed by this label.
+     */
+    std::string _text;
+
+    /**
+     * The font being used to display the label.
+     */
     Font* _font;
+    
+    /**
+     * The text color being used to display the label.
+     */
     Vector4 _textColor;
     Rectangle _textBounds;  // The position and size of this control's text area, before clipping.  Used for text alignment.
 

+ 9 - 46
gameplay/src/MaterialParameter.cpp

@@ -315,6 +315,7 @@ unsigned int MaterialParameter::getAnimationPropertyComponentCount(int propertyI
                     return 0;
             }
         }
+        break;
     }
 
     return 0;
@@ -376,6 +377,7 @@ void MaterialParameter::getAnimationPropertyValue(int propertyId, AnimationValue
                 // UNSUPPORTED: NONE, MATRIX, METHOD, SAMPLER 
             }
         }
+        break;
     }
 }
 
@@ -392,50 +394,21 @@ void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue
                 case FLOAT:
                 {
                     if (_count == 1)
-                    {
-                        if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
-                        {
-                            _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
-                            _value.floatValue = value->getFloat(0);
-                        }
-                        else
-                        {
-                            _value.floatValue = Curve::lerp(blendWeight, _value.floatValue, value->getFloat(0));
-                        }
-                    }
+                        _value.floatValue = Curve::lerp(blendWeight, _value.floatValue, value->getFloat(0));
                     else
-                    {
                         applyAnimationValue(value, blendWeight, 1);
-                    }                    
                     break;
                 }
                 case INT:
                 {
                     if (_count == 1)
                     {
-                        if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
-                        {
-                            _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
-                            _value.intValue = value->getFloat(0);
-                        }
-                        else
-                        {
-                            _value.intValue = Curve::lerp(blendWeight, _value.intValue, value->getFloat(0));
-                        }
+                        _value.intValue = Curve::lerp(blendWeight, _value.intValue, value->getFloat(0));
                     }
                     else
                     {
-                        if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
-                        {
-                            _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
-                            for (unsigned int i = 0; i < _count; i++)
-                                _value.intPtrValue[i] = value->getFloat(i);
-                        }
-                        else
-                        {
-                            for (unsigned int i = 0; i < _count; i++)
-                                _value.intPtrValue[i] = Curve::lerp(blendWeight, _value.intPtrValue[i], value->getFloat(i));
-                        }
+                        for (unsigned int i = 0; i < _count; i++)
+                            _value.intPtrValue[i] = Curve::lerp(blendWeight, _value.intPtrValue[i], value->getFloat(i));
                     }
                     break;
                 }
@@ -454,28 +427,18 @@ void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue
                     applyAnimationValue(value, blendWeight, 4);
                     break;
                 }
-
                 // UNSUPPORTED: NONE, MATRIX, METHOD, SAMPLER 
             }
         }
+        break;
     }
 }
 
 void MaterialParameter::applyAnimationValue(AnimationValue* value, float blendWeight, int components)
 {
     unsigned int count = _count * components;
-    if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
-    {
-        _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
-
-        for (unsigned int i = 0; i < count; i++)
-            _value.floatPtrValue[i] = value->getFloat(i);
-    }
-    else
-    {
-        for (unsigned int i = 0; i < count; i++)
-            _value.floatPtrValue[i] = Curve::lerp(blendWeight, _value.floatPtrValue[i], value->getFloat(i));
-    }
+    for (unsigned int i = 0; i < count; i++)
+        _value.floatPtrValue[i] = Curve::lerp(blendWeight, _value.floatPtrValue[i], value->getFloat(i));
 }
 
 void MaterialParameter::cloneInto(MaterialParameter* materialParameter) const

+ 1 - 3
gameplay/src/MaterialParameter.h

@@ -167,9 +167,7 @@ public:
     void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f);
 
 private:
-
-    static const char ANIMATION_UNIFORM_BIT = 0x01;
-    
+   
     /**
      * Constructor.
      */

+ 1 - 11
gameplay/src/Model.cpp

@@ -252,14 +252,13 @@ void Model::draw(bool wireframe)
         // No mesh parts (index buffers).
         if (_material)
         {
-            GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
-
             Technique* technique = _material->getTechnique();
             unsigned int passCount = technique->getPassCount();
             for (unsigned int i = 0; i < passCount; ++i)
             {
                 Pass* pass = technique->getPass(i);
                 pass->bind();
+                GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
                 if (wireframe && (_mesh->getPrimitiveType() == Mesh::TRIANGLES || _mesh->getPrimitiveType() == Mesh::TRIANGLE_STRIP))
                 {
                     unsigned int vertexCount = _mesh->getVertexCount();
@@ -284,15 +283,6 @@ void Model::draw(bool wireframe)
 
             // Get the material for this mesh part.
             Material* material = getMaterial(i);
-            /*if (_partMaterials && i < _partCount && _partMaterials[i])
-            {
-                material = _partMaterials[i]; // Use part material
-            }
-            else
-            {
-                material = _material; // Use shared material
-            }*/
-
             if (material)
             {
                 Technique* technique = material->getTechnique();

+ 19 - 5
gameplay/src/Node.cpp

@@ -15,6 +15,7 @@
 // Node property flags
 #define NODE_FLAG_VISIBLE 1
 #define NODE_FLAG_TRANSPARENT 2
+#define NODE_FLAG_DYNAMIC 4
 
 namespace gameplay
 {
@@ -235,6 +236,19 @@ void Node::setTransparent(bool transparent)
         _nodeFlags &= ~NODE_FLAG_TRANSPARENT;
 }
 
+bool Node::isDynamic() const
+{
+    return ((_nodeFlags & NODE_FLAG_DYNAMIC) == NODE_FLAG_DYNAMIC);
+}
+
+void Node::setDynamic(bool dynamic)
+{
+    if (dynamic)
+        _nodeFlags |= NODE_FLAG_DYNAMIC;
+    else
+        _nodeFlags &= ~NODE_FLAG_DYNAMIC;
+}
+
 void* Node::getUserPointer() const
 {
     return (_userData ? _userData->pointer : NULL);
@@ -1004,10 +1018,10 @@ PhysicsCollisionObject* Node::setCollisionObject(Properties* properties)
     // Check if the properties is valid.
     if (!properties || 
         !(strcmp(properties->getNamespace(), "character") == 0 || 
-        strcmp(properties->getNamespace(), "ghost") == 0 || 
-        strcmp(properties->getNamespace(), "rigidbody") == 0))
+        strcmp(properties->getNamespace(), "ghostObject") == 0 || 
+        strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
-        WARN("Failed to load collision object from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
+        WARN("Failed to load collision object from properties object: must be non-null object and have namespace equal to \'character\', \'ghostObject\', or \'rigidBody\'.");
         return NULL;
     }
 
@@ -1015,11 +1029,11 @@ PhysicsCollisionObject* Node::setCollisionObject(Properties* properties)
     {
         _collisionObject = PhysicsCharacter::create(this, properties);
     }
-    else if (strcmp(properties->getNamespace(), "ghost") == 0)
+    else if (strcmp(properties->getNamespace(), "ghostObject") == 0)
     {
         _collisionObject = PhysicsGhostObject::create(this, properties);
     }
-    else if (strcmp(properties->getNamespace(), "rigidbody") == 0)
+    else if (strcmp(properties->getNamespace(), "rigidBody") == 0)
     {
         _collisionObject = PhysicsRigidBody::create(this, properties);
     }

+ 110 - 0
gameplay/src/Node.h

@@ -148,6 +148,26 @@ public:
      */
     void setTransparent(bool transparent);
 
+    /**
+     * Returns whether this node is dynamic.
+     *
+     * The dynamic propery can be used to flag nodes as being non-static.
+     * This can be useful for modifying behavior or rendering/material
+     * logic at runtime for static vs dynamic (moving) objects. An
+     * example would be determing whether to use static or  dyanmic
+     * lighting materials for node models during loading.
+     *
+     * @return Whether this node is dynamic (false by default).
+     */
+    bool isDynamic() const;
+
+    /**
+     * Sets whether this node is dynamic.
+     *
+     * @param dynamic Whether the node is dynamic.
+     */
+    void setDynamic(bool dynamic);
+
     /**
      * Returns the user pointer for this node.
      *
@@ -618,30 +638,120 @@ protected:
      */
     struct UserData
     {
+        /**
+         * Constructor.
+         */
         UserData() : pointer(NULL), cleanupCallback(NULL) {}
+
+        /**
+         * A pointer to custom user data.
+         */
         void* pointer;
+
+        /** 
+         * Cleanup callback.
+         */
         void (*cleanupCallback)(void*);
     };
 
+    /**
+     * The Scene this node belongs to.
+     */
     Scene* _scene;
+
+    /**
+     * The Node's ID.
+     */ 
     std::string _id;
+
+    /**
+     * Pointer to the Node's first child.
+     */
     Node* _firstChild;
+    
+    /**
+     * Pointer to the Node's next child.
+     */
     Node* _nextSibling;
+    
+    /**
+     * Pointer to the Node's previous sibling.
+     */
     Node* _prevSibling;
+
+    /**
+     * Pointer to the Node's parent.
+     */
     Node* _parent;
+
+    /**
+     * The number of children belonging to the Node.
+     */
     unsigned int _childCount;
+
+    /**
+     * Node property flags. 
+     */ 
     unsigned int _nodeFlags;
+
+    /**
+     * Pointer to the Camera attached to the Node.
+     */
     Camera* _camera;
+
+    /**
+     * Pointer to the Light attached to the Node.
+     */ 
     Light* _light;
+
+    /**
+     * Pointer to the Model attached to the Node.
+     */
     Model* _model;
+    
+    /**
+     * Pointer to the Form attached to the Node.
+     */
     Form* _form;
+    
+    /**
+     * Pointer to the AudioSource attached to the Node.
+     */
     AudioSource* _audioSource;
+    
+    /**
+     * Pointer to the ParticleEmitter attached to the Node.
+     */
     ParticleEmitter* _particleEmitter;
+    
+    /**
+     * Pointer to the PhysicsCollisionObject attached to the Node.
+     */
     PhysicsCollisionObject* _collisionObject;
+    
+    /**
+     * World Matrix representation of the Node.
+     */
     mutable Matrix _world;
+
+    /**
+     * Dirty bits flag for the Node.
+     */
     mutable int _dirtyBits;
+    
+    /**
+     * A flag indicating if the Node's hierarchy has changed.
+     */ 
     bool _notifyHierarchyChanged;
+
+    /**
+     * The Bounding Sphere containing the Node.
+     */
     mutable BoundingSphere _bounds;
+
+    /**
+     * Pointer to custom UserData and cleanup call back that can be stored in a Node.
+     */
     UserData* _userData;
 };
 

+ 3 - 0
gameplay/src/ParticleEmitter.h

@@ -142,6 +142,9 @@ class ParticleEmitter : public Ref
 
 public:
 
+    /**
+     * Defines the types of texture blending 
+     */
     enum TextureBlending
     {
         BLEND_OPAQUE,

+ 117 - 181
gameplay/src/PhysicsCharacter.cpp

@@ -17,11 +17,17 @@ class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexR
 {
 public:
 
+    /**
+     * @see btCollisionWorld::ClosestConvexResultCallback::ClosestConvexResultCallback
+     */
     ClosestNotMeConvexResultCallback(PhysicsCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
         : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), _me(me), _up(up), _minSlopeDot(minSlopeDot)
     {
     }
 
+    /**
+     * @see btCollisionWorld::ClosestConvexResultCallback::addSingleResult
+     */
     btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
     {
         PhysicsCollisionObject* object = reinterpret_cast<PhysicsCollisionObject*>(convexResult.m_hitCollisionObject->getUserPointer());
@@ -59,9 +65,9 @@ protected:
 
 PhysicsCharacter::PhysicsCharacter(Node* node, const PhysicsCollisionShape::Definition& shape, float mass)
     : PhysicsGhostObject(node, shape), _moveVelocity(0,0,0), _forwardVelocity(0.0f), _rightVelocity(0.0f),
-    _fallVelocity(0, 0, 0), _currentVelocity(0,0,0), _normalizedVelocity(0,0,0),
-    _colliding(false), _collisionNormal(0,0,0), _currentPosition(0,0,0),
-    _stepHeight(0.1f), _slopeAngle(0.0f), _cosSlopeAngle(0.0f), _physicsEnabled(true), _mass(mass)
+    _verticalVelocity(0, 0, 0), _currentVelocity(0,0,0), _normalizedVelocity(0,0,0),
+    _colliding(false), _collisionNormal(0,0,0), _currentPosition(0,0,0), _stepHeight(0.1f),
+    _slopeAngle(0.0f), _cosSlopeAngle(0.0f), _physicsEnabled(true), _mass(mass)
 {
     setMaxSlopeAngle(45.0f);
 
@@ -99,6 +105,8 @@ PhysicsCharacter* PhysicsCharacter::create(Node* node, Properties* properties)
     // Load the character's parameters.
     properties->rewind();
     float mass = 1.0f;
+    float maxStepHeight = 0.1f;
+    float maxSlopeAngle = 0.0f;
     const char* name = NULL;
     while ((name = properties->getNextProperty()) != NULL)
     {
@@ -106,10 +114,20 @@ PhysicsCharacter* PhysicsCharacter::create(Node* node, Properties* properties)
         {
             mass = properties->getFloat();
         }
+        else if (strcmp(name, "maxStepHeight") == 0)
+        {
+            maxStepHeight = properties->getFloat();
+        }
+        else if (strcmp(name, "maxSlopeAngle") == 0)
+        {
+            maxSlopeAngle = properties->getFloat();
+        }
     }
 
     // Create the physics character.
     PhysicsCharacter* character = new PhysicsCharacter(node, *shape, mass);
+    character->setMaxStepHeight(maxStepHeight);
+    character->setMaxSlopeAngle(maxSlopeAngle);
     SAFE_DELETE(shape);
 
     return character;
@@ -156,120 +174,6 @@ void PhysicsCharacter::setMaxSlopeAngle(float angle)
     _cosSlopeAngle = std::cos(MATH_DEG_TO_RAD(angle));
 }
 
-void PhysicsCharacter::addAnimation(const char* name, AnimationClip* clip, float moveSpeed)
-{
-    CharacterAnimation a;
-    a.name = name;
-    a.clip = clip;
-    a.moveSpeed = moveSpeed;
-    a.layer = 0;
-    a.playing = false;
-    a.animationFlags = ANIMATION_STOP;
-    a.prev = NULL;
-    _animations[name] = a;
-}
-
-AnimationClip* PhysicsCharacter::getAnimation(const char* name)
-{
-    if (name)
-    {
-        // Lookup the specified animation
-        std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
-        if (aitr != _animations.end())
-        {
-            return aitr->second.clip;
-        }
-    }
-    return NULL;
-}
-
-void PhysicsCharacter::play(const char* name, AnimationFlags flags, float speed, unsigned int blendDuration, unsigned int layer)
-{
-    CharacterAnimation* animation = NULL;
-    if (name)
-    {
-        // Lookup the specified animation
-        std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
-        if (aitr == _animations.end())
-            return; // invalid animation name
-
-        animation = &(aitr->second);
-
-        // Set animation flags
-        animation->clip->setRepeatCount(flags & ANIMATION_REPEAT ? AnimationClip::REPEAT_INDEFINITE : 1);
-        animation->clip->setSpeed(speed);
-        animation->animationFlags = flags;
-        animation->layer = layer;
-        animation->blendDuration = blendDuration;
-        animation->prev = NULL;
-
-        // If the animation is already marked playing, do nothing more
-        if (animation->playing)
-            return;
-    }
-
-    play(animation, layer);
-}
-
-void PhysicsCharacter::play(CharacterAnimation* animation, unsigned int layer)
-{
-    // Is there already an animation playing on this layer?
-    std::map<unsigned int, CharacterAnimation*>::iterator litr = _layers.find(layer);
-    CharacterAnimation* prevAnimation = (litr == _layers.end() ? NULL : litr->second);
-    if (prevAnimation && prevAnimation->playing)
-    {
-        // An animation is already playing on this layer
-        if (animation)
-        {
-            if (animation->animationFlags == ANIMATION_RESUME)
-                animation->prev = prevAnimation;
-
-            if (animation->blendDuration > 0L)
-            {
-                // Crossfade from current animation into the new one
-                prevAnimation->clip->crossFade(animation->clip, animation->blendDuration);
-            }
-            else
-            {
-                // Stop the previous animation (no blending)
-                prevAnimation->clip->stop();
-
-                // Play the new animation
-                animation->clip->play();
-            }
-        }
-        else
-        {
-            // No new animaton specified - stop current animation on this layer
-            prevAnimation->clip->stop();
-        }
-
-        prevAnimation->playing = false;
-    }
-    else if (animation)
-    {
-        // No animations currently playing - just play the new one
-        animation->clip->play();
-    }
-
-    // Update animaton and layers
-    if (animation)
-    {
-        animation->playing = true;
-
-        // Update layer to point to the new animation
-        if (litr != _layers.end())
-            litr->second = animation;
-        else
-            _layers[layer] = animation;
-    }
-    else if (litr != _layers.end())
-    {
-        // Remove layer sine we stopped the animation previously on it
-        _layers.erase(litr);
-    }
-}
-
 void PhysicsCharacter::setVelocity(const Vector3& velocity)
 {
     _moveVelocity.setValue(velocity.x, velocity.y, velocity.z);
@@ -305,9 +209,31 @@ void PhysicsCharacter::setRightVelocity(float velocity)
     _rightVelocity = velocity;
 }
 
+Vector3 PhysicsCharacter::getCurrentVelocity() const
+{
+    Vector3 v(_currentVelocity.x(), _currentVelocity.y(), _currentVelocity.z());
+    v.x += _verticalVelocity.x();
+    v.y += _verticalVelocity.y();
+    v.z += _verticalVelocity.z();
+    return v;
+}
+
 void PhysicsCharacter::jump(float height)
 {
-    // TODO
+    // TODO: Add support for different jump modes (i.e. double jump, changing direction in air, holding down jump button for extra height, etc)
+    if (!_verticalVelocity.isZero())
+        return;
+
+    // v = sqrt(v0^2 + 2 a s)
+    //  v0 == initial velocity (zero for jumping)
+    //  a == acceleration (inverse gravity)
+    //  s == linear displacement (height)
+    Vector3 jumpVelocity = -Game::getInstance()->getPhysicsController()->getGravity() * height * 2.0f;
+    jumpVelocity.set(
+        jumpVelocity.x == 0 ? 0 : std::sqrt(jumpVelocity.x),
+        jumpVelocity.y == 0 ? 0 : std::sqrt(jumpVelocity.y),
+        jumpVelocity.z == 0 ? 0 : std::sqrt(jumpVelocity.z));
+    _verticalVelocity += BV(jumpVelocity);
 }
 
 void PhysicsCharacter::updateCurrentVelocity()
@@ -403,58 +329,26 @@ void PhysicsCharacter::updateAction(btCollisionWorld* collisionWorld, btScalar d
 
 void PhysicsCharacter::stepUp(btCollisionWorld* collisionWorld, btScalar time)
 {
-    // Note: btKinematicCharacterController implements this by always just setting
-    // target position to currentPosition.y + stepHeight, and then checking for collisions.
-    // Don't let the character move up if it hits the ceiling (or something above).
-    // Do this WITHOUT using time in the calculation - this way you are always guarnateed
-    // to step over a step that is stepHeight high.
-    // 
-    // Note that stepDown() will be called right after this, so the character will move back
-    // down to collide with the ground so that he smoothly steps up stairs.
-    _currentPosition += btVector3(0, _stepHeight, 0);
-}
+    btVector3 targetPosition(_currentPosition);
 
-void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, float time)
-{
-    // Process currently playing movements+animations and determine final move location
-    float animationMoveSpeed = 0.0f;
-    unsigned int animationCount = 0;
-    for (std::map<unsigned int, CharacterAnimation*>::iterator itr = _layers.begin(); itr != _layers.end(); ++itr)
+    if (_verticalVelocity.isZero())
     {
-        CharacterAnimation* animation = itr->second;
-
-        // If the animation is not playing, ignore it
-        if (!animation->playing)
-            continue;
-
-        AnimationClip* clip = animation->clip;
-
-        // Did the clip finish playing (but we still have it marked playing)?
-        if (!clip->isPlaying())
-        {
-            // If the animaton was flaged the ANIMATION_RESUME bit, start the previously playing animation
-            if ((animation->animationFlags == ANIMATION_RESUME) && animation->prev)
-            {
-                play(animation->prev, animation->prev->layer);
-            }
-
-            animation->playing = false;
+        // Simply increase our poisiton by step height to enable us
+        // to smoothly move over steps.
+        targetPosition += btVector3(0, _stepHeight, 0);
+    }
 
-            continue;
-        }
+    // TODO: Convex sweep test to ensure we didn't hit anything during the step up.
 
-        animationMoveSpeed += animation->moveSpeed;
-        ++animationCount;
-    }
+    _currentPosition = targetPosition;
+}
 
+void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, float time)
+{
     updateCurrentVelocity();
 
     // Calculate final velocity
     btVector3 velocity(_currentVelocity);
-    if (animationCount > 0)
-    {
-        velocity *= animationMoveSpeed;
-    }
     velocity *= time; // since velocity is in meters per second
 
     if (velocity.isZero())
@@ -542,11 +436,12 @@ void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, fl
 
 void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
 {
-    // Contribute basic gravity to fall velocity.
+    // Contribute gravity to vertical velocity.
     btVector3 gravity = Game::getInstance()->getPhysicsController()->_world->getGravity();
-    _fallVelocity += (gravity * time);
+    _verticalVelocity += (gravity * time);
 
-    btVector3 targetPosition = _currentPosition + (_fallVelocity * time);
+    // Compute new position from vertical velocity.
+    btVector3 targetPosition = _currentPosition + (_verticalVelocity * time);
     targetPosition -= btVector3(0, _stepHeight, 0);
 
     // Perform a convex sweep test between current and target position
@@ -554,28 +449,69 @@ void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
     btTransform end;
     start.setIdentity();
     end.setIdentity();
-    start.setOrigin(_currentPosition);
-    end.setOrigin(targetPosition);
 
-    ClosestNotMeConvexResultCallback callback(this, btVector3(0, 1, 0), _cosSlopeAngle);
-    callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
-    callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
+    btScalar fraction = 1.0;
+    int maxIter = 10;
+    while (fraction > btScalar(0.01) && maxIter-- > 0)
+    {
+        start.setOrigin(_currentPosition);
+        end.setOrigin(targetPosition);
 
-    _ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+        btVector3 sweepDirNegative(_currentPosition - targetPosition);
 
-    if (callback.hasHit())
-    {
-        // Collision detected, fix it
-        _currentPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
+        ClosestNotMeConvexResultCallback callback(this, sweepDirNegative, 0.0);
+        callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
+        callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
 
-        // Zero out fall velocity when we hit an object
-        _fallVelocity.setZero();
-    }
-    else
-    {
-        // We can move here
-        _currentPosition = targetPosition;
+        _ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+
+        fraction -= callback.m_closestHitFraction;
+
+        if (callback.hasHit())
+        {
+            // Collision detected, fix it.
+            Vector3 normal(callback.m_hitNormalWorld.x(), callback.m_hitNormalWorld.y(), callback.m_hitNormalWorld.z());
+            normal.normalize();
+
+            float dot = normal.dot(Vector3::unitY());
+            if (dot > 1.0f - MATH_EPSILON)
+            {
+                targetPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
+
+                // Zero out fall velocity when we hit an object going straight down.
+                _verticalVelocity.setZero();
+                break;
+            }
+            else
+            {
+                PhysicsCollisionObject* o = Game::getInstance()->getPhysicsController()->getCollisionObject(callback.m_hitCollisionObject);
+                if (o->getType() == PhysicsCollisionObject::RIGID_BODY && o->isDynamic())
+                {
+                    PhysicsRigidBody* rb = static_cast<PhysicsRigidBody*>(o);
+                    normal.normalize();
+                    rb->applyImpulse(_mass * -normal * sqrt(BV(normal).dot(_verticalVelocity)));
+                }
+
+                updateTargetPositionFromCollision(targetPosition, BV(normal));
+            }
+        }
+        else
+        {
+            // Nothing is in the way.
+            break;
+        }
     }
+
+    // Calculate what the vertical velocity actually is.
+    // In cases where the character might not actually be able to move down,
+    // but isn't intersecting with an object straight down either, we don't
+    // want to keep increasing the vertical velocity until the character 
+    // randomly drops through the floor when it can finally move due to its
+    // vertical velocity having such a great magnitude.
+    if (!_verticalVelocity.isZero())
+        _verticalVelocity = ((targetPosition + btVector3(0.0, _stepHeight, 0.0)) - _currentPosition) / time;
+
+    _currentPosition = targetPosition;
 }
 
 /*

+ 12 - 113
gameplay/src/PhysicsCharacter.h

@@ -18,10 +18,6 @@ namespace gameplay
  * PhysicsCharacter class. This results in a more responsive and typical game
  * character than would be possible if trying to move a character by applying
  * physical simulation with forces.
- *
- * This class can also be used to control animations for a character. Animation
- * clips can be setup for typical character animations, such as walk, run, jump,
- * etc; and the controller will handle blending between these animations as needed.
  */
 class PhysicsCharacter : public PhysicsGhostObject, public btActionInterface
 {
@@ -29,27 +25,6 @@ class PhysicsCharacter : public PhysicsGhostObject, public btActionInterface
 
 public:
 
-    /**
-     * Flags for controlling how a character animation is played back.
-     */
-    enum AnimationFlags
-    {
-        /**
-         * Plays an animation once and then stops.
-         */
-        ANIMATION_STOP,
-
-        /**
-         * Play an animation once and then resumes the previous playing animation.
-         */
-        ANIMATION_RESUME,
-
-        /**
-         * Plays an animation and repeats it indefinitely.
-         */
-         ANIMATION_REPEAT
-    };
-
     /**
      * @see PhysicsCollisionObject#getType
      */
@@ -110,74 +85,13 @@ public:
      */
     void setMaxSlopeAngle(float angle);
 
-    /**
-     * Configures a new animation for this character.
-     *
-     * This method registers an animation for the character, with an associated movement speed.
-     * The moveSpeed specifies how fast the character moves while the animation is playing.
-     * The final velocity of the character is the product of the current move velocity and
-     * the currently playing animation(s) moveSpeed.
-     *
-     * @param name Name of the animation.
-     * @param animationClip Animation clip associated with the new character animation.
-     * @param moveSpeed Base movement speed (meters per second) associated with the animation.
-     */
-    void addAnimation(const char* name, AnimationClip* animationClip, float moveSpeed);
-
-    /**
-     * Returns the animation with the specified name.
-     *
-     * @return The specified animation clip.
-     */
-    AnimationClip* getAnimation(const char* name);
-
-    /**
-     * Plays the specified animation.
-     *
-     * There are some limiations and considerations that should be ponited out when
-     * playing animations:
-     * <li>You should avoid playing multiple animations concurrently that have the same target.
-     * For example, two animations targetting the character's joints should not be played 
-     * concurrently, but it is fine to play one animation that targets the joints and another
-     * that targets the character's Node.
-     * <li>When playing an animation that targets the transform of the character's Node
-     * (such as a motion path animation), the character's velocity vector should be set to
-     * Vector3::zero() so that the PhysicsCharacter stops applying motion directly
-     * and instead relies on the motion animation to control the character.
-     *
-     * The optional animation layer can be used to group animations on separate layers.
-     * Each animation layer can have at most one active animation. Playing multiple
-     * animations concurrently can be achieved by putting the different animations
-     * on separate layers. For example, a motion path animation that targets the
-     * character's Node can be put on one layer, while a running animation that targets
-     * a character's Joints can be put on a separate layer. This allows a character's
-     * movement to be animated at the same time as the run animation is playing.
-     *
-     * @param name Animation name, or NULL to stop all character animations on the given layer.
-     * @param flags Animation flags from the AnimationFlags enumeration.
-     * @param animationSpeed Optional animation speed (default is 1.0).
-     * @param blendDuration Optional number of milliseconds to crossfade between the
-     *      currently playing animation on the given layer and the new animation.
-     * @param layer Optional animation layer.
-     */
-    void play(const char* name, AnimationFlags flags, float animationSpeed = 1.0f, unsigned int blendDuration = 0, unsigned int layer = 0);
-
     /**
      * Sets the velocity of the character.
      *
      * Calling this function sets the velocity (speed and direction) for the character.
      * The velocity is maintained until this method is called again. The final velocity
-     * of the character is determined by product of the current velocity vector(s)
-     * and the current character animation's move speed. Therefore, specifying a
-     * normalized (unit-length) velocity vector results in the character speed being
-     * controled entirely by the current animation's velocity; whereas the speed of
-     * the character can be augmented by modifying the magnitude of the velocity vector.
-
-     * Note that a zero velocity vector and/or a zero animation move speed will
-     * result in no character movement (the character will be stationary). A zero
-     * velocity vector should be used when playing an animation that targets the
-     * character's transform directly (such as a motion path animation), since these
-     * animations will overwrite any transformations on the character's node.
+     * of the character is determined by product of the current velocity, right and
+     * forward vectors.
      *
      * @param velocity Movement velocity.
      */
@@ -219,9 +133,6 @@ public:
      * The forward velocity is defined by the character's current orientation
      * (it is the forward vector from the character's current world transform).
      *
-     * The specified velocity acts as a multiplier on the currently playing animation's
-     * velocity (or, if there is no animation playing, it directly impacts velocity).
-     *
      * Note that a negative velocity (i.e. -1.0f) will move the character backwards.
      *
      * @param velocity Optional velocity modifier.
@@ -234,9 +145,6 @@ public:
      * The right velocity is defined by the character's current orientation
      * (it is the right vector from the character's current world transform).
      *
-     * The specified velocity acts as a multiplier on the currently playing animation's
-     * velocity (or, if there is no animation playing, it directly impacts velocity).
-     *
      * Note that a negative velocity (i.e. -1.0f) will move the character left.
      *
      * @param velocity Optional velocity modifier.
@@ -244,9 +152,16 @@ public:
     void setRightVelocity(float velocity = 1.0f);
 
     /**
-     * Causes the character to jump with the specified initial upwards velocity.
+     * Returns the current velocity of the character.
      *
-     * @param velocity Initial jump velocity.
+     * @return The current velocity.
+     */
+    Vector3 getCurrentVelocity() const;
+
+    /**
+     * Causes the character to jump to the specified height.
+     *
+     * @param height The amount to jump.
      */
     void jump(float height);
 
@@ -269,18 +184,6 @@ protected:
 
 private:
 
-    struct CharacterAnimation
-    {
-        const char* name;
-        AnimationClip* clip;
-        float moveSpeed;
-        unsigned int layer;
-        bool playing;
-        AnimationFlags animationFlags;
-        unsigned int blendDuration;
-        CharacterAnimation* prev;
-    };
-
     /**
      * Creates a new PhysicsCharacter.
      *
@@ -311,8 +214,6 @@ private:
 
     void updateCurrentVelocity();
 
-    void play(CharacterAnimation* animation, unsigned int layer);
-
     void stepUp(btCollisionWorld* collisionWorld, btScalar time);
 
     void stepDown(btCollisionWorld* collisionWorld, btScalar time);
@@ -326,14 +227,12 @@ private:
     btVector3 _moveVelocity;
     float _forwardVelocity;
     float _rightVelocity;
-    btVector3 _fallVelocity;
+    btVector3 _verticalVelocity;
     btVector3 _currentVelocity;
     btVector3 _normalizedVelocity;
     bool _colliding;
     btVector3 _collisionNormal;
     btVector3 _currentPosition;
-    std::map<const char*, CharacterAnimation> _animations;
-    std::map<unsigned int, CharacterAnimation*> _layers;
     btManifoldArray _manifoldArray;
     float _stepHeight;
     float _slopeAngle;

+ 9 - 1
gameplay/src/PhysicsCollisionObject.cpp

@@ -6,9 +6,14 @@
 namespace gameplay
 {
 
-// Internal class used to implement the collidesWith(PhysicsCollisionObject*) function.
+/**
+ * Internal class used to implement the collidesWith(PhysicsCollisionObject*) function.
+ */
 struct CollidesWithCallback : public btCollisionWorld::ContactResultCallback
 {
+    /**
+     * Called with each contact. Needed to implement collidesWith(PhysicsCollisionObject*).
+     */
     btScalar addSingleResult(btManifoldPoint& cp, 
         const btCollisionObject* a, int partIdA, int indexA, 
         const btCollisionObject* b, int partIdB, int indexB)
@@ -17,6 +22,9 @@ struct CollidesWithCallback : public btCollisionWorld::ContactResultCallback
         return 0.0f;
     }
 
+    /**
+     * The result of the callback.
+     */
     bool result;
 };
 

+ 12 - 0
gameplay/src/PhysicsCollisionObject.h

@@ -181,6 +181,7 @@ public:
      * Removes a collision listener.
      *
      * @param listener The listener to remove.
+     * @param object Optional collision object used to filter the collision event.
      */
     void removeCollisionListener(CollisionListener* listener, PhysicsCollisionObject* object = NULL);
 
@@ -215,8 +216,19 @@ protected:
     PhysicsMotionState* getMotionState() const;
 
     // Common member variables
+    /**
+     * Pointer to Node contained by this collision object.
+     */ 
     Node* _node;
+
+    /** 
+     * The PhysicsCollisionObject's motion state.
+     */
     PhysicsMotionState* _motionState;
+    
+    /**
+     * The PhysicsCollisionObject's collision shape.
+     */
     PhysicsCollisionShape* _collisionShape;
 
 };

+ 4 - 4
gameplay/src/PhysicsCollisionShape.cpp

@@ -121,10 +121,10 @@ PhysicsCollisionShape::Definition* PhysicsCollisionShape::Definition::create(Nod
     assert(properties);
     if (!properties || 
         !(strcmp(properties->getNamespace(), "character") == 0 || 
-        strcmp(properties->getNamespace(), "ghost") == 0 || 
-        strcmp(properties->getNamespace(), "rigidbody") == 0))
+        strcmp(properties->getNamespace(), "ghostObject") == 0 || 
+        strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
-        WARN("Failed to load physics collision shape from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
+        WARN("Failed to load physics collision shape from properties object: must be non-null object and have namespace equal to \'character\', \'ghostObject\', or \'rigidBody\'.");
         return NULL;
     }
 
@@ -186,7 +186,7 @@ PhysicsCollisionShape::Definition* PhysicsCollisionShape::Definition::create(Nod
             center = new Vector3();
             properties->getVector3("center", center);
         }
-        else if (strcmp(name, "center-absolute") == 0)
+        else if (strcmp(name, "centerAbsolute") == 0)
         {
             centerIsAbsolute = properties->getBool();
         }

+ 19 - 0
gameplay/src/PhysicsCollisionShape.h

@@ -49,9 +49,28 @@ public:
 
     public:
 
+        /**
+         * Constructor.
+         */
         Definition();
+
+        /** 
+         * Constructs a new Defintion that is a copy of the specified Definition.
+         *
+         * @param definition The Definition to copy.
+         */ 
         Definition(const Definition& definition);
+
+        /**
+         * Assigns the specified Definition as the Definition.
+         *
+         * @param definition The Definition to assign to the Definition.
+         */
         Definition& operator=(const Definition& definition);
+        
+        /**
+         * Destructor.
+         */
         ~Definition();
 
     private:

+ 11 - 0
gameplay/src/PhysicsConstraint.h

@@ -102,8 +102,19 @@ protected:
      */
     static Vector3 offsetByCenterOfMass(const Node* node, const Vector3& v);
 
+    /**
+     * Pointer to the one rigid body bound by this constraint.
+     */
     PhysicsRigidBody* _a;
+    
+    /**
+     * Pointer to the other rigid body bound by this constraint.
+     */
     PhysicsRigidBody* _b;
+    
+    /**
+     * Pointer to the Bullet constraint.
+     */
     btTypedConstraint* _constraint;
 };
 

+ 17 - 4
gameplay/src/PhysicsController.cpp

@@ -185,20 +185,33 @@ bool PhysicsController::sweepTest(PhysicsCollisionObject* object, const Vector3&
 
     // Define the start transform
     btTransform start;
+    start.setIdentity();
     if (object->getNode())
-        start.setFromOpenGLMatrix(object->getNode()->getWorldMatrix().m);
-    else
+    {
+        Vector3 translation;
+        Quaternion rotation;
+        const Matrix& m = object->getNode()->getWorldMatrix();
+        m.getTranslation(&translation);
+        m.getRotation(&rotation);
+
         start.setIdentity();
+        start.setOrigin(BV(translation));
+        start.setRotation(BQ(rotation));
+    }
 
     // Define the end transform
     btTransform end(start);
     end.setOrigin(BV(endPosition));
 
+    float d1 = object->getNode()->getTranslationWorld().distance(endPosition);
+    float d2 = start.getOrigin().distance(end.getOrigin());
+
     // Perform bullet convex sweep test
     SweepTestCallback callback(object);
 
     // If the object is represented by a ghost object, use the ghost object's convex sweep test
     // since it is much faster than the world's version.
+    // NOTE: Unfortunately the ghost object sweep test does not seem reliable here currently, so using world's version instead.
     /*switch (object->getType())
     {
     case PhysicsCollisionObject::GHOST_OBJECT:
@@ -209,8 +222,8 @@ bool PhysicsController::sweepTest(PhysicsCollisionObject* object, const Vector3&
     default:
         _world->convexSweepTest(static_cast<btConvexShape*>(shape->getShape()), start, end, callback, _world->getDispatchInfo().m_allowedCcdPenetration);
         break;
-    }
-    */
+    }*/
+
     _world->convexSweepTest(static_cast<btConvexShape*>(shape->getShape()), start, end, callback, _world->getDispatchInfo().m_allowedCcdPenetration);
 
     // Check for hits and store results

+ 55 - 4
gameplay/src/PhysicsController.h

@@ -95,6 +95,7 @@ public:
      * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
      *      body specified the constraint applies between it and the global physics world object.
      * @param b The second rigid body to constrain (optional).
+     * @return Pointer to the created PhysicsFixedConstraint object.
      */
     PhysicsFixedConstraint* createFixedConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
 
@@ -105,6 +106,7 @@ public:
      * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
      *      body specified the constraint applies between it and the global physics world object.
      * @param b The second rigid body to constrain (optional).
+     * @return Pointer to the created PhysicsGenericConstraint object.
      */
     PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
 
@@ -122,6 +124,7 @@ public:
      *      (in its local space) with respect to the constraint joint (optional).
      * @param translationOffsetB The translation offset for the second rigid body
      *      (in its local space) with respect to the constraint joint (optional).
+     * @return Pointer to the created PhysicsGenericConstraint object.
      */
     PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA, 
                                                       PhysicsRigidBody* b = NULL, const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
@@ -140,6 +143,7 @@ public:
      *      (in its local space) with respect to the constraint joint (optional).
      * @param translationOffsetB The translation offset for the second rigid body
      *      (in its local space) with respect to the constraint joint (optional).
+     * @return Pointer to the created PhysicsHingeConstraint object.
      */
     PhysicsHingeConstraint* createHingeConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
                                                   PhysicsRigidBody* b = NULL, const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
@@ -152,6 +156,7 @@ public:
      * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
      *      body specified the constraint applies between it and the global physics world object.
      * @param b The second rigid body to constrain (optional).
+     * @return Pointer to the created PhysicsSocketConstraint object.
      */
     PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
 
@@ -165,6 +170,7 @@ public:
      * @param b The second rigid body to constrain (optional).
      * @param translationOffsetB The translation offset for the second rigid body
      *      (in its local space) with respect to the constraint joint (optional).
+     * @return Pointer to the created PhysicsSocketConstraint object.
      */
     PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, const Vector3& translationOffsetA,
                                                     PhysicsRigidBody* b = NULL, const Vector3& translationOffsetB = Vector3());
@@ -177,6 +183,7 @@ public:
      * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
      *      body specified the constraint applies between it and the global physics world object.
      * @param b The second rigid body to constrain (optional).
+     * @return Pointer to the created PhysicsSpringConstraint object.
      */
     PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b);
 
@@ -194,6 +201,7 @@ public:
      *      (in its local space) with respect to the constraint joint (optional).
      * @param translationOffsetB The translation offset for the second rigid body
      *      (in its local space) with respect to the constraint joint (optional).
+     * @return Pointer to the created PhysicsSpringConstraint object.
      */
     PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,          
                                                     PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB);
@@ -224,7 +232,7 @@ public:
      * 
      * @param ray The ray to test intersection with.
      * @param distance How far along the given ray to test for intersections.
-     * @param result Optioanl pointer to a HitTest structure to store hit test result information in.
+     * @param result Optional pointer to a HitTest structure to store hit test result information in.
      * @return True if the ray test collided with a physics object, false otherwise.
      */
     bool rayTest(const Ray& ray, float distance, PhysicsController::HitResult* result = NULL);
@@ -237,6 +245,7 @@ public:
      *
      * @param object The collision object to test.
      * @param endPosition The end position of the sweep test, in world space.
+     * @param result Optional pointer to a HitTest structure to store hit test result information in.
      * @return True if the object intersects any other physics objects, false otherwise.
      */
     bool sweepTest(PhysicsCollisionObject* object, const Vector3& endPosition, PhysicsController::HitResult* result = NULL);
@@ -354,13 +363,55 @@ private:
     {
     public:
 
+        /** 
+         * DebugVertex.
+         */
         struct DebugVertex
         {
-            float x, y, z;
-            float r, g, b, a;
+            /**
+             * The x coordinate of the vertex.
+             */
+            float x;
+    
+            /**
+             * The y coordinate of the vertex.
+             */
+            float y;
+    
+            /**
+             * The z coordinate of the vertex.
+             */
+            float z;
+
+            /**
+             * The red color component of the vertex.
+             */
+            float r;
+    
+            /**
+             * The green color component of the vertex.
+             */
+            float g;
+    
+            /**
+             * The blue color component of the vertex.
+             */
+            float b;
+    
+            /**
+             * The alpha component of the vertex.
+             */
+            float a;
         };
 
-        DebugDrawer();        
+        /**
+         * Constructor.
+         */
+        DebugDrawer(); 
+
+        /** 
+         * Destructor.
+         */
         ~DebugDrawer();
         
         void begin(const Matrix& viewProjection);

+ 1 - 1
gameplay/src/PhysicsGhostObject.cpp

@@ -43,7 +43,7 @@ PhysicsGhostObject* PhysicsGhostObject::create(Node* node, Properties* propertie
 {
     // Check if the properties is valid and has a valid namespace.
     assert(properties);
-    if (!properties || !(strcmp(properties->getNamespace(), "ghost") == 0))
+    if (!properties || !(strcmp(properties->getNamespace(), "ghostObject") == 0))
     {
         WARN("Failed to load ghost object from properties object: must be non-null object and have namespace equal to \'ghost\'.");
         return NULL;

+ 3 - 0
gameplay/src/PhysicsGhostObject.h

@@ -62,6 +62,9 @@ protected:
      */
     static PhysicsGhostObject* create(Node* node, Properties* properties);
 
+    /**
+     * Pointer to the Bullet ghost collision object.
+     */
     btPairCachingGhostObject* _ghostObject;
 };
 

+ 2 - 2
gameplay/src/PhysicsRigidBody.cpp

@@ -145,9 +145,9 @@ PhysicsRigidBody* PhysicsRigidBody::create(Node* node, Properties* properties)
 {
     // Check if the properties is valid and has a valid namespace.
     assert(properties);
-    if (!properties || !(strcmp(properties->getNamespace(), "rigidbody") == 0))
+    if (!properties || !(strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
-        WARN("Failed to load rigid body from properties object: must be non-null object and have namespace equal to \'rigidbody\'.");
+        WARN("Failed to load rigid body from properties object: must be non-null object and have namespace equal to \'rigidBody\'.");
         return NULL;
     }
 

+ 1 - 1
gameplay/src/PhysicsRigidBody.h

@@ -294,7 +294,7 @@ private:
      * 
      * @param node The node to create a rigid body for; note that the node must have
      *      a model attached to it prior to creating a rigid body for it.
-     * @param properties The properties object defining the rigid body (must have namespace equal to 'rigidbody').
+     * @param properties The properties object defining the rigid body (must have namespace equal to 'rigidBody').
      * @return The newly created rigid body, or <code>NULL</code> if the rigid body failed to load.
      */
     static PhysicsRigidBody* create(Node* node, Properties* properties);

+ 98 - 57
gameplay/src/PlatformAndroid.cpp

@@ -4,6 +4,7 @@
 #include "Platform.h"
 #include "FileSystem.h"
 #include "Game.h"
+#include "Form.h"
 #include <unistd.h>
 
 #include <android/sensor.h>
@@ -41,6 +42,7 @@ const ASensor* __accelerometerSensor;
 
 static int __orientationAngle = 90; // Landscape by default.
 static bool __multiTouch = false;
+static int __primaryTouchId = -1;
 bool __displayKeyboard = false;
 
 static const char* __glExtensions;
@@ -194,69 +196,63 @@ error:
 }
 
 // Display the android virtual keyboard.
-void displayKeyboard(android_app* state, bool pShow)
+void displayKeyboard(android_app* state, bool show)
 { 
-    
-    // The following functions is supposed to show / hide functins from a native activity.. but currently
-    // do not work. 
+    // The following functions is supposed to show / hide functins from a native activity.. but currently do not work. 
     // ANativeActivity_showSoftInput(state->activity, ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT);
     // ANativeActivity_hideSoftInput(state->activity, ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY);
     
     // Show or hide the keyboard by calling the appropriate Java method through JNI instead.
-    // Attaches the current thread to the JVM.
-    jint lResult;
-    jint lFlags = 0;
-    JavaVM* lJavaVM = state->activity->vm;
-    JNIEnv* lJNIEnv = state->activity->env; 
-    JavaVMAttachArgs lJavaVMAttachArgs;
-    lJavaVMAttachArgs.version = JNI_VERSION_1_6;
-    lJavaVMAttachArgs.name = "NativeThread";
-    lJavaVMAttachArgs.group = NULL;
-    lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs); 
-    if (lResult == JNI_ERR)
+    jint result;
+    jint flags = 0;
+    JavaVM* jvm = state->activity->vm;
+    JNIEnv* env;
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
+    jvm->AttachCurrentThread(&env, NULL);
+    if (result == JNI_ERR)
     { 
         return; 
     } 
     // Retrieves NativeActivity. 
     jobject lNativeActivity = state->activity->clazz;
-    jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);
+    jclass ClassNativeActivity = env->GetObjectClass(lNativeActivity);
 
     // Retrieves Context.INPUT_METHOD_SERVICE.
-    jclass ClassContext = lJNIEnv->FindClass("android/content/Context");
-    jfieldID FieldINPUT_METHOD_SERVICE = lJNIEnv->GetStaticFieldID(ClassContext, "INPUT_METHOD_SERVICE", "Ljava/lang/String;");
-    jobject INPUT_METHOD_SERVICE = lJNIEnv->GetStaticObjectField(ClassContext, FieldINPUT_METHOD_SERVICE);
+    jclass ClassContext = env->FindClass("android/content/Context");
+    jfieldID FieldINPUT_METHOD_SERVICE = env->GetStaticFieldID(ClassContext, "INPUT_METHOD_SERVICE", "Ljava/lang/String;");
+    jobject INPUT_METHOD_SERVICE = env->GetStaticObjectField(ClassContext, FieldINPUT_METHOD_SERVICE);
     
     // Runs getSystemService(Context.INPUT_METHOD_SERVICE).
-    jclass ClassInputMethodManager = lJNIEnv->FindClass("android/view/inputmethod/InputMethodManager");
-    jmethodID MethodGetSystemService = lJNIEnv->GetMethodID(ClassNativeActivity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
-    jobject lInputMethodManager = lJNIEnv->CallObjectMethod(lNativeActivity, MethodGetSystemService, INPUT_METHOD_SERVICE);
+    jclass ClassInputMethodManager = env->FindClass("android/view/inputmethod/InputMethodManager");
+    jmethodID MethodGetSystemService = env->GetMethodID(ClassNativeActivity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+    jobject lInputMethodManager = env->CallObjectMethod(lNativeActivity, MethodGetSystemService, INPUT_METHOD_SERVICE);
     
     // Runs getWindow().getDecorView().
-    jmethodID MethodGetWindow = lJNIEnv->GetMethodID(ClassNativeActivity, "getWindow", "()Landroid/view/Window;");
-    jobject lWindow = lJNIEnv->CallObjectMethod(lNativeActivity, MethodGetWindow);
-    jclass ClassWindow = lJNIEnv->FindClass("android/view/Window");
-    jmethodID MethodGetDecorView = lJNIEnv->GetMethodID(ClassWindow, "getDecorView", "()Landroid/view/View;");
-    jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow, MethodGetDecorView);
-    if (pShow)
+    jmethodID MethodGetWindow = env->GetMethodID(ClassNativeActivity, "getWindow", "()Landroid/view/Window;");
+    jobject lWindow = env->CallObjectMethod(lNativeActivity, MethodGetWindow);
+    jclass ClassWindow = env->FindClass("android/view/Window");
+    jmethodID MethodGetDecorView = env->GetMethodID(ClassWindow, "getDecorView", "()Landroid/view/View;");
+    jobject lDecorView = env->CallObjectMethod(lWindow, MethodGetDecorView);
+    if (show)
     {
         // Runs lInputMethodManager.showSoftInput(...).
-        jmethodID MethodShowSoftInput = lJNIEnv->GetMethodID( ClassInputMethodManager, "showSoftInput", "(Landroid/view/View;I)Z");
-        jboolean lResult = lJNIEnv->CallBooleanMethod(lInputMethodManager, MethodShowSoftInput, lDecorView, lFlags); 
+        jmethodID MethodShowSoftInput = env->GetMethodID( ClassInputMethodManager, "showSoftInput", "(Landroid/view/View;I)Z");
+        jboolean result = env->CallBooleanMethod(lInputMethodManager, MethodShowSoftInput, lDecorView, flags); 
     } 
     else 
     { 
         // Runs lWindow.getViewToken() 
-        jclass ClassView = lJNIEnv->FindClass("android/view/View");
-        jmethodID MethodGetWindowToken = lJNIEnv->GetMethodID(ClassView, "getWindowToken", "()Landroid/os/IBinder;");
-        jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView, MethodGetWindowToken); 
+        jclass ClassView = env->FindClass("android/view/View");
+        jmethodID MethodGetWindowToken = env->GetMethodID(ClassView, "getWindowToken", "()Landroid/os/IBinder;");
+        jobject lBinder = env->CallObjectMethod(lDecorView, MethodGetWindowToken); 
         
         // lInputMethodManager.hideSoftInput(...). 
-        jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID(ClassInputMethodManager, "hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z"); 
-        jboolean lRes = lJNIEnv->CallBooleanMethod( lInputMethodManager, MethodHideSoftInput, lBinder, lFlags); 
+        jmethodID MethodHideSoftInput = env->GetMethodID(ClassInputMethodManager, "hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z"); 
+        jboolean lRes = env->CallBooleanMethod( lInputMethodManager, MethodHideSoftInput, lBinder, flags); 
     }
     
     // Finished with the JVM.
-    lJavaVM->DetachCurrentThread(); 
+    jvm->DetachCurrentThread(); 
 }
 
 // Gets the Keyboard::Key enumeration constant that corresponds to the given Android key code.
@@ -531,25 +527,57 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
 {
     if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
     {
-        int32_t data = AMotionEvent_getAction(event);
-        Touch::TouchEvent touchEvent;
-        size_t pointerCount = AMotionEvent_getPointerCount(event);
-        for (size_t i = 0; i < pointerCount; ++i)
+        int32_t action = AMotionEvent_getAction(event);
+        size_t pointerIndex;
+        size_t pointerId;
+        size_t pointerCount;
+        switch (action & AMOTION_EVENT_ACTION_MASK)
         {
-            switch (data & AMOTION_EVENT_ACTION_MASK)
-            {
-                case AMOTION_EVENT_ACTION_DOWN:
-                    touchEvent = Touch::TOUCH_PRESS;
-                    break;
-                case AMOTION_EVENT_ACTION_UP:
-                    touchEvent = Touch::TOUCH_RELEASE;
-                    break;
-                case AMOTION_EVENT_ACTION_MOVE:
-                    touchEvent = Touch::TOUCH_MOVE;
-                    break;
-            }
-            size_t pointerId = AMotionEvent_getPointerId(event, i);
-            Game::getInstance()->touchEvent(touchEvent, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), pointerId);
+            case AMOTION_EVENT_ACTION_DOWN:
+                // Primary pointer down
+                pointerId = AMotionEvent_getPointerId(event, 0);
+                gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0), pointerId);
+                __primaryTouchId = pointerId;
+                break;
+            case AMOTION_EVENT_ACTION_UP:
+                pointerId = AMotionEvent_getPointerId(event, 0);
+                if (__multiTouch || __primaryTouchId == pointerId)
+                {
+                    gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0), pointerId);
+                }
+                __primaryTouchId = -1;
+                break;
+            case AMOTION_EVENT_ACTION_POINTER_DOWN:
+                // Non-primary pointer down
+                if (__multiTouch)
+                {
+                    pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+                    pointerId = AMotionEvent_getPointerId(event, pointerIndex);
+                    gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, AMotionEvent_getX(event, pointerIndex), AMotionEvent_getY(event, pointerIndex), pointerId);
+                }
+                break;
+            case AMOTION_EVENT_ACTION_POINTER_UP:
+                pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+                pointerId = AMotionEvent_getPointerId(event, pointerIndex);
+                if (__multiTouch || __primaryTouchId == pointerId)
+                {
+                    gameplay::Platform::touchEventInternal(Touch::TOUCH_RELEASE, AMotionEvent_getX(event, pointerIndex), AMotionEvent_getY(event, pointerIndex), pointerId);
+                }
+                if (__primaryTouchId == pointerId)
+                    __primaryTouchId = -1;
+                break;
+            case AMOTION_EVENT_ACTION_MOVE:
+                // ACTION_MOVE events are batched, unlike the other events.
+                pointerCount = AMotionEvent_getPointerCount(event);
+                for (size_t i = 0; i < pointerCount; ++i)
+                {
+                    pointerId = AMotionEvent_getPointerId(event, i);
+                    if (__multiTouch || __primaryTouchId == pointerId)
+                    {
+                        gameplay::Platform::touchEventInternal(Touch::TOUCH_MOVE, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), pointerId);
+                    }
+                }
+                break;
         }
         return 1;
     } 
@@ -661,7 +689,10 @@ int Platform::enterMessagePump()
 {
     // Get the android application's activity.
     ANativeActivity* activity = __state->activity;
-    JNIEnv* env = activity->env;
+    JavaVM* jvm = __state->activity->vm;
+    JNIEnv* env;
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
+    jvm->AttachCurrentThread(&env, NULL);
 
     // Get the package name for this app from Java.
     jclass clazz = env->GetObjectClass(activity->clazz);
@@ -765,6 +796,8 @@ int Platform::enterMessagePump()
         // Display the keyboard.
         gameplay::displayKeyboard(__state, __displayKeyboard);
     }
+
+    jvm->DetachCurrentThread();
 }
 
 void Platform::signalShutdown() 
@@ -834,9 +867,9 @@ void Platform::getAccelerometerValues(float* pitch, float* roll)
     tz = -__sensorEvent.acceleration.z;
     
     if (pitch != NULL)
-        *pitch = atan(ty / sqrt(tx * tx + tz * tz)) * 180.0f * M_1_PI;
+        *pitch = -atan(ty / sqrt(tx * tx + tz * tz)) * 180.0f * M_1_PI;
     if (roll != NULL)
-        *roll = atan(tx / sqrt(ty * ty + tz * tz)) * 180.0f * M_1_PI;
+        *roll = -atan(tx / sqrt(ty * ty + tz * tz)) * 180.0f * M_1_PI;
 }
 
 void Platform::swapBuffers()
@@ -853,6 +886,14 @@ void Platform::displayKeyboard(bool display)
         __displayKeyboard = false;
 }
 
+void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+{
+    if (!Form::touchEventInternal(evt, x, y, contactIndex))
+    {
+        Game::getInstance()->touchEvent(evt, x, y, contactIndex);
+    }
+}
+
 void Platform::sleep(long ms)
 {
     usleep(ms * 1000);

+ 11 - 2
gameplay/src/PlatformMacOSX.mm

@@ -251,8 +251,8 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
     if (__rightMouseDown)
     {
         // Update the pitch and roll by adding the scaled deltas.
-        __roll += -(float)(point.x - __lx) * ACCELEROMETER_FACTOR_X;
-        __pitch -= (float)(point.y - (WINDOW_HEIGHT - __ly)) * ACCELEROMETER_FACTOR_Y;
+        __roll += (float)(point.x - __lx) * ACCELEROMETER_FACTOR_X;
+        __pitch -= -(float)(point.y - (WINDOW_HEIGHT - __ly)) * ACCELEROMETER_FACTOR_Y;
     
         // Clamp the values to the valid range.
         __roll = max(min(__roll, 90.0f), -90.0f);
@@ -667,6 +667,15 @@ int Platform::getOrientationAngle()
     return 0;
 }
 
+void Platform::setMultiTouch(bool enabled)
+{
+}
+    
+bool Platform::isMultiTouch()
+{
+    return false;
+}
+    
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 {
     *pitch = __pitch;

+ 54 - 20
gameplay/src/PlatformQNX.cpp

@@ -13,7 +13,7 @@
 #include <bps/event.h>
 #include <bps/screen.h>
 #include <bps/navigator.h>
-#include <bps/accelerometer.h>
+#include <bps/sensor.h>
 #include <bps/orientation.h>
 #include <bps/virtualkeyboard.h>
 
@@ -35,7 +35,8 @@ static EGLSurface __eglSurface = EGL_NO_SURFACE;
 static EGLConfig __eglConfig = 0;
 static int __orientationAngle;
 static bool __multiTouch = false;
-
+static float __pitch;
+static float __roll;
 static const char* __glExtensions;
 PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray = NULL;
 PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays = NULL;
@@ -493,7 +494,12 @@ Platform* Platform::create(Game* game)
     Platform* platform = new Platform(game);
 
     bps_initialize();
-    accelerometer_set_update_frequency(FREQ_40_HZ);
+
+    static const int SENSOR_RATE = 25000;
+    sensor_set_rate(SENSOR_TYPE_AZIMUTH_PITCH_ROLL, SENSOR_RATE);
+    sensor_set_skip_duplicates(SENSOR_TYPE_AZIMUTH_PITCH_ROLL, true);
+    sensor_request_events(SENSOR_TYPE_AZIMUTH_PITCH_ROLL);
+
     navigator_request_events(0);
     navigator_rotation_lock(true);
 
@@ -721,9 +727,8 @@ Platform* Platform::create(Game* game)
 
     if (strstr(__glExtensions, "GL_OES_vertex_array_object") || strstr(__glExtensions, "GL_ARB_vertex_array_object"))
     {
-        // Disable VAO extension for now.
         glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
-        glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArrays");
+        glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
         glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
         glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");
     }
@@ -950,6 +955,16 @@ int Platform::enterMessagePump()
                     break;
                 }
             }
+            else if (domain == sensor_get_domain())
+            {
+            	if (bps_event_get_code(event) == SENSOR_AZIMUTH_PITCH_ROLL_READING)
+            	{
+					float azimuth;
+					sensor_event_get_apr(event, &azimuth, &__pitch, &__roll);
+
+
+				   }
+            }
         }
 
         // If we are done, then exit.
@@ -1044,21 +1059,40 @@ bool Platform::isMultiTouch()
 
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 {
-    double tx, ty, tz;
-    accelerometer_read_forces(&tx, &ty, &tz);
-
-    // Hack landscape adjustment only.
-    if (__orientationAngle == 0)
-    {
-        tx = -tx;
-        ty = -ty;
-        tz = -tz;
-    }
-
-    if (pitch != NULL)
-        *pitch = atan(ty / sqrt(tx * tx + tz * tz)) * 180.0f * M_1_PI;
-    if (roll != NULL)
-        *roll = atan(tx / sqrt(ty * ty + tz * tz)) * 180.0f * M_1_PI;
+	switch(__orientationAngle)
+	{
+	// Landscape based device adjusting for landscape game mode
+	case 0:
+		if (pitch)
+			*pitch = __pitch;
+		if (roll)
+			*roll = -__roll;
+		break;
+	case 180:
+		if (pitch)
+			*pitch = -__pitch;
+		if (roll)
+			*roll = __roll;
+		break;
+
+	// Portrait based device adjusting for landscape game mode
+	case 90:
+		if (pitch)
+			*pitch = -__roll;
+		if (roll)
+			*roll = -__pitch;
+		break;
+
+	case  270:
+		if (pitch)
+			*pitch = __roll;
+		if (roll)
+			*roll = __pitch;
+		break;
+
+	default:
+		break;
+	}
 }
 
 void Platform::swapBuffers()

+ 64 - 61
gameplay/src/PlatformWin32.cpp

@@ -6,6 +6,7 @@
 #include "Game.h"
 #include "Form.h"
 #include <GL/wglew.h>
+#include <windowsx.h>
 
 // Default to 720p
 #define WINDOW_WIDTH    1280
@@ -22,7 +23,6 @@ static HWND __hwnd = 0;
 static HDC __hdc = 0;
 static HGLRC __hrc = 0;
 
-
 static gameplay::Keyboard::Key getKey(WPARAM win32KeyCode, bool shiftDown)
 {
     switch (win32KeyCode)
@@ -245,6 +245,14 @@ static gameplay::Keyboard::Key getKey(WPARAM win32KeyCode, bool shiftDown)
     }
 }
 
+void UpdateCapture(LPARAM lParam)
+{
+	if ((lParam & MK_LBUTTON) || (lParam & MK_MBUTTON) || (lParam & MK_RBUTTON))
+		SetCapture(__hwnd);
+	else
+		ReleaseCapture();
+}
+
 LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
     if (hwnd != __hwnd)
@@ -257,9 +265,6 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
     static const float ACCELEROMETER_X_FACTOR = 90.0f / WINDOW_WIDTH;
     static const float ACCELEROMETER_Y_FACTOR = 90.0f / WINDOW_HEIGHT;
 
-    static bool hasMouse = false;
-    static bool lMouseDown = false;
-    static bool rMouseDown = false;
     static int lx, ly;
 
     static bool shiftDown = false;
@@ -281,87 +286,85 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         return 0;
 
     case WM_LBUTTONDOWN:
-        if (!gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_PRESS_LEFT_BUTTON, LOWORD(lParam), HIWORD(lParam), 0))
+    {
+        int x = GET_X_LPARAM(lParam);
+        int y = GET_Y_LPARAM(lParam);
+
+		UpdateCapture(wParam);
+        if (!gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_PRESS_LEFT_BUTTON, x, y, 0))
         {
-            gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_PRESS, LOWORD(lParam), HIWORD(lParam), 0);
+            gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_PRESS, x, y, 0);
         }
-        lMouseDown = true;
         return 0;
-
+    }
     case WM_LBUTTONUP:
-        lMouseDown = false;
-        if (!gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_RELEASE_LEFT_BUTTON, LOWORD(lParam), HIWORD(lParam), 0))
+    {
+        int x = GET_X_LPARAM(lParam);
+        int y = GET_Y_LPARAM(lParam);
+
+        if (!gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_RELEASE_LEFT_BUTTON, x, y, 0))
         {
-            gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_RELEASE, LOWORD(lParam), HIWORD(lParam), 0);
+            gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_RELEASE, x, y, 0);
         }
+		UpdateCapture(wParam);
         return 0;
-
+    }
     case WM_RBUTTONDOWN:
-        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_PRESS_RIGHT_BUTTON, LOWORD(lParam), HIWORD(lParam), 0);
-        rMouseDown = true;
-        lx = LOWORD(lParam);
-        ly = HIWORD(lParam);
+		UpdateCapture(wParam);
+		lx = GET_X_LPARAM(lParam);
+        ly = GET_Y_LPARAM(lParam);
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_PRESS_RIGHT_BUTTON, lx, ly, 0);
         break;
 
     case WM_RBUTTONUP:
-        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_RELEASE_RIGHT_BUTTON, LOWORD(lParam), HIWORD(lParam), 0);
-        rMouseDown = false;
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_RELEASE_RIGHT_BUTTON,  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0);
+		UpdateCapture(wParam);
         break;
 
     case WM_MBUTTONDOWN:
-        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_PRESS_MIDDLE_BUTTON, LOWORD(lParam), HIWORD(lParam), 0);
+		UpdateCapture(wParam);
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_PRESS_MIDDLE_BUTTON,  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0);
         break;
 
     case WM_MBUTTONUP:
-        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_RELEASE_MIDDLE_BUTTON, LOWORD(lParam), HIWORD(lParam), 0);
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_RELEASE_MIDDLE_BUTTON,  GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0);
+		UpdateCapture(wParam);
         break;
 
     case WM_MOUSEMOVE:
-    {
-        if (!hasMouse)
-        {
-            hasMouse = true;
-
-            // Call TrackMouseEvent to detect the next WM_MOUSE_LEAVE.
-            TRACKMOUSEEVENT tme;
-            tme.cbSize = sizeof(TRACKMOUSEEVENT);
-            tme.dwFlags = TME_LEAVE;
-            tme.hwndTrack = __hwnd;
-            TrackMouseEvent(&tme);
-        }
-
-        bool consumed = gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_MOVE, LOWORD(lParam), HIWORD(lParam), 0);
-        if (lMouseDown && !consumed)
-        {
-            // Mouse move events should be interpreted as touch move only if left mouse is held and the game did not consume the mouse event.
-            gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_MOVE, LOWORD(lParam), HIWORD(lParam), 0);
-            return 0;
-        }
-        else if (rMouseDown)
-        {
-            // Update the pitch and roll by adding the scaled deltas.
-            __roll += -(float)(LOWORD(lParam) - lx) * ACCELEROMETER_X_FACTOR;
-            __pitch += (float)(HIWORD(lParam) - ly) * ACCELEROMETER_Y_FACTOR;
-
-            // Clamp the values to the valid range.
-            __roll = max(min(__roll, 90.0f), -90.0f);
-            __pitch = max(min(__pitch, 90.0f), -90.0f);
-
-            // Update the last X/Y values.
-            lx = LOWORD(lParam);
-            ly = HIWORD(lParam);
-        }
+    {
+        int x = GET_X_LPARAM(lParam);
+        int y = GET_Y_LPARAM(lParam);
+
+		// Allow Game::mouseEvent a chance to handle (and possibly consume) the event.
+		if (!gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_MOVE, x, y, 0))
+		{
+			if ((wParam & MK_LBUTTON) == MK_LBUTTON)
+			{
+				// Mouse move events should be interpreted as touch move only if left mouse is held and the game did not consume the mouse event.
+				gameplay::Platform::touchEventInternal(gameplay::Touch::TOUCH_MOVE, x, y, 0);
+				return 0;
+			}
+			else if ((wParam & MK_RBUTTON) == MK_RBUTTON)
+			{
+				// Update the pitch and roll by adding the scaled deltas.
+				__roll += (float)(x - lx) * ACCELEROMETER_X_FACTOR;
+				__pitch += -(float)(y - ly) * ACCELEROMETER_Y_FACTOR;
+
+				// Clamp the values to the valid range.
+				__roll = max(min(__roll, 90.0f), -90.0f);
+				__pitch = max(min(__pitch, 90.0f), -90.0f);
+
+				// Update the last X/Y values.
+				lx = x;
+				ly = y;
+			}
+		}
         break;
     }
 
-    case WM_MOUSELEAVE:
-        hasMouse = false;
-        lMouseDown = false;
-        rMouseDown = false;
-        break;
-
     case WM_MOUSEWHEEL:
-        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_WHEEL, LOWORD(lParam), HIWORD(lParam), GET_WHEEL_DELTA_WPARAM(wParam) / 120);
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_WHEEL, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), GET_WHEEL_DELTA_WPARAM(wParam) / 120);
         break;
 
     case WM_KEYDOWN:

+ 26 - 5
gameplay/src/PlatformiOS.mm

@@ -460,17 +460,38 @@ int getKey(unichar keyCode);
     return YES;
 }
 
-- (void)getAccelerometerPitch:(float *)pitch roll:(float *)roll 
+- (void)getAccelerometerPitch:(float*)pitch roll:(float*)roll 
 {
     float p = 0.0f;
     float r = 0.0f;
-    CMAccelerometerData *accelerometerData = motionManager.accelerometerData;
+    CMAccelerometerData* accelerometerData = motionManager.accelerometerData;
     if(accelerometerData != nil) 
     {
         float tx, ty, tz;
-        tx = accelerometerData.acceleration.y;
-        ty = -accelerometerData.acceleration.x;
-        tz = -accelerometerData.acceleration.z;      
+        
+        switch ([[UIApplication sharedApplication] statusBarOrientation])
+        {
+        case UIInterfaceOrientationLandscapeRight:
+            tx = -accelerometerData.acceleration.y;
+            ty = accelerometerData.acceleration.x;
+            break;
+
+        case UIInterfaceOrientationLandscapeLeft:
+            tx = accelerometerData.acceleration.y;
+            ty = -accelerometerData.acceleration.x;
+            break;
+
+        case UIInterfaceOrientationPortraitUpsideDown:
+            tx = -accelerometerData.acceleration.y;
+            ty = -accelerometerData.acceleration.x;
+            break;
+
+        case UIInterfaceOrientationPortrait:
+            break;
+        }
+        
+        tz = accelerometerData.acceleration.z;  
+        
         p = atan(ty / sqrt(tx * tx + tz * tz)) * 180.0f * M_1_PI;
         r = atan(tx / sqrt(ty * ty + tz * tz)) * 180.0f * M_1_PI;     
     }

+ 15 - 0
gameplay/src/RadioButton.h

@@ -131,9 +131,24 @@ protected:
      */
     static void clearSelected(const std::string& groupId);
 
+    /**
+     * The RadioButton's group ID.
+     */
     std::string _groupId;
+    
+    /**
+     * Whether the RadioButton is currently selected.
+     */
     bool _selected;
+    
+    /**
+     * The size at which the RadioButton's icon will be drawn.
+     */
     Vector2 _imageSize;
+
+    /**
+     * The ThemeImage to use for the RadioButton.
+     */ 
     Theme::ThemeImage* _image;
 
 private:

+ 19 - 0
gameplay/src/RenderState.h

@@ -357,10 +357,29 @@ private:
 
 protected:
 
+    /**
+     * Collection of MaterialParameter's to be applied to the gamplay::Effect.
+     */
     mutable std::vector<MaterialParameter*> _parameters;
+    
+    /**
+     * Map of IDs to AutoBindings.
+     */
     std::map<std::string, AutoBinding> _autoBindings;
+
+    /**
+     * The Node bound to the RenderState.
+     */
     Node* _nodeBinding;
+
+    /**
+     * The StateBlock of fixed-function render states that can be applied to the RenderState.
+     */
     mutable StateBlock* _state;
+
+    /**
+     * The RenderState's parent.
+     */
     RenderState* _parent;
 };
 

+ 37 - 2
gameplay/src/Scene.cpp

@@ -316,10 +316,45 @@ Material* createDebugMaterial()
     return material;
 }
 
+/**
+ * DebugVertex structure.
+ */
 struct DebugVertex
 {
-    float x, y, z;
-    float r, g, b, a;
+    /**
+     * The x coordinate of the vertex.
+     */
+    float x;
+
+    /**
+     * The y coordinate of the vertex.
+     */
+    float y;
+    
+    /**
+     * The z coordinate of the vertex.
+     */
+    float z;
+    
+    /** 
+     * The red color component of the vertex.
+     */
+    float r;
+
+    /** 
+     * The green color component of the vertex.
+     */
+    float g;
+    
+    /** 
+     * The blue color component of the vertex.
+     */
+    float b;
+    
+    /** 
+     * The alpha component of the vertex.
+     */
+    float a;
 };
 
 void drawDebugLine(MeshBatch* batch, const Vector3& point1, const Vector3& point2, const Vector3& color)

+ 57 - 8
gameplay/src/Scene.h

@@ -158,6 +158,21 @@ public:
      */
     void setAmbientColor(float red, float green, float blue);
 
+    /**
+     * Visits each node in the scene and calls the specified method pointer.
+     *
+     * Calling this method invokes the specified method pointer for each node
+     * in the scene hierarchy.
+     *
+     * The visitMethod parameter must be a pointer to a method that has a bool
+     * return type and accepts a single parameter of type Node*.
+     *
+     * @param instance The pointer to an instance of the object that contains visitMethod.
+     * @param visitMethod The pointer to the class method to call for each node in the scene.
+     */
+    template <class T>
+    void visit(T* instance, bool (T::*visitMethod)(Node*));
+
     /**
      * Visits each node in the scene and calls the specified method pointer.
      *
@@ -165,16 +180,16 @@ public:
      * in the scene hierarchy, passing the Node and the specified cookie value.
      * 
      * The visitMethod parameter must be a pointer to a method that has a bool
-     * return type and accepts two parameters: a Node pointer and a void* (cookie).
-     * The scene travesal continues while visitMethod return true. Returning false
-     * will cause the traversal to stop.
+     * return type and accepts two parameters: a Node pointer and a cookie of a
+     * user-specified type. The scene travesal continues while visitMethod return
+     * true. Returning false will cause the traversal to stop.
      *
      * @param instance The pointer to an instance of the object that contains visitMethod.
      * @param visitMethod The pointer to the class method to call for each node in the scene.
      * @param cookie An optional user-defined parameter that will be passed to each invocation of visitMethod.
      */
-    template <class T>
-    void visit(T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie = 0);
+    template <class T, class C>
+    void visit(T* instance, bool (T::*visitMethod)(Node*,C), C cookie);
 
     /**
      * Draws debugging information (bounding volumes, etc.) for the scene.
@@ -205,7 +220,13 @@ private:
      * Visits the given node and all of its children recursively.
      */
     template <class T>
-    bool visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie);
+    bool visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*));
+
+    /**
+     * Visits the given node and all of its children recursively.
+     */
+    template <class T, class C>
+    bool visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*,C), C cookie);
 
     std::string _id;
     Camera* _activeCamera;
@@ -218,7 +239,18 @@ private:
 };
 
 template <class T>
-void Scene::visit(T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie)
+void Scene::visit(T* instance, bool (T::*visitMethod)(Node*))
+{
+    for (Node* node = getFirstNode(); node != NULL; node = node->getNextSibling())
+    {
+        if (!visitNode(node, instance, visitMethod))
+            return;
+    }
+}
+
+
+template <class T, class C>
+void Scene::visit(T* instance, bool (T::*visitMethod)(Node*,C), C cookie)
 {
     for (Node* node = getFirstNode(); node != NULL; node = node->getNextSibling())
     {
@@ -228,7 +260,24 @@ void Scene::visit(T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie
 }
 
 template <class T>
-bool Scene::visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie)
+bool Scene::visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*))
+{
+    // Invoke the visit method for this node.
+    if (!(instance->*visitMethod)(node))
+        return false;
+
+    // Recurse for all children.
+    for (Node* child = node->getFirstChild(); child != NULL; child = child->getNextSibling())
+    {
+        if (!visitNode(child, instance, visitMethod))
+            return false;
+    }
+
+    return true;
+}
+
+template <class T, class C>
+bool Scene::visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*,C), C cookie)
 {
     // Invoke the visit method for this node.
     if (!(instance->*visitMethod)(node, cookie))

+ 25 - 15
gameplay/src/SceneLoader.cpp

@@ -61,8 +61,9 @@ Scene* SceneLoader::load(const char* filePath)
         SceneNodeProperty::ROTATE |
         SceneNodeProperty::SCALE |
         SceneNodeProperty::TRANSLATE | 
-        SceneNodeProperty::TRANSPARENT);
-    applyNodeProperties(scene, sceneProperties, SceneNodeProperty::CHARACTER | SceneNodeProperty::GHOST | SceneNodeProperty::RIGIDBODY);
+        SceneNodeProperty::TRANSPARENT |
+        SceneNodeProperty::DYNAMIC);
+    applyNodeProperties(scene, sceneProperties, SceneNodeProperty::CHARACTER | SceneNodeProperty::GHOSTOBJECT | SceneNodeProperty::RIGIDBODY);
     createAnimations(scene);
 
     // Find the physics properties object.
@@ -195,7 +196,7 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
         snp._type == SceneNodeProperty::MATERIAL ||
         snp._type == SceneNodeProperty::PARTICLE ||
         snp._type == SceneNodeProperty::CHARACTER ||
-        snp._type == SceneNodeProperty::GHOST ||
+        snp._type == SceneNodeProperty::GHOSTOBJECT ||
         snp._type == SceneNodeProperty::RIGIDBODY)
     {
         // Check to make sure the referenced properties object was loaded properly.
@@ -250,7 +251,7 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             break;
         }
         case SceneNodeProperty::CHARACTER:
-        case SceneNodeProperty::GHOST:
+        case SceneNodeProperty::GHOSTOBJECT:
         case SceneNodeProperty::RIGIDBODY:
         {
             // Check to make sure the referenced properties object was loaded properly.
@@ -283,20 +284,20 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             {
                 WARN_VARG("Attempting to set a 'character' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
-            else if (snp._type == SceneNodeProperty::GHOST && strcmp(p->getNamespace(), "ghost") != 0)
+            else if (snp._type == SceneNodeProperty::GHOSTOBJECT && strcmp(p->getNamespace(), "ghostObject") != 0)
             {
-                WARN_VARG("Attempting to set a 'ghost' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
+                WARN_VARG("Attempting to set a 'ghostObject' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
-            else if (snp._type == SceneNodeProperty::RIGIDBODY && strcmp(p->getNamespace(), "rigidbody") != 0)
+            else if (snp._type == SceneNodeProperty::RIGIDBODY && strcmp(p->getNamespace(), "rigidBody") != 0)
             {
-                WARN_VARG("Attempting to set a 'rigidbody' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
+                WARN_VARG("Attempting to set a 'rigidBody' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
             else
             {
                 // If the scene file specifies a rigid body model, use it for creating the collision object.
                 Properties* np = sceneProperties->getNamespace(sceneNode._nodeID);
                 const char* name = NULL;
-                if (np && (name = np->getString("rigidbodymodel")))
+                if (np && (name = np->getString("rigidBodyModel")))
                 {
                     Node* modelNode = node->getScene()->findNode(name);
                     if (!modelNode)
@@ -307,14 +308,14 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
                             WARN_VARG("Node '%s' does not have a model; attempting to use its model for collision object creation.", name);
                         else
                         {
-                            // Temporarily set rigidbody model on model so it's used during collision object creation.
+                            // Temporarily set rigidBody model on model so it's used during collision object creation.
                             Model* model = node->getModel();
                             assert(model);
                         
                             // Up ref count to prevent node from releasing the model when we swap it.
                             model->addRef(); 
                         
-                            // Create collision object with new rigidbodymodel set.
+                            // Create collision object with new rigidBodyModel set.
                             node->setModel(modelNode->getModel());
                             node->setCollisionObject(p);
 
@@ -370,6 +371,11 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             node->setTransparent(true);
             break;
         }
+        case SceneNodeProperty::DYNAMIC:
+        {
+            node->setDynamic(true);
+            break;
+        }
         default:
             WARN_VARG("Unsupported node property type: %d.", snp._type);
             break;
@@ -554,15 +560,15 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::CHARACTER, ns->getString());
                 }
-                else if (strcmp(name, "ghost") == 0)
+                else if (strcmp(name, "ghostObject") == 0)
                 {
-                    addSceneNodeProperty(sceneNode, SceneNodeProperty::GHOST, ns->getString());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::GHOSTOBJECT, ns->getString());
                 }
-                else if (strcmp(name, "rigidbody") == 0)
+                else if (strcmp(name, "rigidBody") == 0)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::RIGIDBODY, ns->getString());
                 }
-                else if (strcmp(name, "rigidbodymodel") == 0)
+                else if (strcmp(name, "rigidBodyModel") == 0)
                 {
                     // Ignore this for now. We process this when we do rigid body creation.
                 }
@@ -582,6 +588,10 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::TRANSPARENT);
                 }
+                else if (strcmp(name, "dynamic") == 0)
+                {
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::DYNAMIC);
+                }
                 else
                 {
                     WARN_VARG("Unsupported node property: %s = %s", name, ns->getString());

+ 3 - 2
gameplay/src/SceneLoader.h

@@ -46,13 +46,14 @@ private:
             MATERIAL = 2,
             PARTICLE = 4,
             CHARACTER = 8,
-            GHOST = 16,
+            GHOSTOBJECT = 16,
             RIGIDBODY = 32,
             TRANSLATE = 64,
             ROTATE = 128,
             SCALE = 256,
             URL = 512,
-            TRANSPARENT = 1024
+            TRANSPARENT = 1024,
+            DYNAMIC = 2048
         };
 
         SceneNodeProperty(Type type, std::string file, std::string id, int index) : _type(type), _file(file), _id(id), _index(index) { }

+ 37 - 0
gameplay/src/Slider.h

@@ -149,16 +149,53 @@ protected:
      */
     void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
 
+    /**
+     * Called when a slider's properties change. Updates this slider's internal rendering
+     * properties, such as its text viewport.
+     *
+     * @param clip The clipping rectangle of this slider's parent container.
+     * @param offset The scroll offset of this slider's parent container.
+     */
     void update(const Rectangle& clip, const Vector2& offset);
 
+    /**
+     * The minimum value for the Slider.
+     */
     float _min;
+    
+    /**
+     * The maximum value for the Slider
+     */
     float _max;
+    
+    /**
+     * The Slider's step size.
+     */
     float _step;
+    
+    /**
+     * The Slider's current value.
+     */
     float _value;
 
+    /**
+     * The image for the minimum slider value.
+     */
     Theme::ThemeImage* _minImage;
+    
+    /**
+     * The image for the maximum slider value.
+     */
     Theme::ThemeImage* _maxImage;
+    
+    /**
+     * The image for the slider track.
+     */
     Theme::ThemeImage* _trackImage;
+    
+    /**
+     * The image for the slider marker.
+     */
     Theme::ThemeImage* _markerImage;
 
 private:

+ 47 - 4
gameplay/src/SpriteBatch.cpp

@@ -45,12 +45,55 @@
 namespace gameplay
 {
 
-// Sprite vertex structured used for batching
+/**
+ * Sprite vertex structure used for batching.
+ */
 struct SpriteVertex
 {
-    float x, y, z;
-    float u, v;
-    float r, g, b, a;
+    /**
+     * The x coordinate of the vertex.
+     */
+    float x;
+    
+    /**
+     * The y coordinate of the vertex.
+     */
+    float y;
+    
+    /**
+     * The z coordinate of the vertex.
+     */
+    float z;
+
+    /**
+     * The u component of the (u, v) texture coordinates for the vertex.
+     */
+    float u;
+    
+    /**
+     * The v component of the (u, v) texture coordinates for the vertex.
+     */
+    float v;
+
+    /**
+     * The red color component of the vertex.
+     */
+    float r;
+    
+    /**
+     * The green color component of the vertex.
+     */
+    float g;
+    
+    /**
+     * The blue color component of the vertex.
+     */
+    float b;
+    
+    /**
+     * The alpha component of the vertex.
+     */
+    float a;
 };
 
 // Shared sprite effects

+ 19 - 0
gameplay/src/TextBox.h

@@ -122,11 +122,30 @@ protected:
      */
     void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
 
+    /**
+     * The current position of the TextBox's caret.
+     */
     Vector2 _caretLocation;
     Vector2 _prevCaretLocation;
+
+    /**
+     * The index into the TextBox's string that the caret is.
+     */
     unsigned int textIndex;
+    
+    /**
+     * The last character that was entered into the TextBox.
+     */
     int _lastKeypress;
+
+    /**
+     * The font size to be used in the TextBox.
+     */
     unsigned int _fontSize;
+    
+    /**
+     * The Theme::Image for the TextBox's caret.
+     */
     Theme::ThemeImage* _caretImage;
 
 private:

+ 31 - 31
gameplay/src/Texture.cpp

@@ -75,11 +75,11 @@ Texture* Texture::create(const char* path, bool generateMipmaps)
             }
             else if (tolower(ext[1]) == 'p' && tolower(ext[2]) == 'v' && tolower(ext[3]) == 'r')
             {
-#ifdef OPENGL_ES_PVR
-                // PowerVR Compressed RGBA
-                texture = createCompressedPVR(path);
+#ifdef USE_PVRTC
+                // PowerVR Compressed Texture RGBA
+                texture = createCompressedPVRTC(path);
 #else
-                texture = NULL; // Cannot handle PVR if not supported on platform
+                texture = NULL; // Cannot handle PVRTC if not supported on platform
 #endif
             }
             break;
@@ -147,32 +147,32 @@ Texture* Texture::create(Format format, unsigned int width, unsigned int height,
     return texture;
 }
 
-#ifdef OPENGL_ES_PVR
-Texture* Texture::createCompressedPVR(const char* path)
+#ifdef USE_PVRTC
+Texture* Texture::createCompressedPVRTC(const char* path)
 {
-    char PVRTexIdentifier[] = "PVR!";
+    char PVRTCIdentifier[] = "PVR!";
 
     enum
     {
-        PVRTextureFlagTypePVRTC_2 = 24,
-        PVRTextureFlagTypePVRTC_4
+        PVRTC_2 = 24,
+        PVRTC_4
     };
 
-    struct pvr_file_header
+    struct pvrtc_file_header
     {
         unsigned int size;                  // size of the structure
-        unsigned int height;                  // height of surface to be created
-        unsigned int width;                   // width of input surface
-        unsigned int mipmapCount;             // number of mip-map levels requested
+        unsigned int height;                // height of surface to be created
+        unsigned int width;                 // width of input surface
+        unsigned int mipmapCount;           // number of mip-map levels requested
         unsigned int formatflags;           // pixel format flags
-        unsigned int dataSize;                 // total size in bytes
-        unsigned int bpp;                    // number of bits per pixel
+        unsigned int dataSize;              // total size in bytes
+        unsigned int bpp;                   // number of bits per pixel
         unsigned int redBitMask;            // mask for red bit
         unsigned int greenBitMask;          // mask for green bits
         unsigned int blueBitMask;           // mask for blue bits
-        unsigned int alphaBitMask;            // mask for alpha channel
-        unsigned int pvrTag;                // magic number identifying pvr file
-        unsigned int surfaceCount;          // number of surfaces present in the pvr
+        unsigned int alphaBitMask;          // mask for alpha channel
+        unsigned int pvrtcTag;              // magic number identifying pvrtc file
+        unsigned int surfaceCount;          // number of surfaces present in the pvrtc
     } ;
 
     FILE* file = FileSystem::openFile(path, "rb");
@@ -183,24 +183,24 @@ Texture* Texture::createCompressedPVR(const char* path)
     }
 
     // Read the file header
-    unsigned int size = sizeof(pvr_file_header);
-    pvr_file_header header;
+    unsigned int size = sizeof(pvrtc_file_header);
+    pvrtc_file_header header;
     unsigned int read = (int)fread(&header, 1, size, file);
     assert(read == size);
     if (read != size)
     {
-        LOG_ERROR_VARG("Read file header error for pvr file: %s (%d < %d)", path, (int)read, (int)size);
+        LOG_ERROR_VARG("Read file header error for pvrtc file: %s (%d < %d)", path, (int)read, (int)size);
         fclose(file);
         return NULL;
     }
 
     // Proper file header identifier
-    if (PVRTexIdentifier[0] != (char)((header.pvrTag >>  0) & 0xff) ||
-        PVRTexIdentifier[1] != (char)((header.pvrTag >>  8) & 0xff) ||
-        PVRTexIdentifier[2] != (char)((header.pvrTag >> 16) & 0xff) ||
-        PVRTexIdentifier[3] != (char)((header.pvrTag >> 24) & 0xff))
+    if (PVRTCIdentifier[0] != (char)((header.pvrtcTag >>  0) & 0xff) ||
+        PVRTCIdentifier[1] != (char)((header.pvrtcTag >>  8) & 0xff) ||
+        PVRTCIdentifier[2] != (char)((header.pvrtcTag >> 16) & 0xff) ||
+        PVRTCIdentifier[3] != (char)((header.pvrtcTag >> 24) & 0xff))
      {
-        LOG_ERROR_VARG("Invalid PVR texture file: %s", path);
+        LOG_ERROR_VARG("Invalid PVRTC compressed texture file: %s", path);
         fclose(file);
         return NULL;
     }
@@ -208,17 +208,17 @@ Texture* Texture::createCompressedPVR(const char* path)
     // Format flags for GLenum format
     GLenum format;
     unsigned int formatFlags = header.formatflags & 0xff;
-    if (formatFlags == PVRTextureFlagTypePVRTC_4)
+    if (formatFlags == PVRTC_4)
     {
         format = header.alphaBitMask ? COMPRESSED_RGBA_PVRTC_4BPP : COMPRESSED_RGB_PVRTC_4BPP;
     }
-    else if (formatFlags == PVRTextureFlagTypePVRTC_2)
+    else if (formatFlags == PVRTC_2)
     {
         format = header.alphaBitMask ? COMPRESSED_RGBA_PVRTC_2BPP : COMPRESSED_RGB_PVRTC_2BPP;
     }
     else
     {
-        LOG_ERROR_VARG("Invalid PVR texture format flags for file: %s", path);
+        LOG_ERROR_VARG("Invalid PVRTC compressed texture format flags for file: %s", path);
         fclose(file);
         return NULL;
     }
@@ -228,7 +228,7 @@ Texture* Texture::createCompressedPVR(const char* path)
     assert(read == header.dataSize);
     if (read != header.dataSize)
     {
-        LOG_ERROR_VARG("Read file data error for pvr file: %s (%d < %d)", path, (int)read, (int)header.dataSize);
+        LOG_ERROR_VARG("Read file data error for pvrtc file: %s (%d < %d)", path, (int)read, (int)header.dataSize);
         SAFE_DELETE_ARRAY(data);
         fclose(file);
         return NULL;
@@ -259,7 +259,7 @@ Texture* Texture::createCompressedPVR(const char* path)
 
     for (unsigned int level = 0; level <= header.mipmapCount; level++)
     {
-        if (formatFlags == PVRTextureFlagTypePVRTC_4)
+        if (formatFlags == PVRTC_4)
         {
             dataSize = ( max((int)width, 8) * max((int)height, 8) * 4 + 7) / 8;
         }

+ 3 - 3
gameplay/src/Texture.h

@@ -30,7 +30,7 @@ public:
         RGBA    = GL_RGBA,
         ALPHA   = GL_ALPHA,
         DEPTH   = GL_DEPTH_COMPONENT,
-#ifdef OPENGL_ES_PVR
+#ifdef USE_PVRTC
         COMPRESSED_RGB_PVRTC_4BPP = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
         COMPRESSED_RGBA_PVRTC_4BPP = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
         COMPRESSED_RGB_PVRTC_2BPP = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,
@@ -213,8 +213,8 @@ private:
      */
     virtual ~Texture();
 
-#ifdef OPENGL_ES_PVR
-    static Texture* createCompressedPVR(const char* path);
+#ifdef USE_PVRTC
+    static Texture* createCompressedPVRTC(const char* path);
 #endif
     
     std::string _path;

+ 79 - 2
gameplay/src/Theme.h

@@ -155,15 +155,44 @@ public:
      */
     struct UVs
     {
+        /**
+         * Constructor.
+         */
         UVs();
 
+        /**
+         * Constructor
+         *
+         * @param u1 u component of the first UV coordinate.
+         * @param v1 v component of the first UV coordinate.
+         * @param u2 u component of the second UV coordinate.
+         * @param v2 v component of the second UV coordinate.
+         */
         UVs(float u1, float v1, float u2, float v2);
 
+        /**
+         * Get's an empty UVs.
+         */
         static const UVs& empty();
 
+        /**
+         * u component of the first UV coordinate.
+         */
         float u1;
+        
+        /**
+         * v component of the first UV coordinate.
+         */
         float v1;
+        
+        /**
+         * u component of the second UV coordinate.
+         */
         float u2;
+        
+        /**
+         * v component of the second UV coordinate.
+         */
         float v2;
     };
 
@@ -171,17 +200,53 @@ public:
      * Struct representing margin, border, and padding areas by
      * the width or height of each side.
      */
-    typedef struct SideRegions
+    struct SideRegions
     {
+        /** 
+         * Constructor.
+         */
         SideRegions() : top(0), bottom(0), left(0), right(0) {}
 
+        /**
+         * Gets an empty SideRegion.
+         */
         static const SideRegions& empty();
 
+        /**
+         * The top of the SideRegion.
+         */
         float top;
+        
+        /**
+         * The bottom of the SideRegion.
+         */
         float bottom;
+        
+        /**
+         * The left side of the SideRegion.
+         */
         float left;
+        
+        /**
+         * The right side of the SideRegion.
+         */
         float right;
-    } Margin, Border, Padding;
+    };
+    
+    /** 
+     * Struct representing margin areas by the width or height of each side.
+     */
+    typedef SideRegions Margin;
+    
+    /** 
+     * Struct representing border areas by the width or height of each side.
+     */
+    typedef SideRegions Border;
+    
+    /** 
+     * Struct representing padding areas by the width or height of each side.
+     */
+    typedef SideRegions Padding;
 
     /**
      * Class representing an image within the theme's texture atlas.
@@ -195,12 +260,24 @@ public:
 
     public:
 
+        /**
+         * Gets the ID of the ThemeImage.
+         */
         const char* getId() const;
 
+        /**
+         * Gets the UV coordinates for the ThemeImage.
+         */
         const UVs& getUVs() const;
 
+        /** 
+         * Gets the Rectangle region of the ThemeImage.
+         */
         const Rectangle& getRegion() const;
 
+        /** 
+         * Gets the color of the ThemeImage in a Vector4.
+         */
         const Vector4& getColor() const;
 
     private:

+ 1 - 10
gameplay/src/ThemeStyle.cpp

@@ -451,16 +451,7 @@ void Theme::Style::Overlay::setAnimationPropertyValue(int propertyId, AnimationV
     {
         case ANIMATE_OPACITY:
         {
-            float opacity = value->getFloat(0);
-            if ((_animationPropertyBitFlag & ANIMATION_OPACITY_BIT) != ANIMATION_OPACITY_BIT)
-            {
-                _animationPropertyBitFlag |= ANIMATION_OPACITY_BIT;
-            }
-            else
-            {
-                opacity = Curve::lerp(blendWeight, _opacity, opacity);
-            }
-            _opacity = opacity;
+            _opacity = Curve::lerp(blendWeight, _opacity, value->getFloat(0));
             break;
         }
         default:

+ 1 - 4
gameplay/src/ThemeStyle.h

@@ -49,7 +49,6 @@ private:
     private:
 
         static const int ANIMATE_OPACITY = 1;
-        static const char ANIMATION_OPACITY_BIT = 0x01;
 
         Overlay();
             
@@ -145,9 +144,7 @@ private:
         void setImageList(Theme::ImageList* imageList);
             
         Theme::ImageList* getImageList() const;
-
-        void applyAnimationValueOpacity(float opacity, float blendWeight);
-
+        
         Skin* _skin;
         Theme::ThemeImage* _cursor;
         Theme::ImageList* _imageList;

+ 20 - 97
gameplay/src/Transform.cpp

@@ -665,80 +665,66 @@ void Transform::setAnimationPropertyValue(int propertyId, AnimationValue* value,
     {
         case ANIMATE_SCALE_UNIT:
         {
-            applyAnimationValueScaleX(value->getFloat(0), blendWeight);
-            applyAnimationValueScaleY(value->getFloat(0), blendWeight);
-            applyAnimationValueScaleZ(value->getFloat(0), blendWeight);
+            float scale = Curve::lerp(blendWeight, _scale.x, value->getFloat(0));
+            setScale(scale);
             break;
         }   
         case ANIMATE_SCALE:
         {
-            applyAnimationValueScaleX(value->getFloat(0), blendWeight);
-            applyAnimationValueScaleY(value->getFloat(1), blendWeight);
-            applyAnimationValueScaleZ(value->getFloat(2), blendWeight);
+            setScale(Curve::lerp(blendWeight, _scale.x, value->getFloat(0)), Curve::lerp(blendWeight, _scale.y, value->getFloat(1)), Curve::lerp(blendWeight, _scale.z, value->getFloat(2)));
             break;
         }
         case ANIMATE_SCALE_X:
         {
-            applyAnimationValueScaleX(value->getFloat(0), blendWeight);
+            setScaleX(Curve::lerp(blendWeight, _scale.x, value->getFloat(0)));
             break;
         }
         case ANIMATE_SCALE_Y:
         {
-            applyAnimationValueScaleY(value->getFloat(0), blendWeight);
+            setScaleY(Curve::lerp(blendWeight, _scale.y, value->getFloat(0)));
             break;
         }
         case ANIMATE_SCALE_Z:
         {
-            applyAnimationValueScaleZ(value->getFloat(0), blendWeight);
+            setScaleZ(Curve::lerp(blendWeight, _scale.z, value->getFloat(0)));
             break;
         }
         case ANIMATE_ROTATE:
         {
-            Quaternion q(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
-            applyAnimationValueRotation(&q, blendWeight);
+            applyAnimationValueRotation(value, 0, blendWeight);
             break;
         }
         case ANIMATE_TRANSLATE:
         {
-            applyAnimationValueTranslationX(value->getFloat(0), blendWeight);
-            applyAnimationValueTranslationY(value->getFloat(1), blendWeight);
-            applyAnimationValueTranslationZ(value->getFloat(2), blendWeight);
+            setTranslation(Curve::lerp(blendWeight, _translation.x, value->getFloat(0)), Curve::lerp(blendWeight, _translation.y, value->getFloat(1)), Curve::lerp(blendWeight, _translation.z, value->getFloat(2)));
             break;
         }
         case ANIMATE_TRANSLATE_X:
         {
-            applyAnimationValueTranslationX(value->getFloat(0), blendWeight);
+            setTranslationX(Curve::lerp(blendWeight, _translation.x, value->getFloat(0)));
             break;
         }
         case ANIMATE_TRANSLATE_Y:
         {
-            applyAnimationValueTranslationY(value->getFloat(0), blendWeight);
+            setTranslationY(Curve::lerp(blendWeight, _translation.y, value->getFloat(0)));
             break;
         }
         case ANIMATE_TRANSLATE_Z:
         {
-            applyAnimationValueTranslationZ(value->getFloat(0), blendWeight);
+            setTranslationZ(Curve::lerp(blendWeight, _translation.z, value->getFloat(0)));
             break;
         }
         case ANIMATE_ROTATE_TRANSLATE:
         {
-            Quaternion q(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
-            applyAnimationValueRotation(&q, blendWeight);
-            applyAnimationValueTranslationX(value->getFloat(4), blendWeight);
-            applyAnimationValueTranslationY(value->getFloat(5), blendWeight);
-            applyAnimationValueTranslationZ(value->getFloat(6), blendWeight);
+            applyAnimationValueRotation(value, 0, blendWeight);
+            setTranslation(Curve::lerp(blendWeight, _translation.x, value->getFloat(4)), Curve::lerp(blendWeight, _translation.y, value->getFloat(5)), Curve::lerp(blendWeight, _translation.z, value->getFloat(6)));
             break;
         }
         case ANIMATE_SCALE_ROTATE_TRANSLATE:
         {
-            applyAnimationValueScaleX(value->getFloat(0), blendWeight);
-            applyAnimationValueScaleY(value->getFloat(1), blendWeight);
-            applyAnimationValueScaleZ(value->getFloat(2), blendWeight);
-            Quaternion q(value->getFloat(3), value->getFloat(4), value->getFloat(5), value->getFloat(6));
-            applyAnimationValueRotation(&q, blendWeight);
-            applyAnimationValueTranslationX(value->getFloat(7), blendWeight);
-            applyAnimationValueTranslationY(value->getFloat(8), blendWeight);
-            applyAnimationValueTranslationZ(value->getFloat(9), blendWeight);
+            setScale(Curve::lerp(blendWeight, _scale.x, value->getFloat(0)), Curve::lerp(blendWeight, _scale.y, value->getFloat(1)), Curve::lerp(blendWeight, _scale.z, value->getFloat(2)));
+            applyAnimationValueRotation(value, 3, blendWeight);
+            setTranslation(Curve::lerp(blendWeight, _translation.x, value->getFloat(7)), Curve::lerp(blendWeight, _translation.y, value->getFloat(8)), Curve::lerp(blendWeight, _translation.z, value->getFloat(9)));
             break;
         }
         default:
@@ -798,74 +784,11 @@ void Transform::cloneInto(Transform* transform, NodeCloneContext &context) const
     transform->_translation.set(_translation);
 }
 
-void Transform::applyAnimationValueScaleX(float sx, float blendWeight)
+void Transform::applyAnimationValueRotation(AnimationValue* value, unsigned int index, float blendWeight)
 {
-    if ((_animationPropertyBitFlag & ANIMATION_SCALE_X_BIT) != ANIMATION_SCALE_X_BIT)
-        _animationPropertyBitFlag |= ANIMATION_SCALE_X_BIT;
-    else
-        sx = Curve::lerp(blendWeight, _scale.x, sx);
-
-    setScaleX(sx);
-}
-
-void Transform::applyAnimationValueScaleY(float sy, float blendWeight)
-{
-    if ((_animationPropertyBitFlag & ANIMATION_SCALE_Y_BIT) != ANIMATION_SCALE_Y_BIT)
-        _animationPropertyBitFlag |= ANIMATION_SCALE_Y_BIT;
-    else
-        sy = Curve::lerp(blendWeight, _scale.y, sy);
-
-    setScaleY(sy);
-}
-
-void Transform::applyAnimationValueScaleZ(float sz, float blendWeight)
-{
-    if ((_animationPropertyBitFlag & ANIMATION_SCALE_Z_BIT) != ANIMATION_SCALE_Z_BIT)
-        _animationPropertyBitFlag |= ANIMATION_SCALE_Z_BIT;
-    else
-        sz = Curve::lerp(blendWeight, _scale.z, sz);
-
-    setScaleZ(sz);
-}
-
-void Transform::applyAnimationValueRotation(Quaternion* q, float blendWeight)
-{
-    if ((_animationPropertyBitFlag & ANIMATION_ROTATION_BIT) != ANIMATION_ROTATION_BIT)
-        _animationPropertyBitFlag |= ANIMATION_ROTATION_BIT;
-    else
-        Quaternion::slerp(_rotation, *q, blendWeight, q);
-     
-    setRotation(*q);
-}
-
-void Transform::applyAnimationValueTranslationX(float tx, float blendWeight)
-{
-    if ((_animationPropertyBitFlag & ANIMATION_TRANSLATION_X_BIT) != ANIMATION_TRANSLATION_X_BIT)
-        _animationPropertyBitFlag |= ANIMATION_TRANSLATION_X_BIT;
-    else
-        tx = Curve::lerp(blendWeight, _translation.x, tx);
-
-    setTranslationX(tx);
-}
-
-void Transform::applyAnimationValueTranslationY(float ty, float blendWeight)
-{
-    if ((_animationPropertyBitFlag & ANIMATION_TRANSLATION_Y_BIT) != ANIMATION_TRANSLATION_Y_BIT)
-        _animationPropertyBitFlag |= ANIMATION_TRANSLATION_Y_BIT;
-    else
-        ty = Curve::lerp(blendWeight, _translation.y, ty);
-
-    setTranslationY(ty);
-}
-
-void Transform::applyAnimationValueTranslationZ(float tz, float blendWeight)
-{
-    if ((_animationPropertyBitFlag & ANIMATION_TRANSLATION_Z_BIT) != ANIMATION_TRANSLATION_Z_BIT)
-        _animationPropertyBitFlag |= ANIMATION_TRANSLATION_Z_BIT;
-    else
-        tz = Curve::lerp(blendWeight, _translation.z, tz);
-
-    setTranslationZ(tz);
+    Quaternion q(value->getFloat(index), value->getFloat(index + 1), value->getFloat(index + 2), value->getFloat(index + 3));
+    Quaternion::slerp(_rotation, q, blendWeight, &q);
+    setRotation(q);
 }
 
 }

+ 39 - 16
gameplay/src/Transform.h

@@ -709,7 +709,7 @@ public:
      * Adds a transform listener.
      *
      * @param listener The listener to add.
-     * @param cookie An optional long value that is passed to the specified listener when it is called..
+     * @param cookie An optional long value that is passed to the specified listener when it is called.
      */
     void addListener(Transform::Listener* listener, long cookie = 0);
 
@@ -735,12 +735,26 @@ public:
 
 protected:
 
+    /**
+     * Transform Listener.
+     */
     struct TransformListener
     {
+        /**
+         * Listener for Transform events.
+         */
         Listener* listener;
+
+        /**
+         * An optional long value that is specified to the Listener's callback.
+         */
         long cookie;
     };
 
+    /**
+     * Defines the matrix dirty bits for marking the translation, scale and rotation
+     * components of the Transform.
+     */
     enum MatrixDirtyBits
     {
         DIRTY_TRANSLATION = 0x01,
@@ -766,29 +780,38 @@ protected:
      */
     void cloneInto(Transform* transform, NodeCloneContext &context) const;
 
+    /**
+     * The scale component of the Transform.
+     */
     Vector3 _scale;
+
+    /** 
+     * The rotation component of the Transform.
+     */
     Quaternion _rotation;
+    
+    /** 
+     * The translation component of the Transform.
+     */
     Vector3 _translation;
+    
+    /** 
+     * The Matrix representation of the Transform.
+     */
     mutable Matrix _matrix;
+    
+    /** 
+     * Matrix dirty bits flag.
+     */
     mutable char _matrixDirtyBits;
+    
+    /** 
+     * List of TransformListener's on the Transform.
+     */
     std::list<TransformListener>* _listeners;
 
 private:
-    static const char ANIMATION_SCALE_X_BIT = 0x01; 
-    static const char ANIMATION_SCALE_Y_BIT = 0x02; 
-    static const char ANIMATION_SCALE_Z_BIT = 0x04; 
-    static const char ANIMATION_ROTATION_BIT = 0x08;  
-    static const char ANIMATION_TRANSLATION_X_BIT = 0x10; 
-    static const char ANIMATION_TRANSLATION_Y_BIT = 0x20; 
-    static const char ANIMATION_TRANSLATION_Z_BIT = 0x40; 
-
-    void applyAnimationValueScaleX(float sx, float blendWeight);
-    void applyAnimationValueScaleY(float sy, float blendWeight);
-    void applyAnimationValueScaleZ(float sz, float blendWeight);
-    void applyAnimationValueRotation(Quaternion* q, float blendWeight);
-    void applyAnimationValueTranslationX(float tx, float blendWeight);
-    void applyAnimationValueTranslationY(float ty, float blendWeight);
-    void applyAnimationValueTranslationZ(float tz, float blendWeight);
+    void applyAnimationValueRotation(AnimationValue* value, unsigned int index, float blendWeight);
 };
 
 }

+ 7 - 7
gameplay/src/VertexAttributeBinding.cpp

@@ -86,11 +86,11 @@ VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexF
     // Create a new VertexAttributeBinding.
     VertexAttributeBinding* b = new VertexAttributeBinding();
 
-#ifdef USE_GL_VAOS
+#ifdef USE_VAO
     if (mesh && glGenVertexArrays)
     {
         GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
-        GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) );
+        GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
 
         // Use hardware VAOs.
         GL_ASSERT( glGenVertexArrays(1, &b->_handle) );
@@ -168,11 +168,11 @@ VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexF
             attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDINDICES_NAME);
             break;
         case VertexFormat::TEXCOORD0:
-            attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX);
+            attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME);
             // Try adding a "0" after the texcoord attrib name (flexible name for this case).
             if (attrib == -1)
             {
-                name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX;
+                name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME;
                 name += "0";
                 attrib = effect->getVertexAttribute(name.c_str());
             }
@@ -184,7 +184,7 @@ VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexF
         case VertexFormat::TEXCOORD5:
         case VertexFormat::TEXCOORD6:
         case VertexFormat::TEXCOORD7:
-            name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX;
+            name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME;
             name += (e.usage - VertexFormat::TEXCOORD0);
             attrib = effect->getVertexAttribute(name.c_str());
             break;
@@ -221,8 +221,8 @@ void VertexAttributeBinding::setVertexAttribPointer(GLuint indx, GLint size, GLe
     if (_handle)
     {
         // Hardware mode
-        GL_ASSERT( glEnableVertexAttribArray(indx) );
         GL_ASSERT( glVertexAttribPointer(indx, size, type, normalize, stride, pointer) );
+        GL_ASSERT( glEnableVertexAttribArray(indx) );
     }
     else
     {
@@ -260,8 +260,8 @@ void VertexAttributeBinding::bind()
             VertexAttribute& a = _attributes[i];
             if (a.enabled)
             {
-                GL_ASSERT( glEnableVertexAttribArray(i) );
                 GL_ASSERT( glVertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, a.pointer) );
+                GL_ASSERT( glEnableVertexAttribArray(i) );
             }
         }
     }

+ 4 - 0
gameplay/src/VerticalLayout.h

@@ -69,6 +69,10 @@ protected:
      */
     void update(const Container* container);
 
+    /**
+     * Flag determining whether this layout will start laying out controls from the bottom of the container.
+     * The default is 'false' meaning controls will start at the top.
+     */
     bool _bottomToTop;
 
 private: