Pārlūkot izejas kodu

Merge pull request #499 from blackberry/next

gameplay v1.5.0
Sean Paul Taylor 13 gadi atpakaļ
vecāks
revīzija
c44a22146b
100 mainītis faili ar 5541 papildinājumiem un 1438 dzēšanām
  1. 100 42
      .gitignore
  2. 1 0
      .kateconfig
  3. 29 0
      CHANGES.md
  4. 26 0
      CMakeLists.txt
  5. 6 6
      README.md
  6. 8 0
      cmake/README.md
  7. 145 0
      gameplay-encoder/CMakeLists.txt
  8. 37 23
      gameplay-encoder/README.md
  9. 1 1
      gameplay-encoder/gameplay-bundle.txt
  10. 7 5
      gameplay-encoder/gameplay-encoder.vcxproj
  11. 9 0
      gameplay-encoder/gameplay-encoder.vcxproj.filters
  12. 2 2
      gameplay-encoder/gameplay-encoder.vcxproj.user
  13. 28 0
      gameplay-encoder/gameplay-encoder.xcodeproj/project.pbxproj
  14. 12 63
      gameplay-encoder/src/AnimationChannel.cpp
  15. 5 8
      gameplay-encoder/src/AnimationChannel.h
  16. 12 8
      gameplay-encoder/src/Base.h
  17. 9 0
      gameplay-encoder/src/BoundingVolume.cpp
  18. 1 0
      gameplay-encoder/src/Camera.cpp
  19. 1 1
      gameplay-encoder/src/Curve.cpp
  20. 1 1
      gameplay-encoder/src/DAEOptimizer.cpp
  21. 78 84
      gameplay-encoder/src/DAESceneEncoder.cpp
  22. 0 3
      gameplay-encoder/src/DAESceneEncoder.h
  23. 17 17
      gameplay-encoder/src/DAEUtil.cpp
  24. 93 39
      gameplay-encoder/src/EncoderArguments.cpp
  25. 11 8
      gameplay-encoder/src/EncoderArguments.h
  26. 321 159
      gameplay-encoder/src/FBXSceneEncoder.cpp
  27. 1 11
      gameplay-encoder/src/FBXSceneEncoder.h
  28. 2 0
      gameplay-encoder/src/FileIO.h
  29. 103 34
      gameplay-encoder/src/GPBFile.cpp
  30. 8 2
      gameplay-encoder/src/GPBFile.h
  31. 533 0
      gameplay-encoder/src/Heightmap.cpp
  32. 27 0
      gameplay-encoder/src/Heightmap.h
  33. 1 1
      gameplay-encoder/src/Light.cpp
  34. 4 228
      gameplay-encoder/src/Mesh.cpp
  35. 0 7
      gameplay-encoder/src/Mesh.h
  36. 19 19
      gameplay-encoder/src/MeshSkin.cpp
  37. 0 25
      gameplay-encoder/src/Node.cpp
  38. 0 6
      gameplay-encoder/src/Node.h
  39. 1 0
      gameplay-encoder/src/Object.h
  40. 3 3
      gameplay-encoder/src/Quaternion.cpp
  41. 12 12
      gameplay-encoder/src/TTFFontEncoder.cpp
  42. 99 0
      gameplay-encoder/src/Thread.h
  43. 11 32
      gameplay-encoder/src/Transform.cpp
  44. 10 9
      gameplay-encoder/src/Transform.h
  45. 1 1
      gameplay-encoder/src/Vector4.cpp
  46. 19 8
      gameplay-encoder/src/Vertex.cpp
  47. 21 12
      gameplay-encoder/src/Vertex.h
  48. 4 4
      gameplay-encoder/src/main.cpp
  49. 23 15
      gameplay-luagen/gameplay-luagen.doxyfile
  50. 4 2
      gameplay-luagen/gameplay-luagen.vcxproj
  51. 70 70
      gameplay-newproject.bat
  52. 54 36
      gameplay-newproject.sh
  53. 3 3
      gameplay-template/gameplay-template.vcxproj
  54. 3 3
      gameplay-template/gameplay-template.vcxproj.user
  55. 6 32
      gameplay-template/gameplay-template.xcodeproj/project.pbxproj
  56. BIN
      gameplay-template/icon.png
  57. 0 2
      gameplay-template/template.bar-descriptor.xml
  58. 28 21
      gameplay-template/template.cproject
  59. 23 15
      gameplay.doxyfile
  60. 198 8
      gameplay.sln
  61. 30 0
      gameplay.workspace
  62. 6 0
      gameplay.xcworkspace/contents.xcworkspacedata
  63. 614 0
      gameplay/CMakeLists.txt
  64. 11 2
      gameplay/android/jni/Android.mk
  65. 591 0
      gameplay/gameplay.cbp
  66. 255 8
      gameplay/gameplay.vcxproj
  67. 74 20
      gameplay/gameplay.vcxproj.filters
  68. 996 3
      gameplay/gameplay.xcodeproj/project.pbxproj
  69. 58 0
      gameplay/gameplay.xcodeproj/xcshareddata/xcschemes/gameplay-ios.xcscheme
  70. 58 0
      gameplay/gameplay.xcodeproj/xcshareddata/xcschemes/gameplay-macosx.xcscheme
  71. 4 1
      gameplay/res/shaders/colored-unlit.frag
  72. 16 2
      gameplay/res/shaders/colored-unlit.vert
  73. 11 4
      gameplay/res/shaders/textured-unlit.frag
  74. 14 5
      gameplay/res/shaders/textured-unlit.vert
  75. 24 23
      gameplay/src/Animation.cpp
  76. 30 29
      gameplay/src/Animation.h
  77. 5 5
      gameplay/src/AnimationClip.cpp
  78. 1 1
      gameplay/src/AnimationController.cpp
  79. 35 35
      gameplay/src/AnimationTarget.cpp
  80. 23 23
      gameplay/src/AnimationTarget.h
  81. 6 6
      gameplay/src/AnimationValue.cpp
  82. 10 10
      gameplay/src/AnimationValue.h
  83. 8 6
      gameplay/src/AudioBuffer.cpp
  84. 1 1
      gameplay/src/AudioBuffer.h
  85. 16 0
      gameplay/src/AudioListener.cpp
  86. 30 0
      gameplay/src/AudioListener.h
  87. 7 2
      gameplay/src/AudioSource.cpp
  88. 9 0
      gameplay/src/AudioSource.h
  89. 27 11
      gameplay/src/Base.h
  90. 11 0
      gameplay/src/BoundingBox.cpp
  91. 24 0
      gameplay/src/BoundingBox.h
  92. 18 19
      gameplay/src/Bundle.cpp
  93. 1 1
      gameplay/src/Bundle.h
  94. 27 26
      gameplay/src/Button.cpp
  95. 1 0
      gameplay/src/Button.h
  96. 10 9
      gameplay/src/CheckBox.cpp
  97. 159 81
      gameplay/src/Container.cpp
  98. 9 0
      gameplay/src/Container.h
  99. 39 14
      gameplay/src/Control.cpp
  100. 21 0
      gameplay/src/Control.h

+ 100 - 42
.gitignore

@@ -1,13 +1,16 @@
 *.suo
 *.sdf
-*.opensdf
-.DS_Store*
-ehthumbs.db
-Icon?
+*.opensdf
+*.layout
+*.depend
+.DS_Store*
+ehthumbs.db
+Icon?
 Thumbs.db
 /.metadata
 /169.254.0.1
 /ipch
+/cmake
 /Debug
 /Release
 /Simulator
@@ -17,6 +20,18 @@ Thumbs.db
 /Device-Coverage
 /Device-Profile
 /Device-Release
+/gameplay-internal
+/gameplay-api/xml
+
+/gameplay-encoder/Debug
+/gameplay-encoder/Release
+/gameplay-encoder/gameplay-encoder.xcodeproj/xcuserdata
+
+/gameplay-luagen/Release
+/gameplay-luagen/Debug
+/gameplay-luagen/doxygen_entrydb_680.tmp
+/gameplay-luagen/doxygen_objdb_680.tmp
+/gameplay-luagen/xml
 
 /gameplay/Debug
 /gameplay/DebugMem
@@ -27,26 +42,39 @@ Thumbs.db
 /gameplay/Device-Debug
 /gameplay/Device-Coverage
 /gameplay/Device-Profile
-/gameplay/Device-Release
+/gameplay/Device-Release
 /gameplay.xcworkspace/xcuserdata
-/gameplay/gameplay.xcodeproj/xcuserdata
+/gameplay/gameplay.xcodeproj/xcuserdata
 /gameplay/android/NUL
 /gameplay/android/proguard.cfg
+/gameplay/android/proguard-project.txt
 /gameplay/android/local.properties
 /gameplay/android/project.properties
-/gameplay/android/obj
-
-/gameplay-api/xml
-
-/gameplay-encoder/Debug
-/gameplay-encoder/Release
-/gameplay-encoder/gameplay-encoder.xcodeproj/xcuserdata
+/gameplay/android/obj
 
-/gameplay-luagen/Release
-/gameplay-luagen/Debug
-/gameplay-luagen/doxygen_entrydb_680.tmp
-/gameplay-luagen/doxygen_objdb_680.tmp
-/gameplay-luagen/xml
+/gameplay-tests/Debug
+/gameplay-tests/DebugMem
+/gameplay-tests/Release
+/gameplay-tests/Simulator
+/gameplay-tests/Simulator-Coverage
+/gameplay-tests/Simulator-Profile
+/gameplay-tests/Device-Debug
+/gameplay-tests/Device-Coverage
+/gameplay-tests/Device-Profile
+/gameplay-tests/Device-Release
+/gameplay-tests/res/shaders
+/gameplay-tests/res/logo_powered_white.png
+/gameplay-tests/gameplay-tests.xcodeproj/xcuserdata
+/gameplay-tests/android/src
+/gameplay-tests/android/assets
+/gameplay-tests/android/bin
+/gameplay-tests/android/gen
+/gameplay-tests/android/libs
+/gameplay-tests/android/obj
+/gameplay-tests/android/NUL
+/gameplay-tests/android/local.properties
+/gameplay-tests/android/proguard-project.txt
+/gameplay-tests/android/project.properties
 
 /gameplay-samples/sample00-mesh/Debug
 /gameplay-samples/sample00-mesh/DebugMem
@@ -58,9 +86,9 @@ Thumbs.db
 /gameplay-samples/sample00-mesh/Device-Coverage
 /gameplay-samples/sample00-mesh/Device-Profile
 /gameplay-samples/sample00-mesh/Device-Release
-/gameplay-samples/sample00-mesh/res/shaders
+/gameplay-samples/sample00-mesh/res/shaders
 /gameplay-samples/sample00-mesh/res/logo_powered_white.png
-/gameplay-samples/sample00-mesh/sample00-mesh.xcodeproj/xcuserdata
+/gameplay-samples/sample00-mesh/sample00-mesh.xcodeproj/xcuserdata
 /gameplay-samples/sample00-mesh/android/src
 /gameplay-samples/sample00-mesh/android/assets
 /gameplay-samples/sample00-mesh/android/bin
@@ -70,7 +98,7 @@ Thumbs.db
 /gameplay-samples/sample00-mesh/android/NUL
 /gameplay-samples/sample00-mesh/android/local.properties
 /gameplay-samples/sample00-mesh/android/proguard.cfg
-/gameplay-samples/sample00-mesh/android/project.properties
+/gameplay-samples/sample00-mesh/android/project.properties
 
 /gameplay-samples/sample01-longboard/Debug
 /gameplay-samples/sample01-longboard/DebugMem
@@ -82,9 +110,9 @@ Thumbs.db
 /gameplay-samples/sample01-longboard/Device-Coverage
 /gameplay-samples/sample01-longboard/Device-Profile
 /gameplay-samples/sample01-longboard/Device-Release
-/gameplay-samples/sample01-longboard/res/shaders
+/gameplay-samples/sample01-longboard/res/shaders
 /gameplay-samples/sample01-longboard/res/logo_powered_white.png
-/gameplay-samples/sample01-longboard/sample01-longboard.xcodeproj/xcuserdata
+/gameplay-samples/sample01-longboard/sample01-longboard.xcodeproj/xcuserdata
 /gameplay-samples/sample01-longboard/NUL
 /gameplay-samples/sample01-longboard/android/NUL
 /gameplay-samples/sample01-longboard/android/src
@@ -92,10 +120,10 @@ Thumbs.db
 /gameplay-samples/sample01-longboard/android/bin
 /gameplay-samples/sample01-longboard/android/gen
 /gameplay-samples/sample01-longboard/android/libs
-/gameplay-samples/sample01-longboard/android/obj
+/gameplay-samples/sample01-longboard/android/obj
 /gameplay-samples/sample01-longboard/android/proguard.cfg
 /gameplay-samples/sample01-longboard/android/project.properties
-/gameplay-samples/sample01-longboard/android/local.properties
+/gameplay-samples/sample01-longboard/android/local.properties
 
 /gameplay-samples/sample02-spaceship/Debug
 /gameplay-samples/sample02-spaceship/DebugMem
@@ -107,9 +135,9 @@ Thumbs.db
 /gameplay-samples/sample02-spaceship/Device-Coverage
 /gameplay-samples/sample02-spaceship/Device-Profile
 /gameplay-samples/sample02-spaceship/Device-Release
-/gameplay-samples/sample02-spaceship/res/shaders
+/gameplay-samples/sample02-spaceship/res/shaders
 /gameplay-samples/sample02-spaceship/res/logo_powered_white.png
-/gameplay-samples/sample02-spaceship/sample02-spaceship.xcodeproj/xcuserdata
+/gameplay-samples/sample02-spaceship/sample02-spaceship.xcodeproj/xcuserdata
 /gameplay-samples/sample02-spaceship/android/NUL
 /gameplay-samples/sample02-spaceship/android/project.properties
 /gameplay-samples/sample02-spaceship/android/assets
@@ -119,7 +147,7 @@ Thumbs.db
 /gameplay-samples/sample02-spaceship/android/obj
 /gameplay-samples/sample02-spaceship/android/src
 /gameplay-samples/sample02-spaceship/android/proguard.cfg
-/gameplay-samples/sample02-spaceship/android/local.properties
+/gameplay-samples/sample02-spaceship/android/local.properties
 
 /gameplay-samples/sample03-character/Debug
 /gameplay-samples/sample03-character/DebugMem
@@ -131,9 +159,10 @@ Thumbs.db
 /gameplay-samples/sample03-character/Device-Coverage
 /gameplay-samples/sample03-character/Device-Profile
 /gameplay-samples/sample03-character/Device-Release
-/gameplay-samples/sample03-character/res/shaders
+/gameplay-samples/sample03-character/game.config
+/gameplay-samples/sample03-character/res/shaders
 /gameplay-samples/sample03-character/res/logo_powered_white.png
-/gameplay-samples/sample03-character/sample03-character.xcodeproj/xcuserdata
+/gameplay-samples/sample03-character/sample03-character.xcodeproj/xcuserdata
 /gameplay-samples/sample03-character/android/project.properties
 /gameplay-samples/sample03-character/android/proguard.cfg
 /gameplay-samples/sample03-character/android/local.properties
@@ -143,8 +172,8 @@ Thumbs.db
 /gameplay-samples/sample03-character/android/gen
 /gameplay-samples/sample03-character/android/libs
 /gameplay-samples/sample03-character/android/obj
-/gameplay-samples/sample03-character/android/NUL
-/gameplay-samples/sample03-character/res/gamepad.xcf
+/gameplay-samples/sample03-character/android/NUL
+/gameplay-samples/sample03-character/res/gamepad.xcf
 
 /gameplay-samples/sample04-particles/Debug
 /gameplay-samples/sample04-particles/DebugMem
@@ -156,9 +185,9 @@ Thumbs.db
 /gameplay-samples/sample04-particles/Device-Coverage
 /gameplay-samples/sample04-particles/Device-Profile
 /gameplay-samples/sample04-particles/Device-Release
-/gameplay-samples/sample04-particles/res/shaders
+/gameplay-samples/sample04-particles/res/shaders
 /gameplay-samples/sample04-particles/res/logo_powered_white.png
-/gameplay-samples/sample04-particles/sample04-particles.xcodeproj/xcuserdata
+/gameplay-samples/sample04-particles/sample04-particles.xcodeproj/xcuserdata
 /gameplay-samples/sample04-particles/Device-Debug
 /gameplay-samples/sample04-particles/Debug
 /gameplay-samples/sample04-particles/DebugMem
@@ -170,8 +199,8 @@ Thumbs.db
 /gameplay-samples/sample04-particles/android/obj
 /gameplay-samples/sample04-particles/android/proguard.cfg
 /gameplay-samples/sample04-particles/android/local.properties
-/gameplay-samples/sample04-particles/android/project.properties
-
+/gameplay-samples/sample04-particles/android/project.properties
+
 /gameplay-samples/sample05-lua/Debug
 /gameplay-samples/sample05-lua/DebugMem
 /gameplay-samples/sample05-lua/Release
@@ -182,9 +211,9 @@ Thumbs.db
 /gameplay-samples/sample05-lua/Device-Coverage
 /gameplay-samples/sample05-lua/Device-Profile
 /gameplay-samples/sample05-lua/Device-Release
-/gameplay-samples/sample05-lua/res/shaders
+/gameplay-samples/sample05-lua/res/shaders
 /gameplay-samples/sample05-lua/res/logo_powered_white.png
-/gameplay-samples/sample05-lua/sample05-lua.xcodeproj/xcuserdata
+/gameplay-samples/sample05-lua/sample05-lua.xcodeproj/xcuserdata
 /gameplay-samples/sample05-lua/android/src
 /gameplay-samples/sample05-lua/android/assets
 /gameplay-samples/sample05-lua/android/bin
@@ -194,7 +223,36 @@ Thumbs.db
 /gameplay-samples/sample05-lua/android/NUL
 /gameplay-samples/sample05-lua/android/local.properties
 /gameplay-samples/sample05-lua/android/proguard.cfg
-/gameplay-samples/sample05-lua/android/project.properties
-
-/gameplay-internal
-/gameplay\android/proguard-project.txt
+/gameplay-samples/sample05-lua/android/project.properties
+
+/gameplay-samples/sample06-racer/Debug
+/gameplay-samples/sample06-racer/DebugMem
+/gameplay-samples/sample06-racer/Release
+/gameplay-samples/sample06-racer/Simulator
+/gameplay-samples/sample06-racer/Simulator-Coverage
+/gameplay-samples/sample06-racer/Simulator-Profile
+/gameplay-samples/sample06-racer/Device-Debug
+/gameplay-samples/sample06-racer/Device-Debug-IMG
+/gameplay-samples/sample06-racer/Device-Coverage
+/gameplay-samples/sample06-racer/Device-Profile
+/gameplay-samples/sample06-racer/Device-Release
+/gameplay-samples/sample06-racer/game.config
+/gameplay-samples/sample06-racer/res/shaders
+/gameplay-samples/sample06-racer/res/logo_powered_white.png
+/gameplay-samples/sample06-racer/sample06-racer.xcodeproj/xcuserdata
+/gameplay-samples/sample06-racer/android/project.properties
+/gameplay-samples/sample06-racer/android/proguard.cfg
+/gameplay-samples/sample06-racer/android/local.properties
+/gameplay-samples/sample06-racer/android/src
+/gameplay-samples/sample06-racer/android/assets
+/gameplay-samples/sample06-racer/android/bin
+/gameplay-samples/sample06-racer/android/gen
+/gameplay-samples/sample06-racer/android/libs
+/gameplay-samples/sample06-racer/android/obj
+/gameplay-samples/sample06-racer/android/NUL
+/gameplay-samples/sample06-racer/android/local.properties
+/gameplay-samples/sample06-racer/android/proguard.cfg
+/gameplay-samples/sample06-racer/android/project.properties
+
+
+

+ 1 - 0
.kateconfig

@@ -0,0 +1 @@
+kate: space-indent on; tab-width 4; indent-width 4; replace-tabs on; show-tabs: on; replace-tabs-save: off; replace-trailing-space-save: off;

+ 29 - 0
CHANGES.md

@@ -1,3 +1,32 @@
+## v1.5.0
+
+- Linux support. (tested on Ubuntu 12)
+- CMake support for makefile generation for Linux.
+- CodeBlocks 10 IDE support for Linux.
+- Gamepad controllers support for desktops.
+- Touch gesture support for tap, swipe and pinch.
+- Vehicle phyics support via new PhysicsVehicle and PhysicsVehicleWheel classes.
+- Adds new racer sample (sample06-racer).
+- Adds gameplay-tests project as a test app for various basic engine features with some initial tests.
+- Adds support for Scene files for wildcard identifiers.
+- Adds Visual Studio Plug-in support for BlackBerry PlayBook and BlackBerry 10.
+- Adds configurable multi-sampling anti-aliasing support. 
+- Adds updates to latest FBX SDK 2013.3.
+- Adds file formats documenation for game.config .scene, .material, .animation, .physics, .particle
+- Adds Game/Platform::canExit for testing device capabilities to quit. (only ios)
+- Web community forums at http://www.gameplay3d.org/forums.
+- Changed keyTimes from unsigned long[]  to unsigned int[]. (breaks compat. in AnimationTarget and Animation::Channel)
+- Fixed inconsistencies from Bundle::getObjectID() to Bundle::getObjectId() (breaks compat. in Bundle)
+- Fixes the texture coordinates of Mesh::createQuad(float x, float y, float width, float height).
+- Fixes line-wise distortion when loading RGB png's into texture that are non-power of two.
+- Fixes inconsitencies in createXXXX methods.  (breaks compat. in Scene)
+- Fixes Rectanngle::contains.
+- Fixes Lua print logging.
+- Fixes Lua errors to be treated as runtime warnings.
+- Fixes setVertexData to pointers instead of constant data.
+- Fixed AudioSource so that it doesn't loop by default.
+- Fixes minor UI scrolling issues.
+
 ## v1.4.0
 
 - Lua script bindings for all gameplay interfaces.

+ 26 - 0
CMakeLists.txt

@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.6)
+
+project(GamePlay)
+
+set(GAMEPLAY_VERSION 1.5.0)
+set(CMAKE_C_COMPILER_INIT g++)
+
+# debug
+message( "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}" )
+if( "${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG" )
+    add_definitions(-D_DEBUG)
+endif()
+
+# gameplay library
+add_subdirectory(gameplay)
+
+# gameplay samples
+add_subdirectory(gameplay-samples)
+
+# gameplay samples
+add_subdirectory(gameplay-tests)
+
+# gameplay encoder (See gameplay/bin)
+#add_subdirectory(gameplay-encoder)
+
+

+ 6 - 6
README.md

@@ -1,20 +1,20 @@
-## gameplay v1.4.0
+## gameplay v1.5.0
 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 10 and PlayBook 2.0 (using BlackBerry Native SDK)
-- Google Android 2.3+ (using Google Android NDK, SDK API level 9+)
 - Apple iOS 5.1 (using Apple XCode 4.3.2)
+- Google Android 2.3+ (using Google Android NDK, SDK API level 9+)
 
 ## Supported Desktop Platforms
 - Microsoft Windows 7 (using Microsoft Visual Studio 2010)
 - Apple MacOS X (using Apple XCode 4.3.2)
+- Linux (using CMake or CodeBlocks 10)
 
 ## Roadmap for 'next' branch
-- Linux support
-- Vehicle physics
-- Shadows
-- AI pathfinding
+- AI Pathfinding
+- Terrain and Water
+- Asset Pipeline improvements
 
 ## Licence
 The project is open sourced under the Apache 2.0 license.

+ 8 - 0
cmake/README.md

@@ -0,0 +1,8 @@
+## Building with CMake
+Run the following command lines from this directory:
+* cmake ..
+* make
+
+
+
+

+ 145 - 0
gameplay-encoder/CMakeLists.txt

@@ -0,0 +1,145 @@
+
+include_directories( 
+    ${CMAKE_SOURCE_DIR}/external-deps/zlib/include
+    ${CMAKE_SOURCE_DIR}/external-deps/libpng/include
+    ${CMAKE_SOURCE_DIR}/external-deps/freetype2/include
+    ${CMAKE_SOURCE_DIR}/external-deps/collada-dom/include
+    ${CMAKE_SOURCE_DIR}/external-deps/collada-dom/include/1.4
+    /usr/include/libxml2
+    /usr/include
+)
+
+add_definitions(-D__linux__ -DNO_BOOST -DNO_ZAE)
+
+link_directories(
+    ${CMAKE_SOURCE_DIR}/external-deps/zlib/lib/linux
+    ${CMAKE_SOURCE_DIR}/external-deps/libpng/lib/linux
+    ${CMAKE_SOURCE_DIR}/external-deps/freetype2/lib/linux
+    ${CMAKE_SOURCE_DIR}/external-deps/collada-dom/lib/linux
+    /usr/lib
+)
+
+set(APP_LIBRARIES
+    collada14dom
+    pcre
+    pcrecpp
+    xml2
+    png
+    z   
+    freetype
+    pthread
+) 
+
+add_definitions(-lstdc++ -lcollada14dom -lpcre -lpcrecpp -lxml2 -lpng -lz -lfreetype -lpthread)
+
+set( APP_NAME gameplay-encoder )
+
+set(APP_SRC
+	src/AnimationChannel.cpp
+	src/AnimationChannel.h
+	src/Animation.cpp
+	src/Animation.h
+	src/Animations.cpp
+	src/Animations.h
+	src/Base.cpp
+	src/Base.h
+	src/BoundingVolume.cpp
+	src/BoundingVolume.h
+	src/Camera.cpp
+	src/Camera.h
+	src/Curve.cpp
+	src/Curve.h
+	src/Curve.inl
+	src/DAEChannelTarget.cpp
+	src/DAEChannelTarget.h
+	src/DAEOptimizer.cpp
+	src/DAEOptimizer.h
+	src/DAESceneEncoder.cpp
+	src/DAESceneEncoder.h
+	src/DAEUtil.cpp
+	src/DAEUtil.h
+	src/Effect.cpp
+	src/Effect.h
+	src/EncoderArguments.cpp
+	src/EncoderArguments.h
+	src/FBXSceneEncoder.cpp
+	src/FBXSceneEncoder.h
+	src/FileIO.cpp
+	src/FileIO.h
+	src/Font.cpp
+	src/Font.h
+	src/Glyph.cpp
+	src/Glyph.h
+	src/GPBDecoder.cpp
+	src/GPBDecoder.h
+	src/GPBFile.cpp
+	src/GPBFile.h
+	src/Heightmap.cpp
+	src/Heightmap.h
+	src/Light.cpp
+	src/Light.h
+	src/main.cpp
+	src/Material.cpp
+	src/Material.h
+	src/MaterialParameter.cpp
+	src/MaterialParameter.h
+	src/Matrix.cpp
+	src/Matrix.h
+	src/Mesh.cpp
+	src/Mesh.h
+	src/MeshPart.cpp
+	src/MeshPart.h
+	src/MeshSkin.cpp
+	src/MeshSkin.h
+	src/MeshSubSet.cpp
+	src/MeshSubSet.h
+	src/Model.cpp
+	src/Model.h
+	src/Node.cpp
+	src/Node.h
+	src/Object.cpp
+	src/Object.h
+	src/Quaternion.cpp
+	src/Quaternion.h
+	src/Quaternion.inl
+	src/Reference.cpp
+	src/Reference.h
+	src/ReferenceTable.cpp
+	src/ReferenceTable.h
+	src/Scene.cpp
+	src/Scene.h
+	src/StringUtil.cpp
+	src/StringUtil.h
+	src/Thread.h
+	src/Transform.cpp
+	src/Transform.h
+	src/TTFFontEncoder.cpp
+	src/TTFFontEncoder.h
+	src/Vector2.cpp
+	src/Vector2.h
+	src/Vector2.inl
+	src/Vector3.cpp
+	src/Vector3.h
+	src/Vector3.inl
+	src/Vector4.cpp
+	src/Vector4.h
+	src/Vector4.inl
+	src/Vertex.cpp
+	src/VertexElement.cpp
+	src/VertexElement.h
+	src/Vertex.h
+)
+
+add_executable(${APP_NAME}
+    ${APP_SRC}
+)
+
+target_link_libraries(${APP_NAME} ${APP_LIBRARIES})
+
+set_target_properties(${APP_NAME} PROPERTIES
+    OUTPUT_NAME "${APP_NAME}"
+    CLEAN_DIRECT_OUTPUT 1
+)
+
+source_group(src FILES ${APP_SRC})
+

+ 37 - 23
gameplay-encoder/README.md

@@ -1,41 +1,42 @@
 ## gameplay-encoder
 Command-line tool for encoding games assets like true-type fonts and 3D scene files
 into a simple binary-based bundle file format for the gameplay 3D game framework runtime. 
-The 'bin' folder contains pre-built versions of the gameplay-encoder executables for both 
-Windows 7 and MacOS X with support built-in support for:
+The 'bin' folder contains pre-built versions of the gameplay-encoder executables for 
+Windows 7, MacOS X and Linux (tested on Ubuntu 12) with support built-in support for:
 
 ## TrueType Font
-TrueType Fonts represent a standard in defining outline fonts and has become the 
-most common format for fonts. The gameplay-encoder reads these fonts and binary encodes 
-them into a texture mapped base representation using a texture atlas and 8-bit alpha
+TrueType Fonts represent a standard in defining outline fonts and has become the 
+most common format for fonts. The gameplay-encoder reads these fonts and binary encodes 
+them into a texture mapped base representation using a texture atlas and 8-bit alpha
 representation.
 
-## COLLADA Scene
-COLLADA is a royalty-free XML schema that enables digital asset exchange 
+## COLLADA Scene
+COLLADA is a royalty-free XML schema that enables digital asset exchange 
 within the interactive 3D industry. Most major 3D DCC tools support export to COLLADA 1.4.
 
 ## FBX Scene
-Autodesk® FBX® asset exchange technology facilitates higher-fidelity data exchange 
-between several Autodesk content creation packages
-Autodesk® Maya®, Autodesk® 3ds Max®, Autodesk® MotionBuilder®, Autodesk® Mudbox®, and Autodesk® Softimage®
-For more information goto "http://www.autodesk.com/fbx".
-
-## Building gameplay-encoder
-The gameplay-encoder comes pre-built for both Windows 7 and MacOS X in the 'bin' folder.
-However, to build the gameplay-ecoder yourself just open either the 
-Visual Studio 2010 project "gameplay-encoder.vccproj" on Windows 7 or
+Autodesk® FBX® asset exchange technology facilitates higher-fidelity data exchange 
+between several Autodesk content creation packages
+Autodesk® Maya®, Autodesk® 3ds Max®, Autodesk® MotionBuilder®, Autodesk® Mudbox®, and Autodesk® Softimage®
+For more information goto "http://www.autodesk.com/fbx".
+
+## Building gameplay-encoder
+The gameplay-encoder comes pre-built for Windows 7, MacOS X and Linux x64 in the 'bin' folder.
+However, to build the gameplay-ecoder yourself just open either the 
+Visual Studio 2010 project "gameplay-encoder.vccproj" on Windows 7 or
 XCode project "gameplay-encoder.xcodeproj" on MacOSX.
+Uncomment the root CMakeList.txt for the gameplay-encoder and run standard cmake .. from build then make.
 
 ### Building with FBX Support on Windows 7 using Visual Studio 2010
 - Download and install the FBX SDK for Window VS2010. (http://www.autodesk.com/fbx)
 - Edit the project properties of "gameplay-encoder" for Debug
 - Add Preprocessor Definition "USE_FBX" (C++/Preprocessor)
 - Add the FBX SDK include directory to Additional Include Directories (C++/General)
-  * Example: C:/Program Files/Autodesk/FBX/FbxSdk/2013.2/include
+  * Example: C:/Program Files/Autodesk/FBX/FBX SDK/2013.3/include
 - Add the FBX lib directory to the Additional Library Directories (Linker/General)
-  * Example: C:/Program Files/Autodesk/FBX/FbxSdk/2013.2/lib/vs2010/x86
-- Add "fbxsdk-2013.2-mdd.lib"(Release) to the Additional Dependencies (Linker/Input)
-  * Example: fbxsdk-2013.2-mdd.lib
+  * Example: C:/Program Files/Autodesk/FBX/FBX SDK/2013.3/lib/vs2010/x86
+- Add "fbxsdk-2013.3-mdd.lib"(Release) to the Additional Dependencies (Linker/Input)
+  * Example: fbxsdk-2013.3-mdd.lib
 - Build gameplay-encoder
 
 ### Building with FBX Support on Mac OS X using XCode 4.3.2+
@@ -43,12 +44,25 @@ XCode project "gameplay-encoder.xcodeproj" on MacOSX.
 - Edit the project properties of target "gameplay-encoder".
 - Add Preprocessor Macro "USE_FBX" to both Debug/Release sections. (Build Settings)
 - Add the FBX include directory to Header Search Paths: (Build Settings)
-  * Example: "/Applications/Autodesk/FBX SDK/2013.2/include" (Use quotes due to additional space in path)
+  * Example: "/Applications/Autodesk/FBX SDK/2013.3/include" (Use quotes due to additional space in path)
 - Add the FBX library and dependency Library/Frameworks: (Build Phases -> Link Binary with Libraries)
-  * Example: /Applications/Autodesk/FBX SDK/2013.2/lib/gcc4/ub/libfbxsdk-2013.2-static.a  (Add Other)
-  * Example: libiconv.dylib, Cocoa.framework, SystemConfiguration.framework
+  * Example: /Applications/Autodesk/FBX SDK/2013.3/lib/gcc4/ub/libfbxsdk-2013.3-static.a  (Add Other)
 - Build gameplay-encoder
 
+### Building with FBX Support on Linux
+- Download and install the FBX SDK for Mac OS X (http://www.autodesk.com/fbx)
+- Edit the gameplay-encoder/CMakeLists.txt adding the following:
+- Add the FBX include directory to Header Search Paths: (Build Settings)
+  * Example: /usr/include/fbxsdk
+- Add Preprocessor Macro to the add"-DUSE_FBX" to the end of the add_definitions(...) section of the CMakeLists.txt
+- Add the FBX library path to the link_directories(...) section of the CMakeLists.txt
+  * Example: /usr/lib/gcc4
+- Add the FBX library to the set(APP_LIBRARIES {...} )
+  * Example: fbxsdk-2013.3-static
+- Add the FBX library to the library to the add_definitions(-l...) section of the CMakeLists.txt
+  * Example -lfbxsdk-2013.3-static
+- Build gameplay-encoder via main cmake .. in build then make.
+
 ## Bundle File Format
 The gameplay bundle file format is well defined in the gameplay-encoder/gameplay-bundle.txt file.
 

+ 1 - 1
gameplay-encoder/gameplay-bundle.txt

@@ -153,7 +153,7 @@ Reference
 5->AnimationChannel
                 targetId                string
                 targetAttribute         uint
-                keyTimes                unsigned long[]  (milliseconds)
+                keyTimes                uint[]  (milliseconds)
                 values                  float[]
                 tangents_in             float[]
                 tangents_out            float[]

+ 7 - 5
gameplay-encoder/gameplay-encoder.vcxproj

@@ -30,6 +30,7 @@
     <ClCompile Include="src\Glyph.cpp" />
     <ClCompile Include="src\GPBDecoder.cpp" />
     <ClCompile Include="src\Animations.cpp" />
+    <ClCompile Include="src\Heightmap.cpp" />
     <ClCompile Include="src\Light.cpp" />
     <ClCompile Include="src\main.cpp" />
     <ClCompile Include="src\Material.cpp" />
@@ -74,6 +75,7 @@
     <ClInclude Include="src\Glyph.h" />
     <ClInclude Include="src\GPBDecoder.h" />
     <ClInclude Include="src\Animations.h" />
+    <ClInclude Include="src\Heightmap.h" />
     <ClInclude Include="src\Light.h" />
     <ClInclude Include="src\Material.h" />
     <ClInclude Include="src\MaterialParameter.h" />
@@ -89,6 +91,7 @@
     <ClInclude Include="src\ReferenceTable.h" />
     <ClInclude Include="src\Scene.h" />
     <ClInclude Include="src\StringUtil.h" />
+    <ClInclude Include="src\Thread.h" />
     <ClInclude Include="src\Transform.h" />
     <ClInclude Include="src\TTFFontEncoder.h" />
     <ClInclude Include="src\Vector2.h" />
@@ -156,12 +159,12 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalLibraryDirectories>../external-deps/freetype2/lib/win32;../external-deps/collada-dom/lib/win32;../external-deps/libpng/lib/win32;../external-deps/zlib/lib/win32</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>../external-deps/freetype2/lib/windows;../external-deps/collada-dom/lib/windows;../external-deps/libpng/lib/windows;../external-deps/zlib/lib/windows</AdditionalLibraryDirectories>
       <AdditionalDependencies>freetype245.lib;libcollada14dom22-d.lib;libpng14.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <IgnoreSpecificDefaultLibraries>MSVCRT</IgnoreSpecificDefaultLibraries>
     </Link>
     <PostBuildEvent>
-      <Command>copy /Y "$(ProjectDir)..\bin\win32\*.dll" "$(TargetDir)"</Command>
+      <Command>copy /Y "$(ProjectDir)..\bin\windows\*.dll" "$(TargetDir)"</Command>
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -181,13 +184,12 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalDependencies>freetype245.lib;libcollada14dom22-d.lib;libpng14.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>../external-deps/freetype2/lib/win32;../external-deps/collada-dom/lib/win32;../external-deps/libpng/lib/win32;../external-deps/zlib/lib/win32</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>../external-deps/freetype2/lib/windows;../external-deps/collada-dom/lib/windows;../external-deps/libpng/lib/windows;../external-deps/zlib/lib/windows</AdditionalLibraryDirectories>
       <IgnoreSpecificDefaultLibraries>
       </IgnoreSpecificDefaultLibraries>
     </Link>
     <PostBuildEvent>
-      <Command>copy /Y "$(ProjectDir)..\bin\win32\*.dll" "$(TargetDir)"
-</Command>
+      <Command>copy /Y "$(ProjectDir)..\bin\windows\*.dll" "$(TargetDir)"</Command>
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

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

@@ -127,6 +127,9 @@
     <ClCompile Include="src\Curve.cpp">
       <Filter>src</Filter>
     </ClCompile>
+    <ClCompile Include="src\Heightmap.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\VertexElement.h">
@@ -252,6 +255,12 @@
     <ClInclude Include="src\Curve.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="src\Thread.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Heightmap.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="src\Vector2.inl">

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

@@ -4,10 +4,10 @@
     <LocalDebuggerCommandArguments>
     </LocalDebuggerCommandArguments>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
-    <LocalDebuggerEnvironment>PATH=%PATH%;../bin/win32;</LocalDebuggerEnvironment>
+    <LocalDebuggerEnvironment>PATH=%PATH%;../bin/windows;</LocalDebuggerEnvironment>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LocalDebuggerEnvironment>PATH=%PATH%;../bin/win32;</LocalDebuggerEnvironment>
+    <LocalDebuggerEnvironment>PATH=%PATH%;../bin/windows;</LocalDebuggerEnvironment>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
 </Project>

+ 28 - 0
gameplay-encoder/gameplay-encoder.xcodeproj/project.pbxproj

@@ -7,6 +7,9 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		4228A3FF1620A5A300955433 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4228A3FE1620A5A300955433 /* Cocoa.framework */; };
+		4228A4011620A5EC00955433 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4228A4001620A5EC00955433 /* SystemConfiguration.framework */; };
+		4228A4031620A63F00955433 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4228A4021620A63F00955433 /* libiconv.dylib */; };
 		42475D7C14720ECE00610A6A /* libdom.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42475D7B14720ECE00610A6A /* libdom.a */; };
 		4251B12C152D044B002F6199 /* Curve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4251B128152D044B002F6199 /* Curve.cpp */; };
 		42783423148D6F7500A6E27F /* FBXSceneEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4278341E148D6F7500A6E27F /* FBXSceneEncoder.cpp */; };
@@ -58,6 +61,7 @@
 		42D277591472EFA700D867A4 /* libpcre.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42D277571472EFA700D867A4 /* libpcre.a */; };
 		42D2775A1472EFA700D867A4 /* libpcrecpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42D277581472EFA700D867A4 /* libpcrecpp.a */; };
 		5BCD0643152CFC3C0071FAB5 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BCD0642152CFC3C0071FAB5 /* libpng.a */; };
+		F18DCD0615D554B800DB35DB /* Heightmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F18DCD0315D554B800DB35DB /* Heightmap.cpp */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -73,6 +77,9 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+		4228A3FE1620A5A300955433 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+		4228A4001620A5EC00955433 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+		4228A4021620A63F00955433 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = ../../../../../usr/lib/libiconv.dylib; sourceTree = "<group>"; };
 		42475CE6147208A000610A6A /* gameplay-encoder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "gameplay-encoder"; sourceTree = BUILT_PRODUCTS_DIR; };
 		42475D7B14720ECE00610A6A /* libdom.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdom.a; path = "../external-deps/collada-dom/lib/macosx/libdom.a"; sourceTree = "<group>"; };
 		4251B128152D044B002F6199 /* Curve.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Curve.cpp; path = src/Curve.cpp; sourceTree = SOURCE_ROOT; };
@@ -172,6 +179,9 @@
 		42D277571472EFA700D867A4 /* libpcre.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpcre.a; path = "../external-deps/pcre/lib/macosx/libpcre.a"; sourceTree = "<group>"; };
 		42D277581472EFA700D867A4 /* libpcrecpp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpcrecpp.a; path = "../external-deps/pcre/lib/macosx/libpcrecpp.a"; sourceTree = "<group>"; };
 		5BCD0642152CFC3C0071FAB5 /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/macosx/libpng.a"; sourceTree = "<group>"; };
+		F18DCD0315D554B800DB35DB /* Heightmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Heightmap.cpp; path = src/Heightmap.cpp; sourceTree = SOURCE_ROOT; };
+		F18DCD0415D554B800DB35DB /* Heightmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Heightmap.h; path = src/Heightmap.h; sourceTree = SOURCE_ROOT; };
+		F18DCD0515D554B800DB35DB /* Thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Thread.h; path = src/Thread.h; sourceTree = SOURCE_ROOT; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -187,17 +197,30 @@
 				42C8EE391472DAA300E43619 /* libz.dylib in Frameworks */,
 				42C8EE371472D7E700E43619 /* libxml2.dylib in Frameworks */,
 				5BCD0643152CFC3C0071FAB5 /* libpng.a in Frameworks */,
+				4228A3FF1620A5A300955433 /* Cocoa.framework in Frameworks */,
+				4228A4011620A5EC00955433 /* SystemConfiguration.framework in Frameworks */,
+				4228A4031620A63F00955433 /* libiconv.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		4228A3FD1620A58000955433 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				4228A4001620A5EC00955433 /* SystemConfiguration.framework */,
+				4228A3FE1620A5A300955433 /* Cocoa.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 		42475CDB147208A000610A6A = {
 			isa = PBXGroup;
 			children = (
 				42475CE9147208A000610A6A /* src */,
 				427D4F44147DC9080076760E /* Libraries */,
+				4228A3FD1620A58000955433 /* Frameworks */,
 				42475CE7147208A000610A6A /* Products */,
 			);
 			sourceTree = "<group>";
@@ -213,6 +236,9 @@
 		42475CE9147208A000610A6A /* src */ = {
 			isa = PBXGroup;
 			children = (
+				F18DCD0315D554B800DB35DB /* Heightmap.cpp */,
+				F18DCD0415D554B800DB35DB /* Heightmap.h */,
+				F18DCD0515D554B800DB35DB /* Thread.h */,
 				42C8EDB714724CD700E43619 /* Animation.cpp */,
 				42C8EDB814724CD700E43619 /* Animation.h */,
 				42C8EDB914724CD700E43619 /* AnimationChannel.cpp */,
@@ -319,6 +345,7 @@
 				42C8EE361472D7E700E43619 /* libxml2.dylib */,
 				42C8EE341472B60100E43619 /* libfreetype.a */,
 				42475D7B14720ECE00610A6A /* libdom.a */,
+				4228A4021620A63F00955433 /* libiconv.dylib */,
 			);
 			name = Libraries;
 			sourceTree = "<group>";
@@ -416,6 +443,7 @@
 				4283905914896E6C00E2B2F5 /* BoundingVolume.cpp in Sources */,
 				42783423148D6F7500A6E27F /* FBXSceneEncoder.cpp in Sources */,
 				4251B12C152D044B002F6199 /* Curve.cpp in Sources */,
+				F18DCD0615D554B800DB35DB /* Heightmap.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 12 - 63
gameplay-encoder/src/AnimationChannel.cpp

@@ -68,27 +68,27 @@ unsigned int AnimationChannel::getTargetAttribute() const
     return _targetAttrib;
 }
 
-const std::vector<float>& AnimationChannel::getKeyValues() const
+std::vector<float>& AnimationChannel::getKeyValues()
 {
     return _keyValues;
 }
 
-const std::vector<float>& AnimationChannel::getKeyTimes() const
+std::vector<float>& AnimationChannel::getKeyTimes()
 {
     return _keytimes;
 }
 
-const std::vector<float>& AnimationChannel::getTangentsIn() const
+std::vector<float>& AnimationChannel::getTangentsIn()
 {
     return _tangentsIn;
 }
 
-const std::vector<float>& AnimationChannel::getTangentsOut() const
+std::vector<float>& AnimationChannel::getTangentsOut()
 {
     return _tangentsOut;
 }
 
-const std::vector<unsigned int>& AnimationChannel::getInterpolationTypes() const
+std::vector<unsigned int>& AnimationChannel::getInterpolationTypes()
 {
     return _interpolations;
 }
@@ -130,6 +130,10 @@ void AnimationChannel::setInterpolations(const std::vector<unsigned int>& values
 
 void AnimationChannel::removeDuplicates()
 {
+    LOG(3, "      Removing duplicates for channel with target attribute: %u.\n", _targetAttrib);
+
+    int startCount = _keytimes.size();
+
     size_t propSize = Transform::getPropertySize(_targetAttrib);
 
     if (propSize > 1 && !_interpolations.empty() && _interpolations[0] == LINEAR)
@@ -167,64 +171,8 @@ void AnimationChannel::removeDuplicates()
             deleteRange(prevIndex+1, i, propSize);
         }
     }
-}
-
-void AnimationChannel::convertToQuaternion()
-{
-    if (_targetAttrib == Transform::ANIMATE_ROTATE_X ||
-        _targetAttrib == Transform::ANIMATE_ROTATE_Y ||
-        _targetAttrib == Transform::ANIMATE_ROTATE_Z)
-    {
-        std::vector<float> newKeyValues;
-        newKeyValues.resize(_keyValues.size() * 4);
-        const size_t count = _keyValues.size();
-
-        float x = _targetAttrib == Transform::ANIMATE_ROTATE_X ? 1.0f : 0.0f;
-        float y = _targetAttrib == Transform::ANIMATE_ROTATE_Y ? 1.0f : 0.0f;
-        float z = _targetAttrib == Transform::ANIMATE_ROTATE_Z ? 1.0f : 0.0f;
-        for (size_t i = 0; i < count; ++i)
-        {
-            size_t j = i << 2;
-            newKeyValues[j] = x;
-            newKeyValues[j+1] = y;
-            newKeyValues[j+2] = z;
-            newKeyValues[j+3] = _keyValues[i];
-        }
-        setKeyValues(newKeyValues);
-        setTargetAttribute(Transform::ANIMATE_ROTATE);
-    }
-}
 
-void AnimationChannel::convertToTransform()
-{
-    if (_targetAttrib == Transform::ANIMATE_ROTATE_X ||
-        _targetAttrib == Transform::ANIMATE_ROTATE_Y ||
-        _targetAttrib == Transform::ANIMATE_ROTATE_Z)
-    {
-        std::vector<float> newKeyValues;
-        newKeyValues.resize(_keyValues.size() * 10);
-        const size_t count = _keyValues.size();
-
-        float x = _targetAttrib == Transform::ANIMATE_ROTATE_X ? 1.0f : 0.0f;
-        float y = _targetAttrib == Transform::ANIMATE_ROTATE_Y ? 1.0f : 0.0f;
-        float z = _targetAttrib == Transform::ANIMATE_ROTATE_Z ? 1.0f : 0.0f;
-        for (size_t i = 0; i < count; ++i)
-        {
-            size_t j = i << 2;
-            newKeyValues[j+0] = 1.0f;
-            newKeyValues[j+1] = 1.0f;
-            newKeyValues[j+2] = 1.0f;
-            newKeyValues[j+3] = x;
-            newKeyValues[j+4] = y;
-            newKeyValues[j+5] = z;
-            newKeyValues[j+6] = _keyValues[i];
-            newKeyValues[j+7] = 0.0f;
-            newKeyValues[j+8] = 0.0f;
-            newKeyValues[j+9] = 0.0f;
-        }
-        setKeyValues(newKeyValues);
-        setTargetAttribute(Transform::ANIMATE_SCALE_ROTATE_TRANSLATE);
-    }
+    LOG(3, "      Removed %d duplicate keyframes from channel.\n", startCount- _keytimes.size());
 }
 
 unsigned int AnimationChannel::getInterpolationType(const char* str)
@@ -275,8 +223,9 @@ unsigned int AnimationChannel::getInterpolationType(const char* str)
 void AnimationChannel::deleteRange(size_t begin, size_t end, size_t propSize)
 {
     assert(end > begin);
+
     // delete range
-    printf("delete %lu to %lu\n", begin, end - 1);
+    LOG(4, "        delete %lu to %lu\n", begin, end - 1);
 
     std::vector<float>::iterator a = _keyValues.begin() + begin * propSize;
     std::vector<float>::iterator b = _keyValues.begin() + end * propSize;

+ 5 - 8
gameplay-encoder/src/AnimationChannel.h

@@ -54,20 +54,17 @@ public:
     void setInterpolations(const std::vector<unsigned int>& values);
 
     unsigned int getTargetAttribute() const;
-    const std::vector<float>& getKeyValues() const;
-    const std::vector<float>& getKeyTimes() const;
-    const std::vector<float>& getTangentsIn() const;
-    const std::vector<float>& getTangentsOut() const;
-    const std::vector<unsigned int>& getInterpolationTypes() const;
+    std::vector<float>& getKeyValues();
+    std::vector<float>& getKeyTimes();
+    std::vector<float>& getTangentsIn();
+    std::vector<float>& getTangentsOut();
+    std::vector<unsigned int>& getInterpolationTypes();
 
     /**
      * Removes duplicate key frames from the animation channel.
      */
     void removeDuplicates();
 
-    void convertToQuaternion();
-    void convertToTransform();
-
     /**
      * Returns the interpolation type value for the given string or zero if not valid.
      * Example: "LINEAR" returns AnimationChannel::LINEAR

+ 12 - 8
gameplay-encoder/src/Base.h

@@ -10,6 +10,7 @@
 #include <cmath>
 #include <cfloat>
 #include <ctime>
+#include <cstring>
 #include <iostream>
 #include <fstream>
 #include <string>
@@ -24,6 +25,7 @@
 
 // Collada includes
 #include <dae.h>
+#include <dom.h>
 #include <dae/daeSIDResolver.h>
 #include <dae/domAny.h>
 #include <dom/domCOLLADA.h>
@@ -86,7 +88,8 @@ void fillArray(float values[], float value, size_t length);
  */
 std::string getBaseName(const std::string& filepath);
 
-#define ISZERO(x) (fabs(x) < 0.000001f)
+#define ISZERO(x) (fabs(x) < MATH_EPSILON)
+#define ISONE(x) ((x - 1.0f) < MATH_EPSILON)
 
 // Object deletion macro
 #define SAFE_DELETE(x) \
@@ -96,13 +99,14 @@ std::string getBaseName(const std::string& filepath);
         x = NULL; \
     }
 
-#ifdef NDEBUG
-#define DEBUGPRINT(x)
-#define DEBUGPRINT_VARG(x, ...)
-#else
-#define DEBUGPRINT(x)  printf(x)
-#define DEBUGPRINT_VARG(x, ...) printf(x, __VA_ARGS__)
-#endif
+extern int __logVerbosity;
+
+// Logging macro (level is verbosity level, 1-4).
+#define LOG(level, ...) \
+    { \
+        if (level <= __logVerbosity) \
+            printf(__VA_ARGS__); \
+    }
 
 }
 

+ 9 - 0
gameplay-encoder/src/BoundingVolume.cpp

@@ -92,6 +92,15 @@ void BoundingVolume::transform(const Matrix& m)
 
 void BoundingVolume::merge(const BoundingVolume& v)
 {
+    // Merge the box portion
+    min.x = std::min(min.x, v.min.x);
+    min.y = std::min(min.y, v.min.y);
+    min.z = std::min(min.z, v.min.z);
+    max.x = std::max(max.x, v.max.x);
+    max.y = std::max(max.y, v.max.y);
+    max.z = std::max(max.z, v.max.z);
+
+    // Merge the sphere portion
     // Calculate the distance between the two centers.
     float vx = center.x - v.center.x;
     float vy = center.y - v.center.y;

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

@@ -5,6 +5,7 @@ namespace gameplay
 {
 
 Camera::Camera(void) :
+    _cameraType(CameraPerspective), 
     _fieldOfView(0.0f),
     _aspectRatio(0.0f),
     _nearPlane(0.0f),

+ 1 - 1
gameplay-encoder/src/Curve.cpp

@@ -1343,4 +1343,4 @@ int Curve::getInterpolationType(const char* curveId)
     return -1;
 }
 
-}
+}

+ 1 - 1
gameplay-encoder/src/DAEOptimizer.cpp

@@ -19,7 +19,7 @@ void DAEOptimizer::combineAnimations(const std::string& nodeId, const std::strin
 
     daeSIDResolver resolver(_dom, nodeId.c_str());
     daeElement* element = resolver.getElement();
-    if (element && element->getElementType() == COLLADA_TYPE::NODE)
+    if (element && element->typeID() == COLLADA_TYPE::NODE)
     {
         domNodeRef node = daeSafeCast<domNode>(resolver.getElement());
         getAnimationChannels(node, channels);

+ 78 - 84
gameplay-encoder/src/DAESceneEncoder.cpp

@@ -63,7 +63,7 @@ void DAESceneEncoder::optimizeCOLLADA(const EncoderArguments& arguments, domCOLL
             // Ask the user if they want to group animations automatically.
             if (promptUserGroupAnimations())
             {
-                printf("Grouping animations...\n");
+                LOG(2, "Grouping animations...\n");
 
                 DAEOptimizer optimizer(dom);
                 begin();
@@ -87,7 +87,7 @@ void DAESceneEncoder::optimizeCOLLADA(const EncoderArguments& arguments, domCOLL
     {
         if (!_collada->writeTo(arguments.getFilePath(), arguments.getDAEOutputPath()))
         {
-            fprintf(stderr,"Error: COLLADA failed to write the dom for file: %s\n", arguments.getDAEOutputPath().c_str());
+            LOG(1, "Error: COLLADA failed to write the dom for file: %s\n", arguments.getDAEOutputPath().c_str());
         }
     }
 }
@@ -264,11 +264,11 @@ void DAESceneEncoder::write(const std::string& filepath, const EncoderArguments&
     // Load the collada document
     _collada = new DAE();
     begin();
-    _dom = _collada->open(filepath);
+    _dom = (domCOLLADA*)_collada->open(filepath);
     end("Open file");
     if (!_dom)
     {
-        fprintf(stderr,"Error: COLLADA failed to open file: %s\n", filepath.c_str());
+        LOG(1, "Error: COLLADA failed to open file: %s\n", filepath.c_str());
         if (_collada)
         {
             delete _collada;
@@ -287,10 +287,9 @@ void DAESceneEncoder::write(const std::string& filepath, const EncoderArguments&
 
     // Find the <visual_scene> element within the <scene>
     const domCOLLADA::domSceneRef& domScene = _dom->getScene();
-    daeElement* scene = NULL;
     if (domScene && domScene->getInstance_visual_scene())
     {
-        scene = getVisualScene(domScene);
+        daeElement* scene = getVisualScene(domScene);
         if (scene)
         {
             if (nodeId == NULL)
@@ -314,23 +313,23 @@ void DAESceneEncoder::write(const std::string& filepath, const EncoderArguments&
                     }
                     else
                     {
-                        fprintf(stderr,"COLLADA File loaded to the dom, but failed to load node %s.\n", nodeId);
+                        LOG(1, "COLLADA File loaded to the dom, but failed to load node %s.\n", nodeId);
                     }
                 }
                 else
                 {
-                    fprintf(stderr,"COLLADA File loaded to the dom, but node was not found with node ID %s.\n", nodeId);
+                    LOG(1, "COLLADA File loaded to the dom, but node was not found with node ID %s.\n", nodeId);
                 }
             }
         }
         else
         {
-             fprintf(stderr,"COLLADA File loaded to the dom, but query for the dom assets failed.\n");
+             LOG(1, "COLLADA File loaded to the dom, but query for the dom assets failed.\n");
         }
     }
     else
     {
-        fprintf(stderr, "COLLADA File loaded to the dom, but missing <visual_scene>.\n");
+        LOG(1, "COLLADA File loaded to the dom, but missing <visual_scene>.\n");
     }
     
     // The animations should be loaded last
@@ -350,20 +349,20 @@ void DAESceneEncoder::write(const std::string& filepath, const EncoderArguments&
         {
             std::string path = outputFilePath.substr(0, pos);
             path.append(".xml");
-            fprintf(stderr, "Saving debug file: %s\n", path.c_str());
+            LOG(1, "Saving debug file: %s\n", path.c_str());
             if (!_gamePlayFile.saveText(path))
             {
-                fprintf(stderr,"Error writing text file: %s\n", path.c_str());
+                LOG(1, "Error writing text file: %s\n", path.c_str());
             }
         }
     }
     else
     {
-        fprintf(stderr, "Saving binary file: %s\n", outputFilePath.c_str());
+        LOG(1, "Saving binary file: %s\n", outputFilePath.c_str());
         begin();
         if (!_gamePlayFile.saveBinary(outputFilePath))
         {
-            fprintf(stderr,"Error writing binary file: %s\n", outputFilePath.c_str());
+            LOG(1, "Error writing binary file: %s\n", outputFilePath.c_str());
         }
         end("save binary");
     }
@@ -569,7 +568,7 @@ bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChann
             daeInt type = attributeElement->typeID();
             if (type == domRotate::ID())
             {
-                printf(TRANSFORM_WARNING_FORMAT, targetId, "Rotate", TRANSFORM_MESSAGE);
+                LOG(1, TRANSFORM_WARNING_FORMAT, targetId, "Rotate", TRANSFORM_MESSAGE);
                 return false;
                 /*
                 // <rotate>
@@ -610,7 +609,7 @@ bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChann
             }
             else if (type == domScale::ID())
             {
-                printf(TRANSFORM_WARNING_FORMAT, targetId, "Scale", TRANSFORM_MESSAGE);
+                LOG(1, TRANSFORM_WARNING_FORMAT, targetId, "Scale", TRANSFORM_MESSAGE);
                 return false;
                 /*
                 // <scale>
@@ -635,7 +634,7 @@ bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChann
             }
             else if (type == domTranslate::ID())
             {
-                printf(TRANSFORM_WARNING_FORMAT, targetId, "Translate", TRANSFORM_MESSAGE);
+                LOG(1, TRANSFORM_WARNING_FORMAT, targetId, "Translate", TRANSFORM_MESSAGE);
                 return false;
                 /*
                 // <translate>
@@ -719,7 +718,7 @@ void DAESceneEncoder::end(const char* str)
 {
     #ifdef ENCODER_PRINT_TIME
     clock_t time = clock() - _begin;
-    fprintf(stderr,"%5d %s\n", time, str);
+    LOG(1, "%5d %s\n", time, str);
     #endif
 }
 
@@ -890,7 +889,7 @@ void DAESceneEncoder::calcTransform(domNode* domNode, Matrix& dstTransform)
     for (size_t i = 0; i < childCount; ++i)
     {
         daeElementRef childElement = children[i];
-        switch (childElement->getElementType())
+        switch (childElement->typeID())
         {
             case COLLADA_TYPE::TRANSLATE:
             {
@@ -936,10 +935,10 @@ void DAESceneEncoder::calcTransform(domNode* domNode, Matrix& dstTransform)
                 break;
             }
             case COLLADA_TYPE::SKEW:
-                warning("Skew transform found but not supported.");
+                LOG(1, "Warning: Skew transform found but not supported.\n");
                 break;
             case COLLADA_TYPE::LOOKAT:
-                warning("Lookat transform found but not supported.");
+                LOG(1, "Warning: Lookat transform found but not supported.\n");
                 break;
             default:
                 break;
@@ -1024,7 +1023,7 @@ void DAESceneEncoder::loadGeometryInstance(const domNode* n, Node* node)
         }
         else
         {
-            warning(std::string("Failed to resolve geometry url: ") + geometryURI.getURI());
+            LOG(1, "Failed to resolve geometry url: %s\n", geometryURI.getURI());
         }
     }
 }
@@ -1287,7 +1286,7 @@ void DAESceneEncoder::loadSkeleton(domNode* rootNode, MeshSkin* skin)
         domNode* topLevelParent = rootNode;
         while (
             topLevelParent->getParent() &&
-            topLevelParent->getParent()->getElementType() == COLLADA_TYPE::NODE &&
+            topLevelParent->getParent()->typeID() == COLLADA_TYPE::NODE &&
             _gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID()) == NULL)
         {
             topLevelParent = (domNode*)topLevelParent->getParent();
@@ -1296,7 +1295,7 @@ void DAESceneEncoder::loadSkeleton(domNode* rootNode, MeshSkin* skin)
         // Is the parent of this node loaded yet?
         Node* parentNode = NULL;
         if (topLevelParent->getParent() &&
-            topLevelParent->getParent()->getElementType() == COLLADA_TYPE::NODE &&
+            topLevelParent->getParent()->typeID() == COLLADA_TYPE::NODE &&
             _gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID()) != NULL)
         {
             parentNode = (Node*)_gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID());
@@ -1317,7 +1316,7 @@ void DAESceneEncoder::loadSkeleton(domNode* rootNode, MeshSkin* skin)
     // Resolve and set joints array for skin
     std::vector<Node*> _joints;
     const std::vector<std::string>& jointNames = skin->getJointNames();
-    for (std::vector<std::string>::const_iterator i = jointNames.begin(); i != jointNames.end(); i++)
+    for (std::vector<std::string>::const_iterator i = jointNames.begin(); i != jointNames.end(); ++i)
     {
         Object* obj = _gamePlayFile.getFromRefTable(*i);
         if (obj && obj->getTypeId() == Object::NODE_ID)
@@ -1369,11 +1368,11 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
 
             // Go through the joint list and convert them from sid to id because the sid information is
             // lost when converting to the gameplay binary format.
-            for (std::vector<std::string>::iterator i = list.begin(); i != list.end(); i++)
+            for (std::vector<std::string>::iterator i = list.begin(); i != list.end(); ++i)
             {
                 daeSIDResolver resolver(source->getDocument()->getDomRoot(), i->c_str());
                 daeElement* element = resolver.getElement();
-                if (element && element->getElementType() == COLLADA_TYPE::NODE)
+                if (element && element->typeID() == COLLADA_TYPE::NODE)
                 {
                     domNodeRef node = daeSafeCast<domNode>(element);
                     const char* nodeId = node->getId();
@@ -1388,7 +1387,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
             jointCount = list.size();
             _jointInverseBindPoseMatrices.reserve(jointCount);
             unsigned int j = 0;
-            for (std::vector<std::string>::const_iterator i = list.begin(); i != list.end(); i++)
+            for (std::vector<std::string>::const_iterator i = list.begin(); i != list.end(); ++i)
             {
                 _jointLookupTable[*i] = j++;
             }
@@ -1399,7 +1398,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     // Make sure we have some joints
     if (jointCount == 0)
     {
-        warning("No joints found for skin: ");
+        LOG(1, "Warning: No joints found for skin: %s\n", skinElement->getID());
         return NULL;
     }
 
@@ -1572,7 +1571,7 @@ Model* DAESceneEncoder::loadGeometry(const domGeometry* geometry, const domBind_
     const domMesh* meshElement = geometry->getMesh();
     if (meshElement == NULL)
     {
-        warning(std::string("No mesh found for geometry: ") + geometry->getId());
+        LOG(1, "Warning: No mesh found for geometry: %s\n", geometry->getId());
         return NULL;
     }
 
@@ -1599,7 +1598,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
     // Ensure the data is exported as triangles.
     if (trianglesArrayCount == 0)
     {
-        warning(std::string("Geometry mesh has no triangles: ") + geometryId);
+        LOG(1, "Warning: Geometry mesh has no triangles: %s\n", geometryId.c_str());
         return NULL;
     }
 
@@ -1611,7 +1610,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
     }
     mesh = new Mesh();
     mesh->setId(geometryId.c_str());
-    
+
     std::vector<DAEPolygonInput*> polygonInputs;
 
     // Quickly just go through each triangles array and make sure they have the same number of inputs
@@ -1650,7 +1649,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                         int type = getVertexUsageType(semantic);
                         if (type == -1)
                         {
-                            warning(std::string("Vertex semantic (") + semantic + ") is invalid/unsupported for geometry mesh: " + geometryId);
+                            LOG(1, "Warning: Vertex semantic (%s) is invalid/unsupported for geometry mesh: %s\n", semantic.c_str(), geometryId.c_str());
                         }
 
                         DAEPolygonInput* polygonInput = new DAEPolygonInput();
@@ -1669,7 +1668,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                     int type = getVertexUsageType(semantic);
                     if (type == -1)
                     {
-                        warning(std::string("Semantic (") + semantic + ") is invalid/unsupported for geometry mesh: " + geometryId);
+                        LOG(1, "Warning: Semantic (%s) is invalid/unsupported for geometry mesh: %s\n", semantic.c_str(), geometryId.c_str());
                         break;
                     }
                     if (type == TEXCOORD0)
@@ -1709,7 +1708,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                 {
                     delete polygonInputs[j];
                 }
-                warning(std::string("Triangles do not all have the same number of input sources for geometry mesh: ") + geometryId);
+                LOG(1, "Warning: Triangles do not all have the same number of input sources for geometry mesh: %s\n", geometryId.c_str());
                 return NULL;
             }
             else
@@ -1819,7 +1818,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                                 break;
                             case 'b':
                             case 'B':
-                                vertex.diffuse.z = (float)source.get(index + i); // blue
+                                vertex.diffuse.z = (float)source.get(index+ i ); // blue
                                 break;
                             case 'a':
                             case 'A':
@@ -1849,34 +1848,43 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                 break;
 
             case TEXCOORD0:
-                vertex.hasTexCoord = true;
-                if (polygonInputs[k]->accessor)
-                {
-                    // TODO: This assumes (s, t) are first
-                    unsigned int stride = (unsigned int)polygonInputs[k]->accessor->getStride();
-                    if (polyIndexInt < 0)
-                    {
-                        unsigned int i = (unsigned int)((int)polygonInputs[k]->accessor->getCount()) + polyIndexInt;
-                        vertex.texCoord.x = (float)source.get(i * stride);
-                        vertex.texCoord.y = (float)source.get(i * stride + 1);
-                    }
-                    else
-                    {
-                        vertex.texCoord.x = (float)source.get(polyIndex * stride);
-                        vertex.texCoord.y = (float)source.get(polyIndex * stride + 1);
-                    }
-                }
-                else
+            case TEXCOORD1:
+            case TEXCOORD2:
+            case TEXCOORD3:
+            case TEXCOORD4:
+            case TEXCOORD5:
+            case TEXCOORD6:
+            case TEXCOORD7:
                 {
-                    vertex.texCoord.x = (float)source.get(polyIndex * 2);
-                    vertex.texCoord.y = (float)source.get(polyIndex * 2 + 1);
+                    unsigned int index = polygonInputs[k]->type - TEXCOORD0;
+                    //for (unsigned int i = 0; i < uvSetCount; ++i)
+                    //{
+                        vertex.hasTexCoord[index] = true;
+                        if (polygonInputs[k]->accessor)
+                        {
+                            // TODO: This assumes (s, t) are first
+                            unsigned int stride = (unsigned int)polygonInputs[k]->accessor->getStride();
+                            if (polyIndexInt < 0)
+                            {
+                                unsigned int i = (unsigned int)((int)polygonInputs[k]->accessor->getCount()) + polyIndexInt;
+                                vertex.texCoord[index].x = (float)source.get(i * stride);
+                                vertex.texCoord[index].y = (float)source.get(i * stride + 1);
+                            }
+                            else
+                            {
+                                vertex.texCoord[index].x = (float)source.get(polyIndex * stride);
+                                vertex.texCoord[index].y = (float)source.get(polyIndex * stride + 1);
+                            }
+                        }
+                        else
+                        {
+                            vertex.texCoord[index].x = (float)source.get(polyIndex * 2);
+                            vertex.texCoord[index].y = (float)source.get(polyIndex * 2 + 1);
+                        }
+                    //}
                 }
                 break;
 
-            case TEXCOORD1:
-                // TODO
-                break;
-
             default:
                 break;
             }
@@ -1909,13 +1917,6 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
         // Add our new subset for the mesh.
         mesh->addMeshPart(subset);
     }
-    
-    bool hasNormals = mesh->vertices[0].hasNormal;
-    bool hasDiffuses = mesh->vertices[0].hasDiffuse;
-    bool hasTangents = mesh->vertices[0].hasTangent;
-    bool hasBinormals = mesh->vertices[0].hasBinormal;
-    bool hasTexCoords = mesh->vertices[0].hasTexCoord;
-    bool hasWeights = mesh->vertices[0].hasWeights;
 
     // The order that the vertex elements are add to the list matters.
     // It should be the same order as how the Vertex data is written.
@@ -1924,32 +1925,35 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
     mesh->addVetexAttribute(POSITION, Vertex::POSITION_COUNT);
     
     // Normals
-    if (hasNormals)
+    if (mesh->vertices[0].hasNormal)
     {
         mesh->addVetexAttribute(NORMAL, Vertex::NORMAL_COUNT);
     }
     // Tangents
-    if (hasTangents)
+    if (mesh->vertices[0].hasTangent)
     {
         mesh->addVetexAttribute(TANGENT, Vertex::TANGENT_COUNT);
     }
     // Binormals
-    if (hasBinormals)
+    if (mesh->vertices[0].hasBinormal)
     {
         mesh->addVetexAttribute(BINORMAL, Vertex::BINORMAL_COUNT);
     }
     // Texture Coordinates
-    if (hasTexCoords)
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
     {
-        mesh->addVetexAttribute(TEXCOORD0, Vertex::TEXCOORD_COUNT);
+        if (mesh->vertices[0].hasTexCoord[i])
+        {
+            mesh->addVetexAttribute(TEXCOORD0 + i, Vertex::TEXCOORD_COUNT);
+        }
     }
     // Diffuse Color
-    if (hasDiffuses)
+    if (mesh->vertices[0].hasDiffuse)
     {
         mesh->addVetexAttribute(COLOR, Vertex::DIFFUSE_COUNT);
     }
     // Skinning BlendWeights BlendIndices
-    if (hasWeights)
+    if (mesh->vertices[0].hasWeights)
     {
         mesh->addVetexAttribute(BLENDWEIGHTS, Vertex::BLEND_WEIGHTS_COUNT);
         mesh->addVetexAttribute(BLENDINDICES, Vertex::BLEND_INDICES_COUNT);
@@ -1959,16 +1963,6 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
     return mesh;
 }
 
-void DAESceneEncoder::warning(const std::string& message)
-{
-    printf("Warning: %s\n", message.c_str());
-}
-
-void DAESceneEncoder::warning(const char* message)
-{
-    printf("Warning: %s\n", message);
-}
-
 int DAESceneEncoder::getVertexUsageType(const std::string& semantic)
 {
     if (semantic.length() > 0)

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

@@ -156,9 +156,6 @@ private:
      */
     void calcTransform(domNode* domNode, Matrix& dstTransform);
 
-    void warning(const std::string& message);
-    void warning(const char* message);
-
     /**
      * Loads the target data into the animation from the given channel's target.
      * Example: <channel target="Cube/location.X" />

+ 17 - 17
gameplay-encoder/src/DAEUtil.cpp

@@ -54,7 +54,7 @@ void getAnimationChannels(const domNodeRef& node, std::list<domChannelRef>& chan
     for (size_t i = 0; i < childCount; ++i)
     {
         daeElementRef childElement = children[i];
-        if (childElement->getElementType() == COLLADA_TYPE::NODE)
+        if (childElement->typeID() == COLLADA_TYPE::NODE)
         {
             domNodeRef childNode = daeSafeCast<domNode>(childElement);
             getAnimationChannels(childNode, channels);
@@ -115,7 +115,7 @@ void getJointNames(const domSkin* skin, std::vector<std::string>& list)
 domSource* getInputSource(const domChannelRef& channel)
 {
     daeElement* element = channel->getSource().getElement();
-    if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
+    if (element && element->typeID() == COLLADA_TYPE::SAMPLER)
     {
         domSampler* sampler = daeSafeCast<domSampler>(element);
         const domInputLocal_Array& inputArray = sampler->getInput_array();
@@ -126,7 +126,7 @@ domSource* getInputSource(const domChannelRef& channel)
             if (strcmp(input->getSemantic(), "INPUT") == 0)
             {
                 daeElement* e = input->getSource().getElement();
-                if (e && e->getElementType() == COLLADA_TYPE::SOURCE)
+                if (e && e->typeID() == COLLADA_TYPE::SOURCE)
                 {
                     domSource* source = daeSafeCast<domSource>(e);
                     assert(source);
@@ -142,7 +142,7 @@ const domSamplerRef getSampler(const domChannelRef& channel)
 {
     const domURIFragmentType& uri = channel->getSource();
     daeElementRef element = uri.getElement();
-    if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
+    if (element && element->typeID() == COLLADA_TYPE::SAMPLER)
     {
         const domSamplerRef sampler = daeSafeCast<domSampler>(element);
         return sampler;
@@ -150,7 +150,7 @@ const domSamplerRef getSampler(const domChannelRef& channel)
     // resolve the source manually by searching for the sampler in the animation that the channel is a child of.
     const std::string& id = uri.id();
     const daeElementRef& parent = channel->getParent();
-    if (parent && parent->getElementType() == COLLADA_TYPE::ANIMATION)
+    if (parent && parent->typeID() == COLLADA_TYPE::ANIMATION)
     {
         const domAnimationRef animation = daeSafeCast<domAnimation>(parent);
         
@@ -172,7 +172,7 @@ const domSourceRef getSource(const domInputLocalRef& inputLocal, const domAnimat
 {
     const domURIFragmentType& uri = inputLocal->getSource();
     daeElementRef element = uri.getElement();
-    if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
+    if (element && element->typeID() == COLLADA_TYPE::SAMPLER)
     {
         const domSourceRef source = daeSafeCast<domSource>(element);
         return source;
@@ -205,7 +205,7 @@ const domName_arrayRef getSourceNameArray(const domSourceRef& source)
     for (size_t i = 0; i < childCount; ++i)
     {
         const daeElementRef element = children.get(i);
-        if (element->getElementType() == COLLADA_TYPE::NAME_ARRAY)
+        if (element->typeID() == COLLADA_TYPE::NAME_ARRAY)
         {
             return daeSafeCast<domName_array>(element);
         }
@@ -229,7 +229,7 @@ const domInstance_controller::domSkeletonRef getSkeleton(const domInstance_contr
     // Find the skeleton element that points to the root most node.
     const domInstance_controller::domSkeletonRef& currentSkeleton = skeletonArray.get(0);
     const daeElementRef element = currentSkeleton->getValue().getElement();
-    if (element && element->getElementType() == COLLADA_TYPE::NODE)
+    if (element && element->typeID() == COLLADA_TYPE::NODE)
     {
         domNode* node = daeSafeCast<domNode>(element);
         int index = 0;
@@ -237,7 +237,7 @@ const domInstance_controller::domSkeletonRef getSkeleton(const domInstance_contr
         do
         {
             daeElementRef parent = node->getParent();
-            if (parent && parent->getElementType() == COLLADA_TYPE::NODE)
+            if (parent && parent->typeID() == COLLADA_TYPE::NODE)
             {
                 domNodeRef parentNode = daeSafeCast<domNode>(parent);
                 int result = getIndex(skeletonArray, parentNode);
@@ -266,7 +266,7 @@ domNode* getRootJointNode(const domSkin* skin)
     getJointNames(skin, names);
     daeSIDResolver resolver(const_cast<domSkin*>(skin)->getDocument()->getDomRoot(), names[0].c_str());
     daeElement* element = resolver.getElement();
-    if (element && element->getElementType() == COLLADA_TYPE::NODE)
+    if (element && element->typeID() == COLLADA_TYPE::NODE)
     {
         domNode* node = daeSafeCast<domNode>(resolver.getElement());
         return node;
@@ -326,7 +326,7 @@ void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& an
             inputArray = sampler->getInput_array();
             const domInputLocalRef& input = inputArray.get(i);
             daeElementRef element = input->getSource().getElement();
-            if (element && element->getElementType() == COLLADA_TYPE::SOURCE)
+            if (element && element->typeID() == COLLADA_TYPE::SOURCE)
             {
                 domSourceRef source = daeSafeCast<domSource>(element);
                 assert(source);
@@ -355,7 +355,7 @@ int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, con
     {
         const domInstance_controller::domSkeletonRef& skeleton = skeletonArray.get(i);
         daeElementRef element = skeleton->getValue().getElement();
-        if (element->getElementType() == COLLADA_TYPE::NODE)
+        if (element->typeID() == COLLADA_TYPE::NODE)
         {
             domNodeRef targetNode = daeSafeCast<domNode>(element);
             if (nodeId.compare(targetNode->getId()) == 0)
@@ -395,7 +395,7 @@ void getAnimationChannels(const domAnimationRef& animationRef, const std::string
 domVisual_scene* getVisualScene(const domCOLLADA::domSceneRef& domScene)
 {
     daeElement* scene = domScene->getInstance_visual_scene()->getUrl().getElement();
-    if (scene->getElementType() == COLLADA_TYPE::VISUAL_SCENE)
+    if (scene->typeID() == COLLADA_TYPE::VISUAL_SCENE)
     {
         return static_cast<domVisual_scene*>(scene);
     }
@@ -425,7 +425,7 @@ domVisual_scene* getVisualScene(const domCOLLADA::domSceneRef& domScene)
 domNode* getParent(domNodeRef node)
 {
     daeElement* parent = node->getParent();
-    if (parent && parent->getElementType() == COLLADA_TYPE::NODE)
+    if (parent && parent->typeID() == COLLADA_TYPE::NODE)
     {
         domNodeRef parentNode = daeSafeCast<domNode>(parent);
         return parentNode.cast();
@@ -436,7 +436,7 @@ domNode* getParent(domNodeRef node)
 domAnimation* getAnimation(domChannelRef channel)
 {
     daeElement* parent = channel->getParent();
-    if (parent && parent->getElementType() == COLLADA_TYPE::ANIMATION)
+    if (parent && parent->typeID() == COLLADA_TYPE::ANIMATION)
     {
         domAnimationRef parentNode = daeSafeCast<domAnimation>(parent);
         return parentNode.cast();
@@ -538,11 +538,11 @@ void findChannelsTargetingJoints(const domSourceRef& source, std::list<domChanne
 {
     std::vector<std::string> jointNames;
     getJointNames(source, jointNames);
-    for (std::vector<std::string>::iterator i = jointNames.begin(); i != jointNames.end(); i++)
+    for (std::vector<std::string>::iterator i = jointNames.begin(); i != jointNames.end(); ++i)
     {
         daeSIDResolver resolver(source->getDocument()->getDomRoot(), i->c_str());
         daeElement* element = resolver.getElement();
-        if (element && element->getElementType() == COLLADA_TYPE::NODE)
+        if (element && element->typeID() == COLLADA_TYPE::NODE)
         {
             domNodeRef node = daeSafeCast<domNode>(element);
             nodes.push_back(node);

+ 93 - 39
gameplay-encoder/src/EncoderArguments.cpp

@@ -13,13 +13,15 @@ namespace gameplay
 
 static EncoderArguments* __instance;
 
+extern int __logVerbosity = 1;
+
 EncoderArguments::EncoderArguments(size_t argc, const char** argv) :
     _fontSize(0),
     _parseError(false),
     _fontPreview(false),
     _textOutput(false),
     _daeOutput(false),
-    _isHeightmapHighP(false)
+    _optimizeAnimations(false)
 {
     __instance = this;
 
@@ -135,7 +137,6 @@ bool EncoderArguments::containsGroupNodeId(const std::string& nodeId) const
 
 const std::string EncoderArguments::getAnimationId(const std::string& nodeId) const
 {
-    std::vector<std::string>::const_iterator it = find(_groupAnimationNodeId.begin(), _groupAnimationNodeId.end(), nodeId);
     for (size_t i = 0, size = _groupAnimationNodeId.size(); i < size; ++i)
     {
         if (_groupAnimationNodeId[i].compare(nodeId) == 0)
@@ -146,14 +147,9 @@ const std::string EncoderArguments::getAnimationId(const std::string& nodeId) co
     return "";
 }
 
-const std::vector<std::string>& EncoderArguments::getHeightmapNodeIds() const
-{
-    return _heightmapNodeIds;
-}
-
-bool EncoderArguments::isHeightmapHighP() const
+const std::vector<EncoderArguments::HeightmapOption>& EncoderArguments::getHeightmapOptions() const
 {
-    return _isHeightmapHighP;
+    return _heightmaps;
 }
 
 bool EncoderArguments::parseErrorOccured() const
@@ -176,26 +172,36 @@ bool EncoderArguments::fileExists() const
 
 void EncoderArguments::printUsage() const
 {
-    fprintf(stderr,"Usage: gameplay-encoder [options] <input filepath> <output filepath>\n\n");
-    fprintf(stderr,"Supported file extensions:\n");
-    fprintf(stderr,"  .dae\t(COLLADA)\n");
-    fprintf(stderr,"  .fbx\t(FBX)\n");
-    fprintf(stderr,"  .ttf\t(TrueType Font)\n");
-    fprintf(stderr,"\n");
-    fprintf(stderr,"COLLADA and FBX file options:\n");
-    fprintf(stderr,"  -i <id>\t\tFilter by node ID.\n");
-    fprintf(stderr,"  -t\t\t\tWrite text/xml.\n");
-    fprintf(stderr,"  -g <node id> <animation id>\n" \
-        "\t\t\tGroup all animation channels targeting the nodes into a new animation.\n");
-    fprintf(stderr,"  -h \"<node ids>\"\n" \
-        "\t\t\tList of nodes to generate heightmaps for.\n" \
-        "\t\t\tNode id list should be in quotes with a space between each id.\n" \
-        "\t\t\tHeightmaps will be saved in files named <nodeid>.png.\n" \
-        "\t\t\tFor 24-bit packed height data use -hp instead of -h.\n");
-    fprintf(stderr,"\n");
-    fprintf(stderr,"TTF file options:\n");
-    fprintf(stderr,"  -s <size of font>\tSize of the font.\n");
-    fprintf(stderr,"  -p\t\t\tOutput font preview.\n");
+    LOG(1, "Usage: gameplay-encoder [options] <input filepath> <output filepath>\n\n");
+    LOG(1, "Supported file extensions:\n");
+    LOG(1, "  .dae\t(COLLADA)\n");
+    LOG(1, "  .fbx\t(FBX)\n");
+    LOG(1, "  .ttf\t(TrueType Font)\n");
+    LOG(1, "\n");
+    LOG(1, "General Options:\n");
+    LOG(1, "  -v <verbosity>\tVerbosity level (0-4).\n");
+    LOG(1, "\n");
+    LOG(1, "COLLADA and FBX file options:\n");
+    LOG(1, "  -i <id>\tFilter by node ID.\n");
+    LOG(1, "  -t\t\tWrite text/xml.\n");
+    LOG(1, "  -g <node id> <animation id>\n" \
+        "\t\tGroup all animation channels targeting the nodes into a new animation.\n");
+    LOG(1, "  -oa\n" \
+        "\t\tOptimizes animations by analyzing animation channel data and\n" \
+        "\t\tremoving any channels that contain default/identity values\n" \
+        "\t\tand removing any duplicate contiguous keyframes, which are common\n" \
+        "\t\twhen exporting baked animation data.\n");
+    LOG(1, "  -h \"<node ids>\" <filename>\n" \
+        "\t\tGenerates a single heightmap image using meshes from the specified\n" \
+        "\t\tnodes. Node id list should be in quotes with a space between each id.\n" \
+        "\t\tFilename is the name of the image (PNG) to be saved.\n" \
+        "\t\tMultiple -h arguments can be supplied to generate more than one heightmap.\n" \
+        "\t\tFor 24-bit packed height data use -hp instead of -h.\n");
+    LOG(1, "\n");
+    LOG(1, "TTF file options:\n");
+    LOG(1, "  -s <size>\tSize of the font.\n");
+    LOG(1, "  -p\t\tOutput font preview.\n");
+    LOG(1, "\n");
     exit(8);
 }
 
@@ -214,6 +220,11 @@ bool EncoderArguments::DAEOutputEnabled() const
     return _daeOutput;
 }
 
+bool EncoderArguments::optimizeAnimationsEnabled() const
+{
+    return _optimizeAnimations;
+}
+
 const char* EncoderArguments::getNodeId() const
 {
     if (_nodeId.length() == 0)
@@ -278,7 +289,7 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
             // read one string, make sure not to go out of bounds
             if ((*index + 1) >= options.size())
             {
-                fprintf(stderr, "Error: -dae requires 1 argument.\n");
+                LOG(1, "Error: -dae requires 1 argument.\n");
                 _parseError = true;
                 return;
             }
@@ -293,7 +304,7 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
             // read two strings, make sure not to go out of bounds
             if ((*index + 2) >= options.size())
             {
-                fprintf(stderr, "Error: -g requires 2 arguments.\n");
+                LOG(1, "Error: -g requires 2 arguments.\n");
                 _parseError = true;
                 return;
             }
@@ -304,7 +315,6 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
         }
         break;
     case 'i':
-    case 'o':
         // Node ID
         (*index)++;
         if (*index < options.size())
@@ -313,20 +323,32 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
         }
         else
         {
-            fprintf(stderr, "Error: missing arguemnt for -%c.\n", str[1]);
+            LOG(1, "Error: missing arguemnt for -%c.\n", str[1]);
             _parseError = true;
             return;
         }
         break;
+    case 'o':
+        // Optimization flag
+        if (str == "-oa")
+        {
+            // Optimize animations
+            _optimizeAnimations = true;
+        }
+        break;
     case 'h':
         {
             bool isHighPrecision = str.compare("-hp") == 0;
-            if (str.compare("-heightmaps") == 0 || str.compare("-h") == 0 || isHighPrecision)
+            if (str.compare("-heightmap") == 0 || str.compare("-h") == 0 || isHighPrecision)
             {
-                _isHeightmapHighP = isHighPrecision;
                 (*index)++;
-                if (*index < options.size())
+                if (*index < (options.size() + 1))
                 {
+                    _heightmaps.resize(_heightmaps.size() + 1);
+                    HeightmapOption& heightmap = _heightmaps.back();
+                    
+                    heightmap.isHighPrecision = isHighPrecision;
+
                     // Split node id list into tokens
                     unsigned int length = options[*index].size() + 1;
                     char* nodeIds = new char[length];
@@ -335,14 +357,36 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
                     char* id = strtok(nodeIds, " ");
                     while (id)
                     {
-                        _heightmapNodeIds.push_back(id);
+                        heightmap.nodeIds.push_back(id);
                         id = strtok(NULL, " ");
                     }
                     delete[] nodeIds;
+
+                    // Store output filename
+                    (*index)++;
+                    heightmap.filename = options[*index];
+                    if (heightmap.filename.empty())
+                    {
+                        LOG(1, "Error: missing filename argument for -h|-heightmap.\n");
+                        _parseError = true;
+                        return;
+                    }
+                    
+                    // Ensure the output filename has a .png extention
+                    if (heightmap.filename.length() > 5)
+                    {
+                        const char* ext = heightmap.filename.c_str() + (heightmap.filename.length() - 4);
+                        if (ext[0] != '.' || tolower(ext[1]) != 'p' || tolower(ext[2]) != 'n' || tolower(ext[3]) != 'g')
+                            heightmap.filename += ".png";
+                    }
+                    else
+                        heightmap.filename += ".png";
                 }
                 else
                 {
-                    fprintf(stderr, "Error: missing argument for -heightmaps.\n");
+                    LOG(1, "Error: missing argument for -h|-heightmap.\n");
+                    _parseError = true;
+                    return;
                 }
             }
         }
@@ -372,7 +416,7 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
         }
         else
         {
-            fprintf(stderr, "Error: missing arguemnt for -%c.\n", str[1]);
+            LOG(1, "Error: missing arguemnt for -%c.\n", str[1]);
             _parseError = true;
             return;
         }
@@ -380,6 +424,16 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
     case 't':
         _textOutput = true;
         break;
+    case 'v':
+        (*index)++;
+        if (*index < options.size())
+        {
+            __logVerbosity = atoi(options[*index].c_str());
+            if (__logVerbosity < 0)
+                __logVerbosity = 0;
+            else if (__logVerbosity > 4)
+                __logVerbosity = 4;
+        }
     default:
         break;
     }

+ 11 - 8
gameplay-encoder/src/EncoderArguments.h

@@ -20,6 +20,13 @@ public:
         FILEFORMAT_GPB
     };
 
+    struct HeightmapOption
+    {
+        std::vector<std::string> nodeIds;
+        std::string filename;
+        bool isHighPrecision;
+    };
+
     /**
      * Constructor.
      */
@@ -73,12 +80,7 @@ public:
     bool containsGroupNodeId(const std::string& nodeId) const;
     const std::string getAnimationId(const std::string& nodeId) const;
 
-    const std::vector<std::string>& getHeightmapNodeIds() const;
-    
-    /**
-     * Returns true if the heightmap is to be high precision (24-bit packed).
-     */
-    bool isHeightmapHighP() const;
+    const std::vector<HeightmapOption>& getHeightmapOptions() const;
 
     /**
      * Returns true if an error occurred while parsing the command line arguments.
@@ -100,6 +102,7 @@ public:
     bool fontPreviewEnabled() const;
     bool textOutputEnabled() const;
     bool DAEOutputEnabled() const;
+    bool optimizeAnimationsEnabled() const;
 
     const char* getNodeId() const;
     unsigned int getFontSize() const;
@@ -144,11 +147,11 @@ private:
     bool _fontPreview;
     bool _textOutput;
     bool _daeOutput;
-    bool _isHeightmapHighP;
+    bool _optimizeAnimations;
 
     std::vector<std::string> _groupAnimationNodeId;
     std::vector<std::string> _groupAnimationAnimationId;
-    std::vector<std::string> _heightmapNodeIds;
+    std::vector<HeightmapOption> _heightmaps;
 
 };
 

+ 321 - 159
gameplay-encoder/src/FBXSceneEncoder.cpp

@@ -30,11 +30,14 @@ static float getFieldOfView(FbxCamera* fbxCamera);
  * Loads the texture coordinates from given mesh's polygon part into the vertex.
  * 
  * @param fbxMesh The mesh to get the polygon from.
- * @param polyIndex The index of the polygon.
- * @param posInPoly The position in the polygon.
+ * @param uvs The UV list to load tex coords from.
+ * @param uvSetIndex The UV set index of the uvs.
+ * @param polyIndex The index of the polygon in the mesh.
+ * @param posInPoly The position of the vertex in the polygon.
+ * @param meshVertexIndex The index of the vertex in the mesh.
  * @param vertex The vertex to copy the texture coordinates to.
  */
-static void loadTextureCoords(FbxMesh* fbxMesh, int polyIndex, int posInPoly, Vertex* vertex);
+static void loadTextureCoords(FbxMesh* fbxMesh, const FbxGeometryElementUV* uvs, int uvSetIndex, int polyIndex, int posInPoly, int meshVertexIndex, Vertex* vertex);
 
 /**
  * Loads the normal from the mesh and adds it to the given vertex.
@@ -118,14 +121,17 @@ static void copyMatrix(const FbxMatrix& fbxMatrix, Matrix& matrix);
 static void findMinMaxTime(FbxAnimCurve* animCurve, float* startTime, float* stopTime, float* frameRate);
 
 /**
- * Appends a key frame of the given node's transform at the given time.
+ * Appends key frame data to the given node for the specified animation target attribute.
  * 
  * @param fbxNode The node to get the matrix transform from.
- * @param time The key time to add and the time to get the transform from.
- * @param keyTimes The list of key times to append to.
- * @param keyValues The list of key values to append to.
+ * @param channel The aniamtion channel to write values into.
+ * @param time The time of the keyframe.
+ * @param scale The evaluated scale for the keyframe.
+ * @param rotation The evalulated rotation for the keyframe.
+ * @param translation The evalulated translation for the keyframe.
+
  */
-static void appendKeyFrame(FbxNode* fbxNode, float time, std::vector<float>* keyTimes, std::vector<float>* keyValues);
+static void appendKeyFrame(FbxNode* fbxNode, AnimationChannel* channel, float time, const Vector3& scale, const Quaternion& rotation, const Vector3& translation);
 
 /**
  * Decomposes the given node's matrix transform at the given time and copies to scale, rotation and translation.
@@ -196,8 +202,8 @@ void FBXSceneEncoder::write(const std::string& filepath, const EncoderArguments&
     
     if (!importer->Initialize(filepath.c_str(), -1, sdkManager->GetIOSettings()))
     {
-        printf("Call to FbxImporter::Initialize() failed.\n");
-        printf("Error returned: %s\n\n", importer->GetLastErrorString());
+        LOG(1, "Call to FbxImporter::Initialize() failed.\n");
+        LOG(1, "Error returned: %s\n\n", importer->GetLastErrorString());
         exit(-1);
     }
     
@@ -238,19 +244,19 @@ void FBXSceneEncoder::write(const std::string& filepath, const EncoderArguments&
         {
             std::string path = outputFilePath.substr(0, pos);
             path.append(".xml");
-            fprintf(stderr, "Saving debug file: %s\n", path.c_str());
+            LOG(1, "Saving debug file: %s\n", path.c_str());
             if (!_gamePlayFile.saveText(path))
             {
-                fprintf(stderr,"Error writing text file: %s\n", path.c_str());
+                LOG(1, "Error writing text file: %s\n", path.c_str());
             }
         }
     }
     else
     {
-        fprintf(stderr, "Saving binary file: %s\n", outputFilePath.c_str());
+        LOG(1, "Saving binary file: %s\n", outputFilePath.c_str());
         if (!_gamePlayFile.saveBinary(outputFilePath))
         {
-            fprintf(stderr,"Error writing binary file: %s\n", outputFilePath.c_str());
+            LOG(1, "Error writing binary file: %s\n", outputFilePath.c_str());
         }
     }
 }
@@ -302,14 +308,8 @@ void FBXSceneEncoder::loadScene(FbxScene* fbxScene)
 
 void FBXSceneEncoder::loadAnimationChannels(FbxAnimLayer* animLayer, FbxNode* fbxNode, Animation* animation)
 {
-    const std::string* targetId = NULL;
-
     const char* name = fbxNode->GetName();
     Node* node = _gamePlayFile.getNode(name);
-    if (node)
-    {
-        targetId = &node->getId();
-    }
     
     // Determine which properties are animated on this node
     // Find the transform at each key frame
@@ -374,78 +374,142 @@ void FBXSceneEncoder::loadAnimationChannels(FbxAnimLayer* animLayer, FbxNode* fb
         findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
     }
 
-    bool translate = tx | ty | tz;
-    bool scale = sx | sy | sz;
-    bool rotate = rx | ry | rz;
+    if (!(sx || sy || sz || rx || ry || rz || tx || ty || tz))
+        return; // no animation channels
 
-    if (translate || rotate || scale)
-    {
-        assert(startTime != FLT_MAX);
-        assert(stopTime >= 0.0f);
-        AnimationChannel* channel = new AnimationChannel();
-        channel->setTargetId(name);
-        channel->setTargetAttribute(Transform::ANIMATE_SCALE_ROTATE_TRANSLATE);
-        
-        float increment = 1000.0f / frameRate;
-        std::vector<float> keyTimes;
-        std::vector<float> keyValues;
-        for (float time = startTime; time < stopTime; time += increment)
-        {
-            appendKeyFrame(fbxNode, time, &keyTimes, &keyValues);
-        }
-        // Add the last key frame at exactly stopTime
-        appendKeyFrame(fbxNode, stopTime, &keyTimes, &keyValues);
+    assert(startTime != FLT_MAX);
+    assert(stopTime >= 0.0f);
 
-        channel->setKeyTimes(keyTimes);
-        /*
-        std::vector<float> newKeyValues;
-        for (size_t i = 0, size = keyValues.size(); i < size; i += 10)
+    // Determine which animation channels to create
+    std::vector<unsigned int> channelAttribs;
+    if (sx && sy && sz)
+    {
+        if (rx || ry || rz)
         {
-            if (translate)
+            if (tx && ty && tz)
             {
-                newKeyValues.push_back(keyValues[i+0]);
-                newKeyValues.push_back(keyValues[i+1]);
-                newKeyValues.push_back(keyValues[i+2]);
+                channelAttribs.push_back(Transform::ANIMATE_SCALE_ROTATE_TRANSLATE);
             }
-            if (rotate)
-            {
-                newKeyValues.push_back(keyValues[i+3]);
-                newKeyValues.push_back(keyValues[i+4]);
-                newKeyValues.push_back(keyValues[i+5]);
-                newKeyValues.push_back(keyValues[i+6]);
-            }
-            if (scale)
+            else
             {
-                newKeyValues.push_back(keyValues[i+7]);
-                newKeyValues.push_back(keyValues[i+8]);
-                newKeyValues.push_back(keyValues[i+9]);
+                channelAttribs.push_back(Transform::ANIMATE_SCALE_ROTATE);
+                if (tx)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_X);
+                if (ty)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Y);
+                if (tz)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Z);
             }
         }
-        channel->setKeyValues(newKeyValues);
-        */
-        channel->setKeyValues(keyValues);
-        channel->setInterpolation(AnimationChannel::LINEAR);
-        animation->add(channel);
-        /*
-        if (!translate)
+        else
         {
-            addTranslateChannel(animation, fbxNode, startTime, stopTime);
+            if (tx && ty && tz)
+            {
+                channelAttribs.push_back(Transform::ANIMATE_SCALE_TRANSLATE);
+            }
+            else
+            {
+                channelAttribs.push_back(Transform::ANIMATE_SCALE);
+                if (tx)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_X);
+                if (ty)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Y);
+                if (tz)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Z);
+            }
         }
-        if (!rotate)
+    }
+    else
+    {
+        if (rx || ry || rz)
         {
-            printf("rotate?\n"); // TODO
+            if (tx && ty && tz)
+            {
+                channelAttribs.push_back(Transform::ANIMATE_ROTATE_TRANSLATE);
+            }
+            else
+            {
+                channelAttribs.push_back(Transform::ANIMATE_ROTATE);
+                if (tx)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_X);
+                if (ty)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Y);
+                if (tz)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Z);
+            }
         }
-        if (!scale)
+        else
         {
-            addScaleChannel(animation, fbxNode, startTime, stopTime);
+            if (tx && ty && tz)
+            {
+                channelAttribs.push_back(Transform::ANIMATE_TRANSLATE);
+            }
+            else
+            {
+                if (tx)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_X);
+                if (ty)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Y);
+                if (tz)
+                    channelAttribs.push_back(Transform::ANIMATE_TRANSLATE_Z);
+            }
         }
-        */
-        if (_groupAnimation != animation)
+
+        if (sx)
+            channelAttribs.push_back(Transform::ANIMATE_SCALE_X);
+        if (sy)
+            channelAttribs.push_back(Transform::ANIMATE_SCALE_Y);
+        if (sz)
+            channelAttribs.push_back(Transform::ANIMATE_SCALE_Z);
+    }
+    unsigned int channelCount = channelAttribs.size();
+    assert(channelCount > 0);
+
+    // Allocate channel list
+    for (unsigned int i = 0; i < channelCount; ++i)
+    {
+        AnimationChannel* channel = new AnimationChannel();
+        channel->setTargetId(name);
+        channel->setInterpolation(AnimationChannel::LINEAR);
+        channel->setTargetAttribute(channelAttribs[i]);
+        animation->add(channel);
+    }
+
+    // Evaulate animation curve in increments of frameRate and populate channel data.
+    FbxAMatrix fbxMatrix;
+    Matrix matrix;
+    float increment = 1000.0f / frameRate;
+    for (float time = startTime; time <= stopTime; time += increment)
+    {
+        // Clamp time to stopTime
+        time = std::min(time, stopTime);
+
+        // Evalulate the animation at this time
+        FbxTime kTime;
+        kTime.SetMilliSeconds((FbxLongLong)time);
+        fbxMatrix = fbxNode->EvaluateLocalTransform(kTime);
+        copyMatrix(fbxMatrix, matrix);
+
+        // Decompose the evalulated transformation matrix into separate
+        // scale, rotation and translation.
+        Vector3 scale;
+        Quaternion rotation;
+        Vector3 translation;
+        matrix.decompose(&scale, &rotation, &translation);
+        rotation.normalize();
+
+        // Append keyframe data to all channels
+        for (unsigned int i = 0; i < channelCount; ++i)
         {
-            // TODO explains
-            _gamePlayFile.addAnimation(animation);
+            appendKeyFrame(fbxNode, animation->getAnimationChannel(i), time, scale, rotation, translation);
         }
     }
+
+    if (_groupAnimation != animation)
+    {
+        // TODO explain
+        _gamePlayFile.addAnimation(animation);
+    }
 }
 
 void FBXSceneEncoder::loadAnimationLayer(FbxAnimLayer* fbxAnimLayer, FbxNode* fbxNode, const EncoderArguments& arguments)
@@ -573,7 +637,7 @@ void FBXSceneEncoder::saveMesh(FbxUInt64 meshId, Mesh* mesh)
 
 void FBXSceneEncoder::print(const char* str)
 {
-    fprintf(stderr,"%s\n", str);
+    LOG(1, "%s\n", str);
 }
 
 void FBXSceneEncoder::transformNode(FbxNode* fbxNode, Node* node)
@@ -656,7 +720,7 @@ void FBXSceneEncoder::loadCamera(FbxNode* fbxNode, Node* node)
     }
     else
     {
-        warning("Unknown camera type in node");
+        LOG(2, "Warning: Unknown camera type in node.\n");
         return;
     }
     _gamePlayFile.addCamera(camera);
@@ -740,7 +804,7 @@ void FBXSceneEncoder::loadLight(FbxNode* fbxNode, Node* node)
     }
     default:
     {
-        warning("Unknown light type in node.");
+        LOG(2, "Warning: Unknown light type in node.\n");
         return;
     }
     }
@@ -851,6 +915,11 @@ Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh)
     std::vector<std::vector<Vector2> > weights;
     bool hasSkin = loadBlendWeights(fbxMesh, weights);
     
+    // Get list of uv sets for mesh
+    FbxStringList uvSetNameList;
+    fbxMesh->GetUVSetNames(uvSetNameList);
+    const int uvSetCount = uvSetNameList.GetCount();
+
     int vertexIndex = 0;
     FbxVector4* controlPoints = fbxMesh->GetControlPoints();
     const int polygonCount = fbxMesh->GetPolygonCount();
@@ -867,7 +936,15 @@ Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh)
             vertex.position.y = (float)position[1];
             vertex.position.z = (float)position[2];
 
-            loadTextureCoords(fbxMesh, polyIndex, posInPoly, &vertex);
+            // Load tex coords for all uv sets
+            for (int uvSetIndex = 0; uvSetIndex < uvSetCount; ++uvSetIndex)
+            {
+                const FbxGeometryElementUV* uvElement = fbxMesh->GetElementUV(uvSetNameList.GetStringAt(uvSetIndex));
+                if (uvElement)
+                    loadTextureCoords(fbxMesh, uvElement, uvSetIndex, polyIndex, posInPoly, vertexIndex, &vertex);
+            }
+
+            // Load other data
             loadNormal(fbxMesh, vertexIndex, controlPointIndex, &vertex);
             loadTangent(fbxMesh, vertexIndex, &vertex);
             loadBinormal(fbxMesh, vertexIndex, &vertex);
@@ -931,9 +1008,12 @@ Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh)
         mesh->addVetexAttribute(BINORMAL, Vertex::BINORMAL_COUNT);
     }
     // Texture Coordinates
-    if (vertex.hasTexCoord)
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
     {
-        mesh->addVetexAttribute(TEXCOORD0, Vertex::TEXCOORD_COUNT);
+        if (vertex.hasTexCoord[i])
+        {
+            mesh->addVetexAttribute(TEXCOORD0 + i, Vertex::TEXCOORD_COUNT);
+        }
     }
     // Diffuse Color
     if (vertex.hasDiffuse)
@@ -976,16 +1056,6 @@ void FBXSceneEncoder::triangulateRecursive(FbxNode* fbxNode)
     }
 }
 
-void FBXSceneEncoder::warning(const std::string& message)
-{
-    printf("Warning: %s\n", message.c_str());
-}
-
-void FBXSceneEncoder::warning(const char* message)
-{
-    printf("Warning: %s\n", message);
-}
-
 ////////////////////////////////////
 // Functions
 ////////////////////////////////////
@@ -1061,54 +1131,46 @@ float getFieldOfView(FbxCamera* fbxCamera)
     return (float)fieldOfViewY;
 }
 
-void loadTextureCoords(FbxMesh* fbxMesh, int polyIndex, int posInPoly, Vertex* vertex)
+void loadTextureCoords(FbxMesh* fbxMesh, const FbxGeometryElementUV* uvs, int uvSetIndex, int polyIndex, int posInPoly, int meshVertexIndex, Vertex* vertex)
 {
     assert(fbxMesh && polyIndex >=0 && posInPoly >= 0);
-    if (fbxMesh->GetElementUVCount() > 0)
+
+    const bool useIndex = uvs->GetReferenceMode() != FbxGeometryElement::eDirect;
+    const int indexCount = useIndex ? uvs->GetIndexArray().GetCount() : 0;
+    int uvIndex = -1;
+
+    switch (uvs->GetMappingMode())
     {
-        // Get only the first UV coordinates.
-        FbxGeometryElementUV* uv = fbxMesh->GetElementUV(0);
-        switch (uv->GetMappingMode())
+    case FbxGeometryElement::eByControlPoint:
         {
-        case FbxGeometryElement::eByControlPoint:
-            switch (uv->GetReferenceMode())
-            {
-            case FbxGeometryElement::eDirect:
-                vertex->hasTexCoord = true;
-                vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(polyIndex)[0];
-                vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(polyIndex)[1];
-                break;
-            case FbxGeometryElement::eIndexToDirect:
-                {
-                    int id = uv->GetIndexArray().GetAt(polyIndex);
-                    vertex->hasTexCoord = true;
-                    vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(id)[0];
-                    vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(id)[1];
-                }
-                break;
-            default:
-                break;
-            }
-            break;
-        case FbxGeometryElement::eByPolygonVertex:
-            {
-                int lTextureUVIndex = fbxMesh->GetTextureUVIndex(polyIndex, posInPoly);
-                switch (uv->GetReferenceMode())
-                {
-                case FbxGeometryElement::eDirect:
-                case FbxGeometryElement::eIndexToDirect:
-                    vertex->hasTexCoord = true;
-                    vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(lTextureUVIndex)[0];
-                    vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(lTextureUVIndex)[1];
-                    break;
-                default:
-                    break;
-                }
-            }
-            break;
-        default:
-            break;
+            // Get the index of the current vertex in control points array
+            int polyVertIndex = fbxMesh->GetPolygonVertex(polyIndex, posInPoly);
+
+            // The UV index depends on the reference mode
+            uvIndex = useIndex ? uvs->GetIndexArray().GetAt(polyVertIndex) : polyVertIndex;
         }
+        break;
+
+    case FbxGeometryElement::eByPolygonVertex:
+        if (meshVertexIndex < indexCount)
+        {
+            uvIndex = useIndex ? uvs->GetIndexArray().GetAt(meshVertexIndex) : meshVertexIndex;
+        }
+        break;
+
+    default:
+        // Only support eByPolygonVertex and eByControlPoint mappings
+        break;
+    }
+
+    vertex->hasTexCoord[uvSetIndex] = true;
+
+    // Store UV information in vertex
+    if (uvIndex != -1)
+    {
+        FbxVector2 uvValue = uvs->GetDirectArray().GetAt(uvIndex);
+        vertex->texCoord[uvSetIndex].x = (float)uvValue[0];
+        vertex->texCoord[uvSetIndex].y = (float)uvValue[1];
     }
 }
 
@@ -1376,32 +1438,132 @@ void findMinMaxTime(FbxAnimCurve* animCurve, float* startTime, float* stopTime,
     *frameRate = std::max(*frameRate, (float)stop.GetFrameRate(FbxTime::eDefaultMode));
 }
 
-void appendKeyFrame(FbxNode* fbxNode, float time, std::vector<float>* keyTimes, std::vector<float>* keyValues)
+void appendKeyFrame(FbxNode* fbxNode, AnimationChannel* channel, float time, const Vector3& scale, const Quaternion& rotation, const Vector3& translation)
 {
-    FbxAMatrix fbxMatrix;
-    Matrix matrix;
-    FbxTime kTime;
-    kTime.SetMilliSeconds((FbxLongLong)time);
-    fbxMatrix = fbxNode->EvaluateLocalTransform(kTime);
-    copyMatrix(fbxMatrix, matrix);
+    // Write key time
+    channel->getKeyTimes().push_back(time);
 
-    Vector3 scale;
-    Quaternion rotation;
-    Vector3 translation;
-    matrix.decompose(&scale, &rotation, &translation);
-    rotation.normalize();
-
-    keyTimes->push_back(time);
-    keyValues->push_back(scale.x);
-    keyValues->push_back(scale.y);
-    keyValues->push_back(scale.z);
-    keyValues->push_back(rotation.x);
-    keyValues->push_back(rotation.y);
-    keyValues->push_back(rotation.z);
-    keyValues->push_back(rotation.w);
-    keyValues->push_back(translation.x);
-    keyValues->push_back(translation.y);
-    keyValues->push_back(translation.z);
+    // Write key values
+    std::vector<float>& keyValues = channel->getKeyValues();
+    switch (channel->getTargetAttribute())
+    {
+        case Transform::ANIMATE_SCALE:
+        {
+            keyValues.push_back(scale.x);
+            keyValues.push_back(scale.y);
+            keyValues.push_back(scale.z);
+        }
+        break;
+
+        case Transform::ANIMATE_SCALE_X:
+        {
+            keyValues.push_back(scale.x);
+        }
+        break;
+
+        case Transform::ANIMATE_SCALE_Y:
+        {
+            keyValues.push_back(scale.y);
+        }
+        break;
+
+        case Transform::ANIMATE_SCALE_Z:
+        {
+            keyValues.push_back(scale.z);
+        }
+        break;
+
+        case Transform::ANIMATE_ROTATE:
+        {
+            keyValues.push_back(rotation.x);
+            keyValues.push_back(rotation.y);
+            keyValues.push_back(rotation.z);
+            keyValues.push_back(rotation.w);
+        }
+        break;
+
+        case Transform::ANIMATE_TRANSLATE:
+        {
+            keyValues.push_back(translation.x);
+            keyValues.push_back(translation.y);
+            keyValues.push_back(translation.z);
+        }
+        break;
+
+        case Transform::ANIMATE_TRANSLATE_X:
+        {
+            keyValues.push_back(translation.x);
+        }
+        break;
+
+        case Transform::ANIMATE_TRANSLATE_Y:
+        {
+            keyValues.push_back(translation.y);
+        }
+        break;
+
+        case Transform::ANIMATE_TRANSLATE_Z:
+        {
+            keyValues.push_back(translation.z);
+        }
+        break;
+
+        case Transform::ANIMATE_ROTATE_TRANSLATE:
+        {
+            keyValues.push_back(rotation.x);
+            keyValues.push_back(rotation.y);
+            keyValues.push_back(rotation.z);
+            keyValues.push_back(rotation.w);
+            keyValues.push_back(translation.x);
+            keyValues.push_back(translation.y);
+            keyValues.push_back(translation.z);
+        }
+        break;
+
+        case Transform::ANIMATE_SCALE_ROTATE_TRANSLATE:
+        {
+            keyValues.push_back(scale.x);
+            keyValues.push_back(scale.y);
+            keyValues.push_back(scale.z);
+            keyValues.push_back(rotation.x);
+            keyValues.push_back(rotation.y);
+            keyValues.push_back(rotation.z);
+            keyValues.push_back(rotation.w);
+            keyValues.push_back(translation.x);
+            keyValues.push_back(translation.y);
+            keyValues.push_back(translation.z);
+        }
+        break;
+
+        case Transform::ANIMATE_SCALE_TRANSLATE:
+        {
+            keyValues.push_back(scale.x);
+            keyValues.push_back(scale.y);
+            keyValues.push_back(scale.z);
+            keyValues.push_back(translation.x);
+            keyValues.push_back(translation.y);
+            keyValues.push_back(translation.z);
+        }
+        break;
+
+        case Transform::ANIMATE_SCALE_ROTATE:
+        {
+            keyValues.push_back(scale.x);
+            keyValues.push_back(scale.y);
+            keyValues.push_back(scale.z);
+            keyValues.push_back(rotation.x);
+            keyValues.push_back(rotation.y);
+            keyValues.push_back(rotation.z);
+            keyValues.push_back(rotation.w);
+        }
+        break;
+
+        default:
+        {
+            LOG(1, "Warning: Invalid animatoin target (%d) attribute for node: %s.\n", channel->getTargetAttribute(), fbxNode->GetName());
+        }
+        return;
+    }
 }
 
 void decompose(FbxNode* fbxNode, float time, Vector3* scale, Quaternion* rotation, Vector3* translation)
@@ -1547,4 +1709,4 @@ bool isGroupAnimationPossible(FbxMesh* fbxMesh)
     return false;
 }
 
-#endif
+#endif

+ 1 - 11
gameplay-encoder/src/FBXSceneEncoder.h

@@ -192,16 +192,6 @@ private:
      */
     static void triangulateRecursive(FbxNode* fbxNode);
 
-    /**
-     * Prints a warning message.
-     */
-    static void warning(const std::string& message);
-
-    /**
-     * Prints a warning message.
-     */
-    static void warning(const char* message);
-
 private:
 
     /**
@@ -226,4 +216,4 @@ private:
 };
 
 #endif
-#endif
+#endif

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

@@ -4,6 +4,8 @@
 #include <cstdio>
 #include <list>
 #include <vector>
+#include <cstring>
+#include <string>
 
 #include "Vector2.h"
 #include "Vector3.h"

+ 103 - 34
gameplay-encoder/src/GPBFile.cpp

@@ -2,6 +2,8 @@
 #include "GPBFile.h"
 #include "Transform.h"
 #include "StringUtil.h"
+#include "EncoderArguments.h"
+#include "Heightmap.h"
 
 #define EPSILON 1.2e-7f;
 
@@ -15,6 +17,11 @@ static GPBFile* __instance = NULL;
  */
 static bool isAlmostOne(float value);
 
+/**
+ * Returns true if the given value is close to zero.
+ */
+static bool isAlmostZero(float value);
+
 /**
  * Gets the common node ancestor for the given list of nodes.
  * This function assumes that the nodes share a common ancestor.
@@ -60,7 +67,7 @@ bool GPBFile::saveBinary(const std::string& filepath)
     size_t n = 0;
 
     // identifier
-    char identifier[] = { '«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n' };
+    char identifier[] = { '�', 'G', 'P', 'B', '�', '\r', '\n', '\x1A', '\n' };
     n = fwrite(identifier, 1, sizeof(identifier), _file);
     if (n != sizeof(identifier))
     {
@@ -308,8 +315,11 @@ void GPBFile::adjust()
         computeBounds(*i);
     }
 
-    // try to convert joint transform animations into rotation animations
-    //optimizeTransformAnimations();
+    if (EncoderArguments::getInstance()->optimizeAnimationsEnabled())
+    {
+        LOG(1, "Optimizing animations.\n");
+        optimizeAnimations();
+    }
 
     // TODO:
     // remove ambient _lights
@@ -323,6 +333,13 @@ void GPBFile::adjust()
     //   Search for animations that have the same target and key times and see if they can be merged.
     //   Blender will output a simple translation animation to 3 separate animations with the same key times but targeting X, Y and Z.
     //   This can be merged into one animation. Same for scale animations.
+
+    // Generate heightmaps
+    const std::vector<EncoderArguments::HeightmapOption>& heightmaps = EncoderArguments::getInstance()->getHeightmapOptions();
+    for (unsigned int i = 0, count = heightmaps.size(); i < count; ++i)
+    {
+        Heightmap::generate(heightmaps[i].nodeIds, heightmaps[i].filename.c_str(), heightmaps[i].isHighPrecision);
+    }
 }
 
 void GPBFile::groupMeshSkinAnimations()
@@ -376,27 +393,31 @@ void GPBFile::computeBounds(Node* node)
     }
 }
 
-void GPBFile::optimizeTransformAnimations()
+void GPBFile::optimizeAnimations()
 {
     const unsigned int animationCount = _animations.getAnimationCount();
     for (unsigned int animationIndex = 0; animationIndex < animationCount; ++animationIndex)
     {
         Animation* animation = _animations.getAnimation(animationIndex);
         assert(animation);
+
         const int channelCount = animation->getAnimationChannelCount();
+
+        LOG(2, "Optimizing %d channel(s) in animation '%s'.\n", channelCount, animation->getId().c_str());
+
         // loop backwards because we will be adding and removing channels
         for (int channelIndex = channelCount -1; channelIndex >= 0 ; --channelIndex)
         {
             AnimationChannel* channel = animation->getAnimationChannel(channelIndex);
             assert(channel);
-            // get target node
+
+            // Optimize node animation channels
             const Object* obj = _refTable.get(channel->getTargetId());
             if (obj && obj->getTypeId() == Object::NODE_ID)
             {
-                const Node* node = static_cast<const Node*>(obj);
-                if (node->isJoint() && channel->getTargetAttribute() == Transform::ANIMATE_SCALE_ROTATE_TRANSLATE)
+                if (channel->getTargetAttribute() == Transform::ANIMATE_SCALE_ROTATE_TRANSLATE)
                 {
-                    decomposeTransformAnimationChannel(animation, channel);
+                    decomposeTransformAnimationChannel(animation, channel, channelIndex);
 
                     animation->remove(channel);
                     SAFE_DELETE(channel);
@@ -406,9 +427,10 @@ void GPBFile::optimizeTransformAnimations()
     }
 }
 
-
-void GPBFile::decomposeTransformAnimationChannel(Animation* animation, const AnimationChannel* channel)
+void GPBFile::decomposeTransformAnimationChannel(Animation* animation, AnimationChannel* channel, int channelIndex)
 {
+    LOG(2, "  Optimizing animaton channel %s:%d.\n", animation->getId().c_str(), channelIndex+1);
+
     const std::vector<float>& keyTimes = channel->getKeyTimes();
     const std::vector<float>& keyValues = channel->getKeyValues();
     const size_t keyTimesSize = keyTimes.size();
@@ -417,7 +439,7 @@ void GPBFile::decomposeTransformAnimationChannel(Animation* animation, const Ani
     std::vector<float> scaleKeyValues;
     std::vector<float> rotateKeyValues;
     std::vector<float> translateKeyValues;
-                    
+
     scaleKeyValues.reserve(keyTimesSize * 3);
     rotateKeyValues.reserve(keyTimesSize * 4);
     translateKeyValues.reserve(keyTimesSize * 3);
@@ -442,8 +464,13 @@ void GPBFile::decomposeTransformAnimationChannel(Animation* animation, const Ani
 
     // Don't add the scale channel if all the key values are close to 1.0
     size_t oneCount = (size_t)std::count_if(scaleKeyValues.begin(), scaleKeyValues.end(), isAlmostOne);
-    if (scaleKeyValues.size() != oneCount)
+    if (scaleKeyValues.size() == oneCount)
+    {
+        LOG(2, "    Discarding scale channel.\n");
+    }
+    else
     {
+        LOG(3, "    Keeping scale channel.\n");
         AnimationChannel* scaleChannel = new AnimationChannel();
         scaleChannel->setTargetId(channel->getTargetId());
         scaleChannel->setKeyTimes(channel->getKeyTimes());
@@ -456,27 +483,64 @@ void GPBFile::decomposeTransformAnimationChannel(Animation* animation, const Ani
         animation->add(scaleChannel);
     }
 
-    AnimationChannel* rotateChannel = new AnimationChannel();
-    rotateChannel->setTargetId(channel->getTargetId());
-    rotateChannel->setKeyTimes(channel->getKeyTimes());
-    rotateChannel->setTangentsIn(channel->getTangentsIn());
-    rotateChannel->setTangentsOut(channel->getTangentsOut());
-    rotateChannel->setInterpolations(channel->getInterpolationTypes());
-    rotateChannel->setTargetAttribute(Transform::ANIMATE_ROTATE);
-    rotateChannel->setKeyValues(rotateKeyValues);
-    rotateChannel->removeDuplicates();
-    animation->add(rotateChannel);
-
-    AnimationChannel* translateChannel = new AnimationChannel();
-    translateChannel->setTargetId(channel->getTargetId());
-    translateChannel->setKeyTimes(channel->getKeyTimes());
-    translateChannel->setTangentsIn(channel->getTangentsIn());
-    translateChannel->setTangentsOut(channel->getTangentsOut());
-    translateChannel->setInterpolations(channel->getInterpolationTypes());
-    translateChannel->setTargetAttribute(Transform::ANIMATE_TRANSLATE);
-    translateChannel->setKeyValues(translateKeyValues);
-    translateChannel->removeDuplicates();
-    animation->add(translateChannel);
+    // Don't add the rotation channel if all quaternions are close to identity
+    oneCount = 0;
+    for (unsigned int i = 0, count = rotateKeyValues.size(); i < count; i += 4)
+    {
+        float x = rotateKeyValues[i];
+        float y = rotateKeyValues[i+1];
+        float z = rotateKeyValues[i+2];
+        float w = rotateKeyValues[i+3];
+        if (ISZERO(x) && ISZERO(y) && ISZERO(z) && ISONE(w))
+            ++oneCount;
+        else
+        {
+            LOG(4, "Rotation not identity: %u\n", i);
+            Quaternion q(x, y, z, w);
+            Vector3 axis;
+            float angle = q.toAxisAngle(&axis);
+            angle = 0;
+        }
+    }
+    if ((rotateKeyValues.size()>>2) == oneCount)
+    {
+        LOG(2, "    Discarding rotation channel.\n");
+    }
+    else
+    {
+        LOG(3, "    Keeping rotation channel.\n");
+        AnimationChannel* rotateChannel = new AnimationChannel();
+        rotateChannel->setTargetId(channel->getTargetId());
+        rotateChannel->setKeyTimes(channel->getKeyTimes());
+        rotateChannel->setTangentsIn(channel->getTangentsIn());
+        rotateChannel->setTangentsOut(channel->getTangentsOut());
+        rotateChannel->setInterpolations(channel->getInterpolationTypes());
+        rotateChannel->setTargetAttribute(Transform::ANIMATE_ROTATE);
+        rotateChannel->setKeyValues(rotateKeyValues);
+        rotateChannel->removeDuplicates();
+        animation->add(rotateChannel);
+    }
+
+    // Don't add the translation channel if all values are close to zero
+    oneCount = (size_t)std::count_if(translateKeyValues.begin(), translateKeyValues.end(), isAlmostZero);
+    if (translateKeyValues.size() == oneCount)
+    {
+        LOG(2, "    Discarding translation channel.\n");
+    }
+    else
+    {
+        LOG(3, "    Keeping translation channel.\n");
+        AnimationChannel* translateChannel = new AnimationChannel();
+        translateChannel->setTargetId(channel->getTargetId());
+        translateChannel->setKeyTimes(channel->getKeyTimes());
+        translateChannel->setTangentsIn(channel->getTangentsIn());
+        translateChannel->setTangentsOut(channel->getTangentsOut());
+        translateChannel->setInterpolations(channel->getInterpolationTypes());
+        translateChannel->setTargetAttribute(Transform::ANIMATE_TRANSLATE);
+        translateChannel->setKeyValues(translateKeyValues);
+        translateChannel->removeDuplicates();
+        animation->add(translateChannel);
+    }
 }
 
 void GPBFile::moveAnimationChannels(Node* node, Animation* dstAnimation)
@@ -509,7 +573,12 @@ void GPBFile::moveAnimationChannels(Node* node, Animation* dstAnimation)
 
 bool isAlmostOne(float value)
 {
-    return std::fabs(value - 1.0f) < EPSILON;
+    return (value - 1.0f) < EPSILON;
+}
+
+bool isAlmostZero(float value)
+{
+    return std::fabs(value) < EPSILON;
 }
 
 Node* getCommonNodeAncestor(const std::vector<Node*>& nodes)

+ 8 - 2
gameplay-encoder/src/GPBFile.h

@@ -116,19 +116,25 @@ public:
     void renameAnimations(std::vector<std::string>& animationIds, const char* newId);
 
 private:
+
     /**
      * Computes the bounds of all meshes in the node hierarchy.
      */
     void computeBounds(Node* node);
-    void optimizeTransformAnimations();
+
+    /**
+     * Optimizes animation data by removing unneccessary channels and keyframes.
+     */
+    void optimizeAnimations();
 
     /**
      * Decomposes an ANIMATE_SCALE_ROTATE_TRANSLATE channel into 3 new channels. (Scale, Rotate and Translate)
      * 
      * @param animation The animation that the channel belongs to.
      * @param channel The animation channel to decompose.
+     * @param channelIndex Index of the channel.
      */
-    void decomposeTransformAnimationChannel(Animation* animation, const AnimationChannel* channel);
+    void decomposeTransformAnimationChannel(Animation* animation, AnimationChannel* channel, int channelIndex);
 
     /**
      * Moves the animation channels that target the given node and its children to be under the given animation.

+ 533 - 0
gameplay-encoder/src/Heightmap.cpp

@@ -0,0 +1,533 @@
+#include "Heightmap.h"
+#include "GPBFile.h"
+#include "Thread.h"
+
+namespace gameplay
+{
+
+// Number of threads to spawn for the heightmap generator
+#define THREAD_COUNT 8
+
+// Thread data structure
+struct HeightmapThreadData
+{
+    float rayHeight;                    // [in]
+    const Vector3* rayDirection;        // [in]
+    const std::vector<Mesh*>* meshes;   // [in]
+    const BoundingVolume* bounds;       // [in]
+    int minX;                           // [in]
+    int maxX;                           // [in]
+    int minZ;                           // [in]
+    int maxZ;                           // [in]
+    float minHeight;                    // [out]
+    float maxHeight;                    // [out]
+    float* heights;                     // [in][out]
+    int heightIndex;                    // [in]
+};
+
+// Globals used by thread
+int __processedHeightmapScanLines = 0;
+int __totalHeightmapScanlines = 0;
+int __failedRayCasts = 0;
+
+// Forward declarations
+int generateHeightmapChunk(void* threadData);
+bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const Vector3& boxMin, const Vector3& boxMax, float* distance = NULL);
+int intersect_triangle(const float orig[3], const float dir[3], const float vert0[3], const float vert1[3], const float vert2[3], float *t, float *u, float *v);
+bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const std::vector<Vertex>& vertices, const std::vector<MeshPart*>& parts, Vector3* point);
+
+void Heightmap::generate(const std::vector<std::string>& nodeIds, const char* filename, bool highP)
+{
+    LOG(1, "Generating heightmap: %s...\n", filename);
+
+    // Initialize state variables
+    __processedHeightmapScanLines = 0;
+    __totalHeightmapScanlines = 0;
+    __failedRayCasts = 0;
+
+    GPBFile* gpbFile = GPBFile::getInstance();
+
+    // Lookup nodes in GPB file and compute a single bounding volume that encapsulates all meshes
+    // to be included in the heightmap generation.
+    BoundingVolume bounds;
+    bounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
+    bounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+    std::vector<Mesh*> meshes;
+    for (unsigned int j = 0, ncount = nodeIds.size(); j < ncount; ++j)
+    {
+        Node* node = gpbFile->getNode(nodeIds[j].c_str());
+        if (node)
+        {
+            Mesh* mesh = node->getModel() ? node->getModel()->getMesh() : NULL;
+            if (mesh)
+            {
+                // Add this mesh and update our bounding volume
+                if (meshes.size() == 0)
+                    bounds = mesh->bounds;
+                else
+                    bounds.merge(mesh->bounds);
+
+                meshes.push_back(mesh);
+            }
+            else
+            {
+                LOG(1, "WARNING: Node passed to heightmap argument does not have a mesh: %s\n", nodeIds[j].c_str());
+            }
+        }
+        else
+        {
+            LOG(1, "WARNING: Failed to locate node for heightmap argument: %s\n", nodeIds[j].c_str());
+        }
+    }
+
+    if (meshes.size() == 0)
+    {
+        LOG(1, "WARNING: Skipping generation of heightmap '%s'. No nodes found.\n", filename);
+        return;
+    }
+
+    // Shoot rays down from a point just above the max Y position of the mesh.
+    // Compute ray-triangle intersection tests against the ray and this mesh to 
+    // generate heightmap data.
+    Vector3 rayOrigin(0, bounds.max.y + 10, 0);
+    Vector3 rayDirection(0, -1, 0);
+
+    int minX = (int)ceil(bounds.min.x);
+    int maxX = (int)floor(bounds.max.x);
+    int minZ = (int)ceil(bounds.min.z);
+    int maxZ = (int)floor(bounds.max.z);
+    int width = maxX - minX + 1;
+    int height = maxZ - minZ + 1;
+    int size = width * height;
+    float* heights = new float[size];
+    float minHeight = FLT_MAX;
+    float maxHeight = -FLT_MAX;
+
+    __totalHeightmapScanlines = height;
+
+    // Split the work into separate threads to make max use of available cpu cores and speed up computation.
+    HeightmapThreadData threadData[THREAD_COUNT];
+    THREAD_HANDLE threads[THREAD_COUNT];
+    int stepSize = height / THREAD_COUNT;
+    for (int i = 0; i < THREAD_COUNT; ++i)
+    {
+        HeightmapThreadData& data = threadData[i];
+        data.rayHeight = rayOrigin.y;
+        data.rayDirection = &rayDirection;
+        data.bounds = &bounds;
+        data.meshes = &meshes;
+        data.minX = minX;
+        data.maxX = maxX;
+        data.minZ = minZ + (stepSize * i);
+        data.maxZ = data.minZ + stepSize - 1;
+        if (i == THREAD_COUNT - 1)
+            data.maxZ = maxZ;
+        data.heights = heights;
+        data.heightIndex = width * (stepSize * i);
+
+        // Start the processing thread
+        if (!createThread(&threads[i], &generateHeightmapChunk, &data))
+        {
+            LOG(1, "ERROR: Failed to spawn worker thread for generation of heightmap: %s\n", filename);
+            return;
+        }
+    }
+
+    // Wait for all threads to terminate
+    waitForThreads(THREAD_COUNT, threads);
+
+    // Close all thread handles and free memory allocations.
+    for (int i = 0; i < THREAD_COUNT; ++i)
+        closeThread(threads[i]);
+
+    // Update min/max height from all completed threads
+    for (int i = 0; i < THREAD_COUNT; ++i)
+    {
+        if (threadData[i].minHeight < minHeight)
+            minHeight = threadData[i].minHeight;
+        if (threadData[i].maxHeight > maxHeight)
+            maxHeight = threadData[i].maxHeight;
+    }
+
+    LOG(1, "\r\tDone.\n");
+
+    if (__failedRayCasts)
+    {
+        LOG(1, "Warning: %d triangle intersections failed for heightmap: %s\n", __failedRayCasts, filename);
+
+        // Go through and clamp any height values that are set to -FLT_MAX to the min recorded height value
+        // (otherwise the range of height values will be far too large).
+        for (int i = 0; i < size; ++i)
+        {
+            if (heights[i] == -FLT_MAX)
+                heights[i] = minHeight;
+        }
+    }
+    
+    // Normalize the max height value
+    maxHeight = maxHeight - minHeight;
+
+    png_structp png_ptr = NULL;
+    png_infop info_ptr = NULL;
+    png_bytep row = NULL;
+
+    FILE* fp = fopen(filename, "wb");
+    if (fp == NULL)
+    {
+        LOG(1, "Error: Failed to open file for writing: %s\n", filename);
+        goto error;
+    }
+
+    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (png_ptr == NULL)
+    {
+        LOG(1, "Error: Write struct creation failed: %s\n", filename);
+        goto error;
+    }
+
+    info_ptr = png_create_info_struct(png_ptr);
+    if (info_ptr == NULL)
+    {
+        LOG(1, "Error: Info struct creation failed: %s\n", filename);
+        goto error;
+    }
+
+    png_init_io(png_ptr, fp);
+
+    png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+    png_write_info(png_ptr, info_ptr);
+
+    // Allocate memory for a single row of image data
+    row = (png_bytep)malloc(3 * width * sizeof(png_byte));
+
+    for (int y = 0; y < height; y++)
+    {
+        for (int x = 0; x < width; x++)
+        {
+            // Write height value normalized between 0-255 (between min and max height)
+            float h = heights[y*width + x];
+            float nh = (h - minHeight) / maxHeight;
+            int pos = x*3;
+            if (highP)
+            {
+                // high precision packed 24-bit (RGB)
+                int bits = (int)(nh * 16777215.0f); // 2^24-1
+                
+                row[pos+2] = (png_byte)(bits & 0xff);
+                bits >>= 8;
+                row[pos+1] = (png_byte)(bits & 0xff);
+                bits >>= 8;
+                row[pos] = (png_byte)(bits & 0xff);
+            }
+            else
+            {
+                // standard precision 8-bit (grayscale)
+                png_byte b = (png_byte)(nh * 255.0f);
+                row[pos] = row[pos+1] = row[pos+2] = b;
+            }
+        }
+        png_write_row(png_ptr, row);
+    }
+
+    png_write_end(png_ptr, NULL);
+    LOG(1, "Saved heightmap: %s\n", filename);
+
+error:
+    if (heights)
+        delete[] heights;
+    if (fp)
+        fclose(fp);
+    if (row)
+        free(row);
+    if (info_ptr)
+        png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+    if (png_ptr)
+        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+}
+
+int generateHeightmapChunk(void* threadData)
+{
+    HeightmapThreadData* data = (HeightmapThreadData*)threadData;
+
+    Vector3 rayOrigin(0, data->rayHeight, 0);
+    const Vector3& rayDirection = *data->rayDirection;
+    int minX = data->minX;
+    int maxX = data->maxX;
+    int minZ = data->minZ;
+    int maxZ = data->maxZ;
+    const std::vector<Mesh*>& meshes = *data->meshes;
+    float* heights = data->heights;
+
+    Vector3 intersectionPoint;
+    float minHeight = FLT_MAX;
+    float maxHeight = -FLT_MAX;
+    int index = data->heightIndex;
+
+    for (int z = minZ; z <= maxZ; ++z)
+    {
+        LOG(1, "\r\t%d%%", (int)(((float)__processedHeightmapScanLines / __totalHeightmapScanlines) * 100.0f));
+
+        rayOrigin.z = (float)z;
+        for (int x = minX; x <= maxX; ++x)
+        {
+            float h = -FLT_MAX;
+            rayOrigin.x = (float)x;
+
+            for (unsigned int i = 0, count = meshes.size(); i < count; ++i)
+            {
+                // Pick the highest intersecting Y value of all meshes
+                Mesh* mesh = meshes[i];
+
+                // Perform a quick ray/bounding box test to quick-out
+                if (!intersect(rayOrigin, rayDirection, mesh->bounds.min, mesh->bounds.max))
+                    continue;
+
+                // Computer intersection point of ray with mesh
+                if (intersect(rayOrigin, rayDirection, mesh->vertices, mesh->parts, &intersectionPoint))
+                {
+                    if (intersectionPoint.y > h)
+                    {
+                        h = intersectionPoint.y;
+
+                        // Update min/max height values
+                        if (h < minHeight)
+                            minHeight = h;
+                        if (h > maxHeight)
+                            maxHeight = h;
+                    }
+                }
+            }
+
+            // Update the glboal height array
+            heights[index++] = h;
+
+            if (h == -FLT_MAX)
+                ++__failedRayCasts;
+        }
+
+        ++__processedHeightmapScanLines;
+    }
+
+    // Update min/max height for this thread data
+    data->minHeight = minHeight;
+    data->maxHeight = maxHeight;
+
+    return 0;
+}
+
+/////////////////////////////////////////////////////////////
+// 
+// Fast, Minimum Storage Ray-Triangle Intersection
+// 
+// Authors: Tomas Möller, Ben Trumbore
+// http://jgt.akpeters.com/papers/MollerTrumbore97
+//
+// Implementation of algorithm from Real-Time Rendering (vol 1), pg. 305.
+//
+// Adapted slightly for use here.
+// 
+#ifndef EPSILON
+#define EPSILON 0.000001
+#endif
+#define CROSS(dest,v1,v2) \
+          dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
+          dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
+          dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
+#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
+#define SUB(dest,v1,v2) \
+          dest[0]=v1[0]-v2[0]; \
+          dest[1]=v1[1]-v2[1]; \
+          dest[2]=v1[2]-v2[2]; 
+int intersect_triangle(const float orig[3], const float dir[3], const float vert0[3], const float vert1[3], const float vert2[3], float *t, float *u, float *v)
+{
+   float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
+   float det,inv_det;
+
+   /* find vectors for two edges sharing vert0 */
+   SUB(edge1, vert1, vert0);
+   SUB(edge2, vert2, vert0);
+
+   /* begin calculating determinant - also used to calculate U parameter */
+   CROSS(pvec, dir, edge2);
+
+   /* if determinant is near zero, ray lies in plane of triangle */
+   det = DOT(edge1, pvec);
+
+   if (det > -EPSILON && det < EPSILON)
+     return 0;
+   inv_det = 1.0f / det;
+
+   /* calculate distance from vert0 to ray origin */
+   SUB(tvec, orig, vert0);
+
+   /* calculate U parameter and test bounds */
+   *u = DOT(tvec, pvec) * inv_det;
+   if (*u < 0.0 || *u > 1.0)
+     return 0;
+
+   /* prepare to test V parameter */
+   CROSS(qvec, tvec, edge1);
+
+   /* calculate V parameter and test bounds */
+   *v = DOT(dir, qvec) * inv_det;
+   if (*v < 0.0 || *u + *v > 1.0)
+     return 0;
+
+   /* calculate t, ray intersects triangle */
+   *t = DOT(edge2, qvec) * inv_det;
+
+   return 1;
+}
+
+// Performs an intersection test between a ray and the given mesh part and stores the result in "point".
+bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const std::vector<Vertex>& vertices, const std::vector<MeshPart*>& parts, Vector3* point)
+{
+    const float* orig = &rayOrigin.x;
+    const float* dir = &rayDirection.x;
+
+    float minT = FLT_MAX;
+
+    for (unsigned int i = 0, partCount = parts.size(); i < partCount; ++i)
+    {
+        MeshPart* part = parts[i];
+
+        for (unsigned int j = 0, indexCount = part->getIndicesCount(); j < indexCount; j += 3)
+        {
+            const float* v0 = &vertices[part->getIndex( j )].position.x;
+            const float* v1 = &vertices[part->getIndex(j+1)].position.x;
+            const float* v2 = &vertices[part->getIndex(j+2)].position.x;
+
+            // Perform a quick check (in 2D) to determine if the point is definitely NOT in the triangle
+            float xmin, xmax, zmin, zmax;
+            xmin = v0[0] < v1[0] ? v0[0] : v1[0]; xmin = xmin < v2[0] ? xmin : v2[0];
+            xmax = v0[0] > v1[0] ? v0[0] : v1[0]; xmax = xmax > v2[0] ? xmax : v2[0];
+            zmin = v0[2] < v1[2] ? v0[2] : v1[2]; zmin = zmin < v2[2] ? zmin : v2[2];
+            zmax = v0[2] > v1[2] ? v0[2] : v1[2]; zmax = zmax > v2[2] ? zmax : v2[2];
+            if (orig[0] < xmin || orig[0] > xmax || orig[2] < zmin || orig[2] > zmax)
+                continue;
+
+            // Perform a full ray/traingle intersection test in 3D to get the intersection point
+            float t, u, v;
+            if (intersect_triangle(orig, dir, v0, v1, v2, &t, &u, &v))
+            {
+                // Found an intersection!
+                if (t < minT)
+                {
+                    minT = t;
+
+                    if (point)
+                    {
+                        Vector3 rd(rayDirection);
+                        rd.scale(t);
+                        Vector3::add(rayOrigin, rd, point);
+                    }
+                }
+                //return true;
+            }
+        }
+    }
+
+    return (minT != FLT_MAX);//false;
+}
+
+// Ray/Box intersection test.
+bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const Vector3& boxMin, const Vector3& boxMax, float* distance)
+{
+    const Vector3& origin = rayOrigin;
+    const Vector3& direction = rayDirection;
+    const Vector3& min = boxMin;
+    const Vector3& max = boxMax;
+
+    // Intermediate calculation variables.
+    float dnear = 0.0f;
+    float dfar = 0.0f;
+    float tmin = 0.0f;
+    float tmax = 0.0f;
+
+    // X direction.
+    float div = 1.0f / direction.x;
+    if (div >= 0.0f)
+    {
+        tmin = (min.x - origin.x) * div;
+        tmax = (max.x - origin.x) * div;
+    }
+    else
+    {
+        tmin = (max.x - origin.x) * div;
+        tmax = (min.x - origin.x) * div;
+    }
+    dnear = tmin;
+    dfar = tmax;
+
+    // Check if the ray misses the box.
+    if (dnear > dfar || dfar < 0.0f)
+    {
+        return false;
+    }
+
+    // Y direction.
+    div = 1.0f / direction.y;
+    if (div >= 0.0f)
+    {
+        tmin = (min.y - origin.y) * div;
+        tmax = (max.y - origin.y) * div;
+    }
+    else
+    {
+        tmin = (max.y - origin.y) * div;
+        tmax = (min.y - origin.y) * div;
+    }
+
+    // Update the near and far intersection distances.
+    if (tmin > dnear)
+    {
+        dnear = tmin;
+    }
+    if (tmax < dfar)
+    {
+        dfar = tmax;
+    }
+    // Check if the ray misses the box.
+    if (dnear > dfar || dfar < 0.0f)
+    {
+        return false;
+    }
+
+    // Z direction.
+    div = 1.0f / direction.z;
+    if (div >= 0.0f)
+    {
+        tmin = (min.z - origin.z) * div;
+        tmax = (max.z - origin.z) * div;
+    }
+    else
+    {
+        tmin = (max.z - origin.z) * div;
+        tmax = (min.z - origin.z) * div;
+    }
+
+    // Update the near and far intersection distances.
+    if (tmin > dnear)
+    {
+        dnear = tmin;
+    }
+    if (tmax < dfar)
+    {
+        dfar = tmax;
+    }
+
+    // Check if the ray misses the box.
+    if (dnear > dfar || dfar < 0.0f)
+    {
+        return false;
+    }
+
+    // The ray intersects the box
+    if (distance)
+        *distance = dnear;
+
+    return true;
+}
+
+}

+ 27 - 0
gameplay-encoder/src/Heightmap.h

@@ -0,0 +1,27 @@
+#ifndef HEIGHTMAP_H_
+#define HEIGHTMAP_H_
+
+#include "Node.h"
+
+namespace gameplay
+{
+
+class Heightmap
+{
+public:
+
+    /**
+     * Generates heightmap data and saves the result to the specified filename (PNG file).
+     *
+     * @param nodeIds List of node ids to include in the heightmap generation.
+     * @param filename Output PNG file to write the heightmap image to.
+     * @param highP Use packed 24-bit (RGB) instead of standard 8-bit grayscale.
+     */
+    static void generate(const std::vector<std::string>& nodeIds, const char* filename, bool highP = false);
+
+
+};
+
+}
+
+#endif

+ 1 - 1
gameplay-encoder/src/Light.cpp

@@ -224,7 +224,7 @@ void Light::setFalloffExponent(float value)
     _falloffExponent = value;
     if ( value != 1.0)
     {
-        printf("Warning: spot light falloff_exponent must be 1.0. \n");
+        LOG(1, "Warning: spot light falloff_exponent must be 1.0. \n");
     }
 }
 

+ 4 - 228
gameplay-encoder/src/Mesh.cpp

@@ -28,7 +28,7 @@ void Mesh::writeBinary(FILE* file)
     Object::writeBinary(file);
     // vertex formats
     write(_vertexFormat.size(), file);
-    for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); i++)
+    for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); ++i)
     {
         i->writeBinary(file);
     }
@@ -38,232 +38,6 @@ void Mesh::writeBinary(FILE* file)
     writeBinaryObjects(parts, file);
 }
 
-/////////////////////////////////////////////////////////////
-// 
-// Fast, Minimum Storage Ray-Triangle Intersection
-// 
-// Authors: Tomas Möller, Ben Trumbore
-// http://jgt.akpeters.com/papers/MollerTrumbore97
-//
-// Implementation of algorithm from Real-Time Rendering (vol 1), pg. 305.
-//
-// Adapted slightly for use here.
-// 
-#define EPSILON 0.000001
-#define CROSS(dest,v1,v2) \
-          dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
-          dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
-          dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
-#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
-#define SUB(dest,v1,v2) \
-          dest[0]=v1[0]-v2[0]; \
-          dest[1]=v1[1]-v2[1]; \
-          dest[2]=v1[2]-v2[2]; 
-
-int
-intersect_triangle(const float orig[3], const float dir[3],
-                   const float vert0[3], const float vert1[3], const float vert2[3],
-                   float *t, float *u, float *v)
-{
-   float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
-   float det,inv_det;
-
-   /* find vectors for two edges sharing vert0 */
-   SUB(edge1, vert1, vert0);
-   SUB(edge2, vert2, vert0);
-
-   /* begin calculating determinant - also used to calculate U parameter */
-   CROSS(pvec, dir, edge2);
-
-   /* if determinant is near zero, ray lies in plane of triangle */
-   det = DOT(edge1, pvec);
-
-   if (det > -EPSILON && det < EPSILON)
-     return 0;
-   inv_det = 1.0f / det;
-
-   /* calculate distance from vert0 to ray origin */
-   SUB(tvec, orig, vert0);
-
-   /* calculate U parameter and test bounds */
-   *u = DOT(tvec, pvec) * inv_det;
-   if (*u < 0.0 || *u > 1.0)
-     return 0;
-
-   /* prepare to test V parameter */
-   CROSS(qvec, tvec, edge1);
-
-   /* calculate V parameter and test bounds */
-   *v = DOT(dir, qvec) * inv_det;
-   if (*v < 0.0 || *u + *v > 1.0)
-     return 0;
-
-   /* calculate t, ray intersects triangle */
-   *t = DOT(edge2, qvec) * inv_det;
-
-   return 1;
-}
-
-// Performs an intersection test between a ray and the given mesh part
-// and stores the result in "point".
-bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const std::vector<Vertex>& vertices, const std::vector<MeshPart*>& parts, Vector3* point)
-{
-    const float* orig = &rayOrigin.x;
-    const float* dir = &rayDirection.x;
-
-    for (unsigned int i = 0, partCount = parts.size(); i < partCount; ++i)
-    {
-        MeshPart* part = parts[i];
-
-        for (unsigned int j = 0, indexCount = part->getIndicesCount(); j < indexCount; j += 3)
-        {
-            const float* v0 = &vertices[part->getIndex( j )].position.x;
-            const float* v1 = &vertices[part->getIndex(j+1)].position.x;
-            const float* v2 = &vertices[part->getIndex(j+2)].position.x;
-
-            float t, u, v;
-            if (intersect_triangle(orig, dir, v0, v1, v2, &t, &u, &v))
-            {
-                // Found an intersection!
-                if (point)
-                {
-                    Vector3 rd(rayDirection);
-                    rd.scale(t);
-                    Vector3::add(rayOrigin, rd, point);
-                }
-                return true;
-            }
-        }
-    }
-
-    return false;
-}
-
-void Mesh::generateHeightmap(const char* filename, bool highP)
-{
-    // Shoot rays down from a point just above the max Y position of the mesh.
-    // Compute ray-triangle intersection tests against the ray and this mesh to 
-    // generate heightmap data.
-    Vector3 rayOrigin(0, bounds.max.y + 10, 0);
-    Vector3 rayDirection(0, -1, 0);
-    Vector3 intersectionPoint;
-    int minX = (int)ceil(bounds.min.x);
-    int maxX = (int)floor(bounds.max.x);
-    int minZ = (int)ceil(bounds.min.z);
-    int maxZ = (int)floor(bounds.max.z);
-    int width = maxX - minX + 1;
-    int height = maxZ - minZ + 1;
-    float* heights = new float[width * height];
-    int index = 0;
-    float minHeight = FLT_MAX;
-    float maxHeight = -FLT_MAX;
-    for (int z = minZ; z <= maxZ; z++)
-    {
-        rayOrigin.z = (float)z;
-        for (int x = minX; x <= maxX; x++)
-        {
-            float h;
-            rayOrigin.x = (float)x;
-            if (intersect(rayOrigin, rayDirection, vertices, parts, &intersectionPoint))
-            {
-                h = intersectionPoint.y;
-            }
-            else
-            {
-                h = 0;
-                fprintf(stderr, "Warning: Heightmap triangle intersection failed for (%d, %d).\n", x, z);
-            }
-            if (h < minHeight)
-                minHeight = h;
-            if (h > maxHeight)
-                maxHeight = h;
-            heights[index++] = h;
-        }
-    }
-    
-    // Normalize the max height value
-    maxHeight = maxHeight - minHeight;
-
-    png_structp png_ptr = NULL;
-    png_infop info_ptr = NULL;
-    png_bytep row = NULL;
-
-    FILE* fp = fopen(filename, "wb");
-    if (fp == NULL)
-    {
-        fprintf(stderr, "Error: Failed to open file for writing: %s\n", filename);
-        goto error;
-    }
-
-    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-    if (png_ptr == NULL)
-    {
-        fprintf(stderr, "Error: Write struct creation failed: %s\n", filename);
-        goto error;
-    }
-
-    info_ptr = png_create_info_struct(png_ptr);
-    if (info_ptr == NULL)
-    {
-        fprintf(stderr, "Error: Info struct creation failed: %s\n", filename);
-        goto error;
-    }
-
-    png_init_io(png_ptr, fp);
-
-    png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
-    png_write_info(png_ptr, info_ptr);
-
-    // Allocate memory for a single row of image data
-    row = (png_bytep)malloc(3 * width * sizeof(png_byte));
-
-    for (int y = 0; y < height; y++)
-    {
-        for (int x = 0; x < width; x++)
-        {
-            // Write height value normalized between 0-255 (between min and max height)
-            float h = heights[y*width + x];
-            float nh = (h - minHeight) / maxHeight;
-            int pos = x*3;
-            if (highP)
-            {
-                // high precision packed 24-bit (RGB)
-                int bits = (int)(nh * 16777215.0f); // 2^24-1
-
-                row[pos+2] = (png_byte)(bits & 0xff);
-                bits >>= 8;
-                row[pos+1] = (png_byte)(bits & 0xff);
-                bits >>= 8;
-                row[pos] = (png_byte)(bits & 0xff);
-            }
-            else
-            {
-                // standard precision 8-bit (grayscale)
-                png_byte b = (png_byte)(nh * 255.0f);
-                row[pos] = row[pos+1] = row[pos+2] = b;
-            }
-        }
-        png_write_row(png_ptr, row);
-    }
-
-    png_write_end(png_ptr, NULL);
-    DEBUGPRINT_VARG("> Saved heightmap: %s\n", filename);
-
-error:
-    if (heights)
-        delete[] heights;
-    if (fp)
-        fclose(fp);
-    if (row)
-        free(row);
-    if (info_ptr)
-        png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-    if (png_ptr)
-        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
-
-}
-
 void Mesh::writeBinaryVertices(FILE* file)
 {
     if (vertices.size() > 0)
@@ -300,7 +74,7 @@ void Mesh::writeText(FILE* file)
     // for each VertexFormat
     if (vertices.size() > 0 )
     {
-        for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); i++)
+        for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); ++i)
         {
             i->writeText(file);
         }
@@ -403,6 +177,8 @@ void Mesh::computeBounds()
         return;
     }
 
+    LOG(2, "Computing bounds for mesh: %s\n", getId().c_str());
+
     bounds.min.x = bounds.min.y = bounds.min.z = FLT_MAX;
     bounds.max.x = bounds.max.y = bounds.max.z = -FLT_MAX;
     bounds.center.x = bounds.center.y = bounds.center.z = 0.0f;

+ 0 - 7
gameplay-encoder/src/Mesh.h

@@ -60,13 +60,6 @@ public:
 
     unsigned int getVertexIndex(const Vertex& vertex);
 
-    /**
-     * Generates a heightmap with the given filename for this mesh.
-     * Optional high precision uses packed 24-bit (RGB) instead of
-     * standard 8-bit grayscale.
-     */
-    void generateHeightmap(const char* filename, bool highP = false);
-
     void computeBounds();
 
     Model* model;

+ 19 - 19
gameplay-encoder/src/MeshSkin.cpp

@@ -37,12 +37,12 @@ void MeshSkin::writeBinary(FILE* file)
     Object::writeBinary(file);
     write(_bindShape, 16, file);
     write(_joints.size(), file);
-    for (std::vector<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); i++)
+    for (std::vector<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); ++i)
     {
         (*i)->writeBinaryXref(file);
     }
     write(_bindPoses.size() * 16, file);
-    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); i++)
+    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
     {
         write(i->m, 16, file);
     }
@@ -68,13 +68,13 @@ void MeshSkin::writeText(FILE* file)
     fprintfMatrix4f(file, _bindShape);
     fprintf(file, "</bindShape>");
     fprintf(file, "<joints>");
-    for (std::vector<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); i++)
+    for (std::vector<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
     {
         fprintf(file, "%s ", i->c_str());
     }
     fprintf(file, "</joints>\n");
     fprintf(file, "<bindPoses count=\"%lu\">", _bindPoses.size() * 16);
-    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); i++)
+    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
     {
         for (unsigned int j = 0; j < 16; ++j)
         {
@@ -129,7 +129,7 @@ void MeshSkin::setBindPoses(std::vector<Matrix>& list)
 
 bool MeshSkin::hasJoint(const char* id)
 {
-    for (std::vector<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); i++)
+    for (std::vector<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
     {
         if (equals(*i, id))
         {
@@ -163,7 +163,7 @@ void MeshSkin::computeBounds()
         return;
     }
 
-    DEBUGPRINT_VARG("\nComputing bounds for skin of mesh: %s\n", _mesh->getId().c_str());
+    LOG(2, "Computing bounds for skin of mesh: %s\n", _mesh->getId().c_str());
 
     Node* joint;
 
@@ -192,7 +192,7 @@ void MeshSkin::computeBounds()
     unsigned int jointCount = _joints.size();
     unsigned int vertexCount = _mesh->getVertexCount();
 
-    DEBUGPRINT_VARG("> %d joints found.\n", jointCount);
+    LOG(3, "  %u joints found.\n", jointCount);
 
     std::vector<AnimationChannel*> channels;
     std::vector<Node*> channelTargets;
@@ -201,8 +201,8 @@ void MeshSkin::computeBounds()
     _jointBounds.resize(jointCount);
 
     // Construct a list of all animation channels that target the joints affecting this mesh skin
-    DEBUGPRINT("> Collecting animations...\n");
-    DEBUGPRINT("> 0%%\r");
+    LOG(3, "  Collecting animations...\n");
+    LOG(3, "  0%%\r");
     for (unsigned int i = 0; i < jointCount; ++i)
     {
         joint = _joints[i];
@@ -272,16 +272,16 @@ void MeshSkin::computeBounds()
         }
         _jointBounds[i] = jointBounds;
 
-        DEBUGPRINT_VARG("> %d%%\r", (int)((float)(i+1) / (float)jointCount * 100.0f));
+        LOG(3, "  %d%%\r", (int)((float)(i+1) / (float)jointCount * 100.0f));
     }
-    DEBUGPRINT("\n");
+    LOG(3, "\n");
 
     unsigned int channelCount = channels.size();
 
     // Create a Curve for each animation channel
     float maxDuration = 0.0f;
-    DEBUGPRINT("> Building animation curves...\n");
-    DEBUGPRINT("> 0%%\r");
+    LOG(3, "  Building animation curves...\n");
+    LOG(3, "  0%%\r");
     for (unsigned int i = 0; i < channelCount; ++i)
     {
         AnimationChannel* channel = channels[i];
@@ -340,9 +340,9 @@ void MeshSkin::computeBounds()
         delete[] keyValues;
         keyValues = NULL;
 
-        DEBUGPRINT_VARG("> %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
+        LOG(3, "  %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
     }
-    DEBUGPRINT("\n");
+    LOG(3, "\n");
 
     // Compute a total combined bounding volume for the MeshSkin that contains all possible
     // vertex positions for all animations targeting the skin. This rough approximation allows
@@ -366,8 +366,8 @@ void MeshSkin::computeBounds()
     _mesh->bounds.radius = 0;
     Vector3 skinnedPos;
     Vector3 tempPos;
-    DEBUGPRINT("> Evaluating joints...\n");
-    DEBUGPRINT("> 0%%\r");
+    LOG(3, "  Evaluating joints...\n");
+    LOG(3, "  0%%\r");
     BoundingVolume finalBounds;
     while (time <= maxDuration)
     {
@@ -416,9 +416,9 @@ void MeshSkin::computeBounds()
         else
             time += 33.0f;
 
-        DEBUGPRINT_VARG("> %d%%\r", (int)(time / maxDuration * 100.0f));
+        LOG(3, "  %d%%\r", (int)(time / maxDuration * 100.0f));
     }
-    DEBUGPRINT("\n");
+    LOG(3, "\n");
 
     // Update the bounding sphere for the mesh
     _mesh->bounds = finalBounds;

+ 0 - 25
gameplay-encoder/src/Node.cpp

@@ -78,8 +78,6 @@ void Node::writeBinary(FILE* file)
     {
         writeZero(file);
     }
-
-    generateHeightmap();
 }
 
 void Node::writeText(FILE* file)
@@ -117,29 +115,6 @@ void Node::writeText(FILE* file)
         _model->writeText(file);
     }
     fprintElementEnd(file);
-
-    generateHeightmap();
-}
-
-void Node::generateHeightmap()
-{
-    // Is this node flagged to have a heightmap generated for it?
-    const std::vector<std::string>& heightmapNodes = EncoderArguments::getInstance()->getHeightmapNodeIds();
-    if (std::find(heightmapNodes.begin(), heightmapNodes.end(), getId()) != heightmapNodes.end())
-    {
-        Mesh* mesh = _model ? _model->getMesh() : NULL;
-        if (mesh)
-        {
-            DEBUGPRINT_VARG("> Generating heightmap for node: %s\n", getId().c_str());
-
-            std::string heightmapFilename(EncoderArguments::getInstance()->getOutputDirPath());
-            heightmapFilename += "/heightmap_";
-            heightmapFilename += getId();
-            heightmapFilename += ".png";
-
-            mesh->generateHeightmap(heightmapFilename.c_str(), EncoderArguments::getInstance()->isHeightmapHighP());
-        }
-    }
 }
 
 void Node::addChild(Node* child)

+ 0 - 6
gameplay-encoder/src/Node.h

@@ -171,12 +171,6 @@ public:
     
 private:
 
-    /**
-     * Internal method to generate heightmap for a node's mesh data
-     * if the node was flagged as a heightmap via encoder arguments.
-     */
-    void generateHeightmap();
-
     Matrix _transform;
     mutable Matrix _worldTransform;
 

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

@@ -2,6 +2,7 @@
 #define OBJ_H_
 
 #include "FileIO.h"
+#include "Base.h"
 
 namespace gameplay
 {

+ 3 - 3
gameplay-encoder/src/Quaternion.cpp

@@ -52,7 +52,7 @@ bool Quaternion::isIdentity() const
 
 bool Quaternion::isZero() const
 {
-    return x == 0.0f && y == 0.0f && z == 0.0f && z == 0.0f;
+    return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
 }
 
 void Quaternion::createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst)
@@ -60,14 +60,14 @@ void Quaternion::createFromAxisAngle(const Vector3& axis, float angle, Quaternio
     assert(dst);
 
     float halfAngle = angle * 0.5f;
-    float sinHalfAngle = sinf(halfAngle);
+    float sinHalfAngle = sin(halfAngle);
 
     Vector3 normal(axis);
     normal.normalize();
     dst->x = normal.x * sinHalfAngle;
     dst->y = normal.y * sinHalfAngle;
     dst->z = normal.z * sinHalfAngle;
-    dst->w = cosf(halfAngle);
+    dst->w = cos(halfAngle);
 }
 
 void Quaternion::conjugate()

+ 12 - 12
gameplay-encoder/src/TTFFontEncoder.cpp

@@ -43,7 +43,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
     FT_Error error = FT_Init_FreeType(&library);
     if (error)
     {
-        fprintf(stderr, "FT_Init_FreeType error: %d \n", error);
+        LOG(1, "FT_Init_FreeType error: %d \n", error);
         return -1;
     }
     
@@ -52,7 +52,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
     error = FT_New_Face(library, inFilePath, 0, &face);
     if (error)
     {
-        fprintf(stderr, "FT_New_Face error: %d \n", error);
+        LOG(1, "FT_New_Face error: %d \n", error);
         return -1;
     }
     
@@ -66,7 +66,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
     
     if (error)
     {
-        fprintf(stderr, "FT_Set_Char_Size error: %d \n", error);
+        LOG(1, "FT_Set_Char_Size error: %d \n", error);
         return -1;
     }
 
@@ -74,7 +74,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
     error = FT_Set_Pixel_Sizes(face, FONT_SIZE, 0);
     if (error)
     {
-        fprintf(stderr, "FT_Set_Pixel_Sizes error : %d \n", error);
+        LOG(1, "FT_Set_Pixel_Sizes error : %d \n", error);
         exit(1);
     }
     */
@@ -92,7 +92,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
         error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
         if (error)
         {
-            fprintf(stderr, "FT_Load_Char error : %d \n", error);
+            LOG(1, "FT_Load_Char error : %d \n", error);
         }
         
         int bitmapRows = slot->bitmap.rows;
@@ -137,7 +137,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
             error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
             if (error)
             {
-                fprintf(stderr, "FT_Load_Char error : %d \n", error);
+                LOG(1, "FT_Load_Char error : %d \n", error);
             }
 
             // Glyph image.
@@ -204,7 +204,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
         error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
         if (error)
         {
-            fprintf(stderr, "FT_Load_Char error : %d \n", error);
+            LOG(1, "FT_Load_Char error : %d \n", error);
         }
 
         // Glyph image.
@@ -222,10 +222,10 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
             penY = row * rowSize;
             if (penY + rowSize > (int)imageHeight)
             {
-                fprintf(stderr, "Image size exceeded!");
-               return -1;
+                free(imageBuffer);
+				LOG(1, "Image size exceeded!");
+				return -1;
             }
-
         }
         
         // penY should include the glyph offsets.
@@ -298,7 +298,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
     // Close file.
     fclose(gpbFp);
 
-    printf("%s.gpb created successfully. \n", getBaseName(outFilePath).c_str());
+    LOG(1, "%s.gpb created successfully. \n", getBaseName(outFilePath).c_str());
 
     if (fontpreview)
     {
@@ -306,7 +306,7 @@ int writeFont(const char* inFilePath, const char* outFilePath, unsigned int font
         std::string pgmFilePath = getFilenameNoExt(outFilePath);
         pgmFilePath.append(".pgm");
         FILE *imageFp = fopen(pgmFilePath.c_str(), "wb");
-        fprintf(imageFp, "P5 %d %d 255\n", imageWidth, imageHeight);
+        fprintf(imageFp, "P5 %u %u 255\n", imageWidth, imageHeight);
         fwrite((const char *)imageBuffer, sizeof(unsigned char), imageWidth * imageHeight, imageFp);
         fclose(imageFp);
     }

+ 99 - 0
gameplay-encoder/src/Thread.h

@@ -0,0 +1,99 @@
+#ifndef THREAD_H_
+#define THREAD_H_
+
+namespace gameplay
+{
+
+#ifdef WIN32
+
+    #include <Windows.h>
+
+    typedef HANDLE THREAD_HANDLE;
+
+    struct WindowsThreadData
+    {
+        int(*threadFunction)(void*);
+        void* arg;
+    };
+
+    DWORD WINAPI WindowsThreadProc(LPVOID lpParam)
+    {
+        WindowsThreadData* data = (WindowsThreadData*)lpParam;
+        int(*threadFunction)(void*) = data->threadFunction;
+        void* arg = data->arg;
+        delete data;
+        data = NULL;
+        return threadFunction(arg);
+    }
+
+    static bool createThread(THREAD_HANDLE* handle, int(*threadFunction)(void*), void* arg)
+    {
+        WindowsThreadData* data = new WindowsThreadData();
+        data->threadFunction = threadFunction;
+        data->arg = arg;
+        *handle = CreateThread(NULL, 0, &WindowsThreadProc, data, 0, NULL);
+        return (*handle != NULL);
+    }
+
+    static void waitForThreads(int count, THREAD_HANDLE* threads)
+    {
+        WaitForMultipleObjects(count, threads, TRUE, INFINITE);
+    }
+
+    static void closeThread(THREAD_HANDLE thread)
+    {
+        CloseHandle(thread);
+    }
+
+#else
+
+    #include <pthread.h>
+
+    typedef pthread_t THREAD_HANDLE;
+
+    struct PThreadData
+    {
+        int(*threadFunction)(void*);
+        void* arg;
+    };
+
+    void* PThreadProc(void* threadData)
+    {
+        PThreadData* data = (PThreadData*)threadData;
+        int(*threadFunction)(void*) = data->threadFunction;
+        void* arg = data->arg;
+        delete data;
+        data = NULL;
+        int retVal = threadFunction(arg);
+        pthread_exit((void*)retVal);
+    }
+
+    static bool createThread(THREAD_HANDLE* handle, int(*threadFunction)(void*), void* arg)
+    {
+        PThreadData* data = new PThreadData();
+        data->threadFunction = threadFunction;
+        data->arg = arg;
+        return pthread_create(handle, NULL, &PThreadProc, data) == 0;
+    }
+
+    static void waitForThreads(int count, THREAD_HANDLE* threads)
+    {
+        // Call join on all threads to wait for them to terminate.
+        // This also frees any resources allocated by the threads,
+        // essentially cleaning them up.
+        for (int i = 0; i < count; ++i)
+        {
+            pthread_join(threads[i], NULL);
+        }
+    }
+
+    static void closeThread(THREAD_HANDLE thread)
+    {
+        // nothing to do... waitForThreads (which calls join) cleans up
+    }
+
+#endif
+
+}
+
+#endif

+ 11 - 32
gameplay-encoder/src/Transform.cpp

@@ -16,12 +16,6 @@ const char* Transform::getPropertyString(unsigned int prop)
             return "ANIMATE_SCALE_Y";
         case ANIMATE_SCALE_Z:
             return "ANIMATE_SCALE_Z";
-        case ANIMATE_SCALE_XY: 
-            return "ANIMATE_SCALE_XY";
-        case ANIMATE_SCALE_XZ: 
-            return "ANIMATE_SCALE_XZ";
-        case ANIMATE_SCALE_YZ:
-            return "ANIMATE_SCALE_YZ";
         case ANIMATE_ROTATE:
             return "ANIMATE_ROTATE";
         case ANIMATE_TRANSLATE: 
@@ -32,22 +26,14 @@ const char* Transform::getPropertyString(unsigned int prop)
             return "ANIMATE_TRANSLATE_Y";
         case ANIMATE_TRANSLATE_Z: 
             return "ANIMATE_TRANSLATE_Z";
-        case ANIMATE_TRANSLATE_XY: 
-            return "ANIMATE_TRANSLATE_XY";
-        case ANIMATE_TRANSLATE_XZ: 
-            return "ANIMATE_TRANSLATE_XZ";
-        case ANIMATE_TRANSLATE_YZ: 
-            return "ANIMATE_TRANSLATE_YZ";
         case ANIMATE_ROTATE_TRANSLATE: 
             return "ANIMATE_ROTATE_TRANSLATE";
         case ANIMATE_SCALE_ROTATE_TRANSLATE: 
             return "ANIMATE_SCALE_ROTATE_TRANSLATE";
-        case ANIMATE_ROTATE_X: 
-            return "ANIMATE_ROTATE_X";
-        case ANIMATE_ROTATE_Y: 
-            return "ANIMATE_ROTATE_Y";
-        case ANIMATE_ROTATE_Z: 
-            return "ANIMATE_ROTATE_Z";
+        case ANIMATE_SCALE_TRANSLATE:
+            return "ANIMATE_SCALE_TRANSLATE";
+        case ANIMATE_SCALE_ROTATE:
+            return "ANIMATE_SCALE_ROTATE";
         default:
             return "";
     }
@@ -57,31 +43,24 @@ unsigned int Transform::getPropertySize(unsigned int prop)
 {
     switch (prop)
     {
-        case ANIMATE_SCALE_ROTATE_TRANSLATE: 
+        case ANIMATE_SCALE_ROTATE_TRANSLATE:
             return 10;
-        case ANIMATE_ROTATE_TRANSLATE: 
+        case ANIMATE_ROTATE_TRANSLATE:
+        case ANIMATE_SCALE_ROTATE:
             return 7;
+        case ANIMATE_SCALE_TRANSLATE:
+            return 6;
         case ANIMATE_ROTATE:
             return 4;
         case ANIMATE_SCALE:
-        case ANIMATE_TRANSLATE: 
-            return 3;   
-        case ANIMATE_SCALE_XY: 
-        case ANIMATE_SCALE_XZ: 
-        case ANIMATE_SCALE_YZ:
-        case ANIMATE_TRANSLATE_XY: 
-        case ANIMATE_TRANSLATE_XZ: 
-        case ANIMATE_TRANSLATE_YZ: 
-            return 2;
+        case ANIMATE_TRANSLATE:
+            return 3;
         case ANIMATE_SCALE_X:
         case ANIMATE_SCALE_Y:
         case ANIMATE_SCALE_Z:
         case ANIMATE_TRANSLATE_X:
         case ANIMATE_TRANSLATE_Y:
         case ANIMATE_TRANSLATE_Z:
-        case ANIMATE_ROTATE_X: 
-        case ANIMATE_ROTATE_Y: 
-        case ANIMATE_ROTATE_Z: 
             return 1;
         default:
             return 0;

+ 10 - 9
gameplay-encoder/src/Transform.h

@@ -17,9 +17,6 @@ public:
         ANIMATE_SCALE_X = 2,
         ANIMATE_SCALE_Y = 3,
         ANIMATE_SCALE_Z = 4,
-        ANIMATE_SCALE_XY = 5,
-        ANIMATE_SCALE_XZ = 6,
-        ANIMATE_SCALE_YZ = 7,
 
         /**
          * Rotation animation property. Data=qx,qy,qz,qw (as quaternion).
@@ -33,22 +30,26 @@ public:
         ANIMATE_TRANSLATE_X = 10,
         ANIMATE_TRANSLATE_Y = 11,
         ANIMATE_TRANSLATE_Z = 12,
-        ANIMATE_TRANSLATE_XY = 13,
-        ANIMATE_TRANSLATE_XZ = 14,
-        ANIMATE_TRANSLATE_YZ = 15,
 
         /**
          * Rotation + Translation animation property(Rigid Body). Data=qx,qy,qz,qw,tx,ty,tz
          */
         ANIMATE_ROTATE_TRANSLATE = 16,
+
         /**
          * Scale, Rotation + Translation animation property. Data=sx,sy,sz,qx,qy,qz,qw,tx,ty,tz
          */
         ANIMATE_SCALE_ROTATE_TRANSLATE = 17,
 
-        ANIMATE_ROTATE_X = 18,
-        ANIMATE_ROTATE_Y = 19,
-        ANIMATE_ROTATE_Z = 20
+        /**
+         * Scale + Translation animation property. Data=sx,sy,sz,tx,ty,tz
+         */
+        ANIMATE_SCALE_TRANSLATE = 18,
+
+        /**
+         * Scale + Rotation animation property. Data=sx,sy,sz,qx,qy,qz,qw
+         */
+        ANIMATE_SCALE_ROTATE = 19
     };
 
     /**

+ 1 - 1
gameplay-encoder/src/Vector4.cpp

@@ -91,7 +91,7 @@ bool Vector4::isZero() const
 
 bool Vector4::isOne() const
 {
-    return x == 1.0f && y == 1.0f && z == 1.0f && z == 1.0f;
+    return x == 1.0f && y == 1.0f && z == 1.0f && w == 1.0f;
 }
 
 float Vector4::angle(const Vector4& v1, const Vector4& v2)

+ 19 - 8
gameplay-encoder/src/Vertex.cpp

@@ -5,8 +5,10 @@ namespace gameplay
 {
 
 Vertex::Vertex(void)
-    : hasNormal(false), hasTangent(false), hasBinormal(false), hasTexCoord(false), hasDiffuse(false), hasWeights(false)
+    : hasNormal(false), hasTangent(false), hasBinormal(false), hasDiffuse(false), hasWeights(false)
 {
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+        hasTexCoord[i] = false;
 }
 
 Vertex::~Vertex(void)
@@ -22,8 +24,11 @@ unsigned int Vertex::byteSize() const
         count += TANGENT_COUNT;
     if (hasBinormal)
         count += BINORMAL_COUNT;
-    if (hasTexCoord)
-        count += TEXCOORD_COUNT;
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+    {
+        if (hasTexCoord[i])
+            count += TEXCOORD_COUNT;
+    }
     if (hasWeights)
         count += BLEND_WEIGHTS_COUNT + BLEND_INDICES_COUNT;
     if (hasDiffuse)
@@ -46,9 +51,12 @@ void Vertex::writeBinary(FILE* file) const
     {
         writeVectorBinary(binormal, file);
     }
-    if (hasTexCoord)
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
     {
-        writeVectorBinary(texCoord, file);
+        if (hasTexCoord[i])
+        {
+            writeVectorBinary(texCoord[i], file);
+        }
     }
     if (hasDiffuse)
     {
@@ -80,10 +88,13 @@ void Vertex::writeText(FILE* file) const
         write("// binormal\n", file);
         writeVectorText(binormal, file);
     }
-    if (hasTexCoord)
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
     {
-        write("// texCoord\n", file);
-        writeVectorText(texCoord, file);
+        if (hasTexCoord[i])
+        {
+            write("// texCoord\n", file);
+            writeVectorText(texCoord[i], file);
+        }
     }
     if (hasDiffuse)
     {

+ 21 - 12
gameplay-encoder/src/Vertex.h

@@ -6,6 +6,9 @@
 #include "Vector3.h"
 #include "Vector4.h"
 
+// Maximum number of supported UV sets
+#define MAX_UV_SETS 8
+
 namespace gameplay
 {
 
@@ -36,13 +39,13 @@ public:
     Vector3 normal;
     Vector3 tangent;
     Vector3 binormal;
-    Vector2 texCoord;
+    Vector2 texCoord[MAX_UV_SETS];
     Vector4 diffuse;
 
     Vector4 blendWeights;
     Vector4 blendIndices;
 
-    bool hasNormal, hasTangent, hasBinormal, hasTexCoord, hasDiffuse, hasWeights;
+    bool hasNormal, hasTangent, hasBinormal, hasTexCoord[MAX_UV_SETS], hasDiffuse, hasWeights;
 
     inline bool operator<(const Vertex& v) const
     {
@@ -54,23 +57,24 @@ public:
                 {
                     if (binormal == v.binormal)
                     {
-                        if (texCoord == v.texCoord)
+                        if (diffuse == v.diffuse)
                         {
-                            if (diffuse == v.diffuse)
+                            if (blendWeights == v.blendWeights)
                             {
-                                if (blendWeights == v.blendWeights)
+                                if (blendIndices == v.blendIndices)
                                 {
-                                    if (blendIndices == v.blendIndices)
+                                    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
                                     {
-                                        return false;
+                                        if (!(texCoord[i] == v.texCoord[i]))
+                                            return texCoord[i] < v.texCoord[i];
                                     }
-                                    return blendIndices < v.blendIndices;
+                                    return false;
                                 }
-                                return blendWeights < v.blendWeights;
+                                return blendIndices < v.blendIndices;
                             }
-                            return diffuse < v.diffuse;
+                            return blendWeights < v.blendWeights;
                         }
-                        return texCoord < v.texCoord;
+                        return diffuse < v.diffuse;
                     }
                     return binormal < v.binormal;
                 }
@@ -83,7 +87,12 @@ public:
 
     inline bool operator==(const Vertex& v) const
     {
-        return position==v.position && normal==v.normal && tangent==v.tangent && binormal==v.binormal && texCoord==v.texCoord &&
+        for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+        {
+            if (!(texCoord[i] == v.texCoord[i]))
+                return false;
+        }
+        return position==v.position && normal==v.normal && tangent==v.tangent && binormal==v.binormal &&
             diffuse==v.diffuse && blendWeights==v.blendWeights && blendIndices==v.blendIndices;
     }
 

+ 4 - 4
gameplay-encoder/src/main.cpp

@@ -56,12 +56,12 @@ int main(int argc, const char** argv)
     // Check if the file exists.
     if (!arguments.fileExists())
     {
-        fprintf(stderr, "Error: File not found: %s\n", arguments.getFilePathPointer());
+        LOG(1, "Error: File not found: %s\n", arguments.getFilePathPointer());
         return -1;
     }
 
     // File exists
-    fprintf(stderr, "Encoding file: %s\n", arguments.getFilePathPointer());
+    LOG(1, "Encoding file: %s\n", arguments.getFilePathPointer());
 
     switch (arguments.getFileFormat())
     {
@@ -80,7 +80,7 @@ int main(int argc, const char** argv)
             fbxEncoder.write(realpath, arguments);
             break;
 #else
-            fprintf(stderr, "Error: FBX not enabled. Install the FBX SDK and use the preprocessor definition USE_FBX.\n");
+            LOG(1, "Error: FBX not enabled. Install the FBX SDK and use the preprocessor definition USE_FBX.\n");
             return -1;
 #endif
         }
@@ -104,7 +104,7 @@ int main(int argc, const char** argv)
         }
    default:
         {
-            fprintf(stderr, "Error: Unsupported file format: %s\n", arguments.getFilePathPointer());
+            LOG(1, "Error: Unsupported file format: %s\n", arguments.getFilePathPointer());
             return -1;
         }
     }

+ 23 - 15
gameplay-luagen/gameplay-luagen.doxyfile

@@ -1,4 +1,4 @@
-# Doxyfile 1.8.1
+# Doxyfile 1.8.0
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project
@@ -32,7 +32,7 @@ PROJECT_NAME           = gameplay
 # This could be handy for archiving the generated documentation or 
 # if some version control system is used.
 
-PROJECT_NUMBER         = 1.4.0
+PROJECT_NUMBER         = 1.5.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description 
 # for a project that appears at the top of each page and should give viewer 
@@ -564,6 +564,12 @@ MAX_INITIALIZER_LINES  = 30
 
 SHOW_USED_FILES        = NO
 
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
 # Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
 # This will remove the Files entry from the Quick Index and from the 
 # Folder Tree View (if specified). The default is YES.
@@ -948,23 +954,20 @@ HTML_COLORSTYLE_GAMMA  = 80
 
 HTML_TIMESTAMP         = YES
 
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
 # documentation will contain sections that can be hidden and shown after the 
-# page has loaded.
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
 
 HTML_DYNAMIC_SECTIONS  = NO
 
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of 
-# entries shown in the various tree structured indices initially; the user 
-# can expand and collapse entries dynamically later on. Doxygen will expand 
-# the tree to such a level that at most the specified number of entries are 
-# visible (unless a fully collapsed tree already exceeds this amount). 
-# So setting the number of entries 1 will produce a full collapsed tree by 
-# default. 0 is a special value representing an infinite number of entries 
-# and will result in a full expanded tree by default.
-
-HTML_INDEX_NUM_ENTRIES = 113
-
 # If the GENERATE_DOCSET tag is set to YES, additional index files 
 # will be generated that can be used as input for Apple's Xcode 3 
 # integrated development environment, introduced with OSX 10.5 (Leopard). 
@@ -1143,6 +1146,11 @@ GENERATE_TREEVIEW      = NO
 
 ENUM_VALUES_PER_LINE   = 4
 
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
 # used to set the initial width (in pixels) of the frame in which the tree 
 # is shown.
@@ -1705,7 +1713,7 @@ CALLER_GRAPH           = NO
 
 GRAPHICAL_HIERARCHY    = YES
 
-# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES 
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
 # then doxygen will show the dependencies a directory has on other directories 
 # in a graphical way. The dependency relations are determined by the #include 
 # relations between the files in the directories.

+ 4 - 2
gameplay-luagen/gameplay-luagen.vcxproj

@@ -57,11 +57,13 @@
     <LinkIncremental>true</LinkIncremental>
     <CustomBuildBeforeTargets>
     </CustomBuildBeforeTargets>
+    <OutDir>$(Configuration)\</OutDir>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <LinkIncremental>false</LinkIncremental>
     <CustomBuildBeforeTargets>
     </CustomBuildBeforeTargets>
+    <OutDir>$(Configuration)\</OutDir>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
@@ -76,7 +78,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalLibraryDirectories>..\external-deps\tinyxml2\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>..\external-deps\tinyxml2\lib\windows;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>tinyxml2.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <PreBuildEvent>
@@ -108,7 +110,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>..\external-deps\tinyxml2\lib\win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>..\external-deps\tinyxml2\lib\windows;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>tinyxml2.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <PreBuildEvent>

+ 70 - 70
gameplay-newproject.bat

@@ -127,7 +127,7 @@ echo.
 call:replacevar projPath "/" "\"
 
 REM Does this path already exist?
-if exist %projPath% (
+if exist "%projPath%" (
     echo.
     echo ERROR: Path '%projPath%' already exists, aborting.
     echo.
@@ -151,124 +151,124 @@ REM    rmdir /S /Q %projPath%
 
 REM Generate relative path from project folder to GamePlay folder
 set gpPath=%cd%
-call:makerelative gpPath %projPath%\
+call:makerelative gpPath "%projPath%\"
 call:replacevar gpPath "\" "/"
 
-mkdir %projPath%
-mkdir %projPath%\src
-mkdir %projPath%\res
+mkdir "%projPath%"
+mkdir "%projPath%\src"
+mkdir "%projPath%\res"
 
 REM Copy Microsoft Visual Studio project files
-copy gameplay-template\gameplay-template.vcxproj %projPath%\%projName%.vcxproj
-call:replace %projPath%\%projName%.vcxproj TEMPLATE_PROJECT "%projName%"
-call:replace %projPath%\%projName%.vcxproj TemplateGame "%className%"
-call:replace %projPath%\%projName%.vcxproj GAMEPLAY_PATH "%gpPath%"
+copy gameplay-template\gameplay-template.vcxproj "%projPath%\%projName%.vcxproj"
+call:replace "%projPath%\%projName%.vcxproj" TEMPLATE_PROJECT "%projName%"
+call:replace "%projPath%\%projName%.vcxproj" TemplateGame "%className%"
+call:replace "%projPath%\%projName%.vcxproj" GAMEPLAY_PATH "%gpPath%"
 
-copy gameplay-template\gameplay-template.vcxproj.filters %projPath%\%projName%.vcxproj.filters
-call:replace %projPath%\%projName%.vcxproj.filters TemplateGame "%className%"
+copy gameplay-template\gameplay-template.vcxproj.filters "%projPath%\%projName%.vcxproj.filters"
+call:replace "%projPath%\%projName%.vcxproj.filters" TemplateGame "%className%"
 
-copy gameplay-template\gameplay-template.vcxproj.user %projPath%\%projName%.vcxproj.user
-call:replace %projPath%\%projName%.vcxproj.user GAMEPLAY_PATH "%gpPath%"
+copy gameplay-template\gameplay-template.vcxproj.user "%projPath%\%projName%.vcxproj.user"
+call:replace "%projPath%\%projName%.vcxproj.user" GAMEPLAY_PATH "%gpPath%"
 
 REM Copy Apple XCode project files
-mkdir %projPath%\%projName%.xcodeproj
-copy gameplay-template\gameplay-template.xcodeproj\project.pbxproj %projPath%\%projName%.xcodeproj\project.pbxproj
-call:replace %projPath%\%projName%.xcodeproj\project.pbxproj GAMEPLAY_PATH "%gpPath%"
-call:replace %projPath%\%projName%.xcodeproj\project.pbxproj TemplateGame "%className%"
-call:replace %projPath%\%projName%.xcodeproj\project.pbxproj TEMPLATE_PROJECT "%projName%"
+mkdir "%projPath%\%projName%.xcodeproj"
+copy gameplay-template\gameplay-template.xcodeproj\project.pbxproj "%projPath%\%projName%.xcodeproj\project.pbxproj"
+call:replace "%projPath%\%projName%.xcodeproj\project.pbxproj" GAMEPLAY_PATH "%gpPath%"
+call:replace "%projPath%\%projName%.xcodeproj\project.pbxproj" TemplateGame "%className%"
+call:replace "%projPath%\%projName%.xcodeproj\project.pbxproj" TEMPLATE_PROJECT "%projName%"
 
-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-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%"
+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%"
-call:replace %projPath%\.cproject TEMPLATE_UUID "%uuid%"
-call:replace %projPath%\.cproject GAMEPLAY_PATH "%gpPath%"
+copy gameplay-template\template.cproject "%projPath%\.cproject"
+call:replace "%projPath%\.cproject" TEMPLATE_PROJECT "%projName%"
+call:replace "%projPath%\.cproject" TEMPLATE_UUID "%uuid%"
+call:replace "%projPath%\.cproject" GAMEPLAY_PATH "%gpPath%"
 
-copy gameplay-template\template.project %projPath%\.project
-call:replace %projPath%\.project TEMPLATE_PROJECT "%projName%"
+copy gameplay-template\template.project "%projPath%\.project"
+call:replace "%projPath%\.project" TEMPLATE_PROJECT "%projName%"
 
-copy gameplay-template\template.bar-descriptor.xml %projPath%\bar-descriptor.xml
-call:replace %projPath%\bar-descriptor.xml TEMPLATE_PROJECT "%projName%"
-call:replace %projPath%\bar-descriptor.xml TEMPLATE_TITLE "%title%"
-call:replace %projPath%\bar-descriptor.xml TEMPLATE_UUID "%uuid%"
-call:replace %projPath%\bar-descriptor.xml TEMPLATE_AUTHOR "%author%"
-call:replace %projPath%\bar-descriptor.xml TEMPLATE_DESCRIPTION "%desc%"
+copy gameplay-template\template.bar-descriptor.xml "%projPath%\bar-descriptor.xml"
+call:replace "%projPath%\bar-descriptor.xml" TEMPLATE_PROJECT "%projName%"
+call:replace "%projPath%\bar-descriptor.xml" TEMPLATE_TITLE "%title%"
+call:replace "%projPath%\bar-descriptor.xml" TEMPLATE_UUID "%uuid%"
+call:replace "%projPath%\bar-descriptor.xml" TEMPLATE_AUTHOR "%author%"
+call:replace "%projPath%\bar-descriptor.xml" TEMPLATE_DESCRIPTION "%desc%"
 
 REM Copy Android NDK project files
-mkdir %projPath%\android
+mkdir "%projPath%\android"
 
-copy gameplay-template\android\template.AndroidManifest.xml %projPath%\android\AndroidManifest.xml
-call:replace %projPath%\android\AndroidManifest.xml TEMPLATE_PROJECT "%projName%"
-call:replace %projPath%\android\AndroidManifest.xml TEMPLATE_UUID "%uuid%"
+copy gameplay-template\android\template.AndroidManifest.xml "%projPath%\android\AndroidManifest.xml"
+call:replace "%projPath%\android\AndroidManifest.xml" TEMPLATE_PROJECT "%projName%"
+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.build.xml "%projPath%\android\build.xml"
+call:replace "%projPath%\android\build.xml" TEMPLATE_PROJECT "%projName%"
 
-mkdir %projPath%\android\jni
+mkdir "%projPath%\android\jni"
 
-copy gameplay-template\android\jni\Application.mk %projPath%\android\jni\Application.mk
+copy gameplay-template\android\jni\Application.mk "%projPath%\android\jni\Application.mk"
 
-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%"
+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
+mkdir "%projPath%\android\res\drawable"
 
-copy gameplay-template\icon.png %projPath%\android\res\drawable\icon.png
+copy gameplay-template\icon.png "%projPath%\android\res\drawable\icon.png"
 
-mkdir %projPath%\android\res\values
+mkdir "%projPath%\android\res\values"
 
-copy gameplay-template\android\res\values\template.strings.xml %projPath%\android\res\values\strings.xml
-call:replace %projPath%\android\res\values\strings.xml TEMPLATE_TITLE "%title%"
+copy gameplay-template\android\res\values\template.strings.xml "%projPath%\android\res\values\strings.xml"
+call:replace "%projPath%\android\res\values\strings.xml" TEMPLATE_TITLE "%title%"
 
 
 REM Copy source files
-copy gameplay-template\src\TemplateGame.h %projPath%\src\%className%.h
-copy gameplay-template\src\TemplateGame.cpp %projPath%\src\%className%.cpp
-call:replace %projPath%\src\%className%.h TemplateGame "%className%"
-call:replace %projPath%\src\%className%.cpp TemplateGame "%className%"
+copy gameplay-template\src\TemplateGame.h "%projPath%\src\%className%.h"
+copy gameplay-template\src\TemplateGame.cpp "%projPath%\src\%className%.cpp"
+call:replace "%projPath%\src\%className%.h" TemplateGame "%className%"
+call:replace "%projPath%\src\%className%.cpp" TemplateGame "%className%"
 
 REM Copy resource files
-copy gameplay-template\res\* %projPath%\res\
+copy gameplay-template\res\* "%projPath%\res\"
 
 REM Copy icon
-copy gameplay-template\icon.png %projPath%\icon.png
+copy gameplay-template\icon.png "%projPath%\icon.png"
 
 REM Copy config
-copy gameplay-template\game.config %projPath%\game.config
-call:replace %projPath%\game.config TEMPLATE_TITLE "%title%"
+copy gameplay-template\game.config "%projPath%\game.config"
+call:replace "%projPath%\game.config" TEMPLATE_TITLE "%title%"
 
 REM Open new project folder
-start %projPath%
+start "" "%projPath%"
 
 goto done
 
 :replace
-set rtemp=%1.rtemp
-if exist %rtemp% del /Q %rtemp%
-for /f "tokens=1* eol=€ delims=€]" %%j in ('type "%1" ^| find /V /N ""') do (
+set rtemp=%~1.rtemp
+if exist "%rtemp%" del /Q "%rtemp%"
+for /f "tokens=1* eol=€ delims=€]" %%j in ('type "%~1" ^| find /V /N ""') do (
     set line=%%k
     setlocal EnableDelayedExpansion
     if "!line!" == "" (
-        echo.>>%rtemp%
+        echo.>>"%rtemp%"
     ) else (
         set linput=!line!
         set loutput=!linput:%~2=%~3!
-        echo.!loutput!>>%rtemp%
+        echo.!loutput!>>"%rtemp%"
     )
     endlocal
 )
-copy /Y %rtemp% %1
-del /Q %rtemp%
+copy /Y "%rtemp%" "%~1"
+del /Q "%rtemp%"
 exit /b
 goto done
 

+ 54 - 36
gameplay-newproject.sh

@@ -1,4 +1,4 @@
-#/bin/bash
+#!/bin/bash
 # ********************************************************************
 #
 # generate-project.sh
@@ -13,6 +13,21 @@
 #
 # ********************************************************************
 
+#Find out which OS we're on. 
+unamestr=$(uname)
+
+#Switch-on alias expansion within the script (see http://chiefsandendians.blogspot.co.uk/2010/07/linux-scripts-and-alias.html)
+shopt -s expand_aliases
+
+#alias the sed in-place command for OSX and Linux - incompatibilities between BSD and Linux sed args
+if [[ "$unamestr" == "Darwin" ]]; then
+	alias aliassedinplace='sed -i ""'
+else
+	#For Linux, notice no space after the '-i' 
+	alias aliassedinplace='sed -i""'
+fi
+
+
 echo
 echo "1. Enter a name for the new project."
 echo
@@ -161,15 +176,15 @@ fi
 # 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"
-sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.vcxproj"
+aliassedinplace "s*TEMPLATE_PROJECT*$projectName*g" "$projPath/$projName.vcxproj"
+aliassedinplace "s*TemplateGame*$className*g" "$projPath/$projName.vcxproj"
+aliassedinplace "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.vcxproj"
 
 cp "gameplay-template/gameplay-template.vcxproj.filters" "$projPath/$projName.vcxproj.filters"
-sed -i "" "s*TemplateGame*$className*g" "$projPath/$projName.vcxproj.filters"
+aliassedinplace "s*TemplateGame*$className*g" "$projPath/$projName.vcxproj.filters"
 
 cp "gameplay-template/gameplay-template.vcxproj.user" "$projPath/$projName.vcxproj.user"
-sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.vcxproj.user"
+aliassedinplace "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.vcxproj.user"
 
 
 #############################################
@@ -177,36 +192,36 @@ sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.vcxproj.user"
 #############################################
 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"
-sed -i "" "s*TemplateGame*$className*g" "$projPath/$projName.xcodeproj/project.pbxproj"
-sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.xcodeproj/project.pbxproj"
+aliassedinplace "s*TEMPLATE_PROJECT*$projName*g" "$projPath/$projName.xcodeproj/project.pbxproj"
+aliassedinplace "s*TemplateGame*$className*g" "$projPath/$projName.xcodeproj/project.pbxproj"
+aliassedinplace "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/$projName.xcodeproj/project.pbxproj"
 
 cp "gameplay-template/TEMPLATE_PROJECT-macosx.plist" "$projPath/$projName-macosx.plist"
-sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/$projName-macosx.plist"
-sed -i "" "s*TEMPLATE_AUTHOR*$author*g" "$projPath/$projName-macosx.plist"
+aliassedinplace "s*TEMPLATE_UUID*$uuid*g" "$projPath/$projName-macosx.plist"
+aliassedinplace "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"
+aliassedinplace "s*TEMPLATE_TITLE*$title*g" "$projPath/$projName-ios.plist"
+aliassedinplace "s*TEMPLATE_UUID*$uuid*g" "$projPath/$projName-ios.plist"
+aliassedinplace "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"
-sed -i "" "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/.cproject"
+aliassedinplace "s*TEMPLATE_PROJECT*$projName*g" "$projPath/.cproject"
+aliassedinplace "s*TEMPLATE_UUID*$uuid*g" "$projPath/.cproject"
+aliassedinplace "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/.cproject"
 
 cp "gameplay-template/template.project" "$projPath/.project"
-sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/.project"
+aliassedinplace "s*TEMPLATE_PROJECT*$projName*g" "$projPath/.project"
 
 cp "gameplay-template/template.bar-descriptor.xml" "$projPath/bar-descriptor.xml"
-sed -i "" "s*TEMPLATE_PROJECT*$projName*g" "$projPath/bar-descriptor.xml"
-sed -i "" "s*TEMPLATE_TITLE*$title*g" "$projPath/bar-descriptor.xml"
-sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/bar-descriptor.xml"
-sed -i "" "s*TEMPLATE_AUTHOR*$author*g" "$projPath/bar-descriptor.xml"
-sed -i "" "s*TEMPLATE_DESCRIPTION*$desc*g" "$projPath/bar-descriptor.xml"
+aliassedinplace "s*TEMPLATE_PROJECT*$projName*g" "$projPath/bar-descriptor.xml"
+aliassedinplace "s*TEMPLATE_TITLE*$title*g" "$projPath/bar-descriptor.xml"
+aliassedinplace "s*TEMPLATE_UUID*$uuid*g" "$projPath/bar-descriptor.xml"
+aliassedinplace "s*TEMPLATE_AUTHOR*$author*g" "$projPath/bar-descriptor.xml"
+aliassedinplace "s*TEMPLATE_DESCRIPTION*$desc*g" "$projPath/bar-descriptor.xml"
 
 #############################################
 # Copy Android NDK project files
@@ -217,23 +232,23 @@ 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"
-sed -i "" "s*TEMPLATE_UUID*$uuid*g" "$projPath/android/AndroidManifest.xml"
+aliassedinplace "s*TEMPLATE_PROJECT*$projName*g" "$projPath/android/AndroidManifest.xml"
+aliassedinplace "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"
+aliassedinplace "s*TEMPLATE_PROJECT*$projName*g" "$projPath/android/build.xml"
 
 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"
+aliassedinplace "s*TEMPLATE_PROJECT*$projName*g" "$projPath/android/jni/Android.mk"
+aliassedinplace "s*TemplateGame*$className*g" "$projPath/android/jni/Android.mk"
+aliassedinplace "s*GAMEPLAY_PATH*$gpPath*g" "$projPath/android/jni/Android.mk"
 
 
 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"
+aliassedinplace "s*TEMPLATE_TITLE*$title*g" "$projPath/android/res/values/strings.xml"
 
 
 #############################################
@@ -241,8 +256,8 @@ sed -i "" "s*TEMPLATE_TITLE*$title*g" "$projPath/android/res/values/strings.xml"
 #############################################
 cp "gameplay-template/src/TemplateGame.h" "$projPath/src/$className.h"
 cp "gameplay-template/src/TemplateGame.cpp" "$projPath/src/$className.cpp"
-sed -i "" "s*TemplateGame*$className*g" "$projPath/src/$className.h"
-sed -i "" "s*TemplateGame*$className*g" "$projPath/src/$className.cpp"
+aliassedinplace "s*TemplateGame*$className*g" "$projPath/src/$className.h"
+aliassedinplace "s*TemplateGame*$className*g" "$projPath/src/$className.cpp"
 
 # Copy resource files
 cp "gameplay-template/res/"* "$projPath/res/"
@@ -252,10 +267,13 @@ cp "gameplay-template/icon.png" "$projPath/icon.png"
 
 # Copy config
 cp "gameplay-template/game.config" "$projPath/game.config"
-sed -i "" "s*TEMPLATE_TITLE*$title*g" "$projPath/game.config"
-
+aliassedinplace "s*TEMPLATE_TITLE*$title*g" "$projPath/game.config"
 
-# Open the new project folder
-open $projPath
+# Open the new project folder, use xdg-open on Linux
+if [[ "$unamestr" == "Linux" ]]; then
+	xdg-open $projPath
+else
+	open $projPath
+fi
 
 exit 0

+ 3 - 3
gameplay-template/gameplay-template.vcxproj

@@ -82,7 +82,7 @@
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalDependencies>lua.lib;OpenAL32.lib;OpenGL32.lib;GLU32.lib;glew32.lib;libpng14.lib;zlib.lib;gameplay.lib;libogg.lib;libvorbis.lib;libvorbisfile.lib;BulletDynamics.lib;BulletCollision.lib;LinearMath.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>GAMEPLAY_PATH/external-deps/lua/lib/win32;GAMEPLAY_PATH/external-deps/bullet/lib/win32;GAMEPLAY_PATH/external-deps/openal/lib/win32;GAMEPLAY_PATH/external-deps/oggvorbis/lib/win32;GAMEPLAY_PATH/external-deps/glew/lib/win32;GAMEPLAY_PATH/external-deps/libpng/lib/win32;GAMEPLAY_PATH/external-deps/zlib/lib/win32;GAMEPLAY_PATH/gameplay/$(Configuration)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>GAMEPLAY_PATH/external-deps/lua/lib/windows;GAMEPLAY_PATH/external-deps/bullet/lib/windows;GAMEPLAY_PATH/external-deps/openal/lib/windows;GAMEPLAY_PATH/external-deps/oggvorbis/lib/windows;GAMEPLAY_PATH/external-deps/glew/lib/windows;GAMEPLAY_PATH/external-deps/libpng/lib/windows;GAMEPLAY_PATH/external-deps/zlib/lib/windows;GAMEPLAY_PATH/gameplay/$(Configuration)</AdditionalLibraryDirectories>
     </Link>
     <PostBuildEvent>
       <Command>
@@ -114,7 +114,7 @@
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalDependencies>lua.lib;OpenAL32.lib;OpenGL32.lib;GLU32.lib;glew32.lib;libpng14.lib;zlib.lib;gameplay.lib;libogg.lib;libvorbis.lib;libvorbisfile.lib;BulletDynamics.lib;BulletCollision.lib;LinearMath.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>GAMEPLAY_PATH/external-deps/lua/lib/win32;GAMEPLAY_PATH/external-deps/bullet/lib/win32;GAMEPLAY_PATH/external-deps/openal/lib/win32;GAMEPLAY_PATH/external-deps/oggvorbis/lib/win32;GAMEPLAY_PATH/external-deps/glew/lib/win32;GAMEPLAY_PATH/external-deps/libpng/lib/win32;GAMEPLAY_PATH/external-deps/zlib/lib/win32;GAMEPLAY_PATH/gameplay/$(Configuration)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>GAMEPLAY_PATH/external-deps/lua/lib/windows;GAMEPLAY_PATH/external-deps/bullet/lib/windows;GAMEPLAY_PATH/external-deps/openal/lib/windows;GAMEPLAY_PATH/external-deps/oggvorbis/lib/windows;GAMEPLAY_PATH/external-deps/glew/lib/windows;GAMEPLAY_PATH/external-deps/libpng/lib/windows;GAMEPLAY_PATH/external-deps/zlib/lib/windows;GAMEPLAY_PATH/gameplay/$(Configuration)</AdditionalLibraryDirectories>
     </Link>
     <PostBuildEvent>
       <Command>
@@ -146,7 +146,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalDependencies>lua.lib;OpenAL32.lib;OpenGL32.lib;GLU32.lib;glew32.lib;libpng14.lib;zlib.lib;gameplay.lib;BulletDynamics.lib;BulletCollision.lib;LinearMath.lib;libogg.lib;libvorbis.lib;libvorbisfile.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>GAMEPLAY_PATH/external-deps/lua/lib/win32;GAMEPLAY_PATH/external-deps/bullet/lib/win32;GAMEPLAY_PATH/external-deps/openal/lib/win32;GAMEPLAY_PATH/external-deps/oggvorbis/lib/win32;GAMEPLAY_PATH/external-deps/glew/lib/win32;GAMEPLAY_PATH/external-deps/libpng/lib/win32;GAMEPLAY_PATH/external-deps/zlib/lib/win32;GAMEPLAY_PATH/gameplay/$(Configuration)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>GAMEPLAY_PATH/external-deps/lua/lib/windows;GAMEPLAY_PATH/external-deps/bullet/lib/windows;GAMEPLAY_PATH/external-deps/openal/lib/windows;GAMEPLAY_PATH/external-deps/oggvorbis/lib/windows;GAMEPLAY_PATH/external-deps/glew/lib/windows;GAMEPLAY_PATH/external-deps/libpng/lib/windows;GAMEPLAY_PATH/external-deps/zlib/lib/windows;GAMEPLAY_PATH/gameplay/$(Configuration)</AdditionalLibraryDirectories>
     </Link>
     <PostBuildEvent>
       <Command>

+ 3 - 3
gameplay-template/gameplay-template.vcxproj.user

@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LocalDebuggerEnvironment>PATH=%PATH%;GAMEPLAY_PATH/bin/win32;</LocalDebuggerEnvironment>
+    <LocalDebuggerEnvironment>PATH=%PATH%;GAMEPLAY_PATH/bin/windows;</LocalDebuggerEnvironment>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-	<LocalDebuggerEnvironment>PATH=%PATH%;GAMEPLAY_PATH/bin/win32;</LocalDebuggerEnvironment>
+	<LocalDebuggerEnvironment>PATH=%PATH%;GAMEPLAY_PATH/bin/windows;</LocalDebuggerEnvironment>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|Win32'">
-    <LocalDebuggerEnvironment>PATH=%PATH%;GAMEPLAY_PATH/bin/win32;</LocalDebuggerEnvironment>
+    <LocalDebuggerEnvironment>PATH=%PATH%;GAMEPLAY_PATH/bin/windows;</LocalDebuggerEnvironment>
 	<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
 </Project>

+ 6 - 32
gameplay-template/gameplay-template.xcodeproj/project.pbxproj

@@ -9,6 +9,7 @@
 /* Begin PBXBuildFile section */
 		42438B531491AD2000D218B8 /* libgameplay.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42438B521491AD2000D218B8 /* libgameplay.a */; };
 		428F7BDE15CB131A009ED24C /* game.config in Resources */ = {isa = PBXBuildFile; fileRef = 428F7BDD15CB131A009ED24C /* game.config */; };
+		424CC03C161FCBDD00577827 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 424CC03B161FCBDD00577827 /* IOKit.framework */; };
 		42C932C11491A0DB0098216A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C932C01491A0DB0098216A /* Cocoa.framework */; };
 		42C932EE1491A4CB0098216A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 42C932ED1491A4CB0098216A /* icon.png */; };
 		42C932F11491A5160098216A /* TemplateGame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C932EF1491A5160098216A /* TemplateGame.cpp */; };
@@ -45,6 +46,7 @@
 /* Begin PBXFileReference section */
 		428F7BDD15CB131A009ED24C /* game.config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = game.config; sourceTree = "<group>"; };
 		42438B521491AD2000D218B8 /* libgameplay.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgameplay.a; path = "~/Library/Developer/Xcode/DerivedData/gameplay-exiunaubxxjndaapmcqkaoeboiob/Build/Products/Debug/libgameplay.a"; sourceTree = "<group>"; };
+		424CC03B161FCBDD00577827 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
 		42C932BC1491A0DB0098216A /* TEMPLATE_PROJECT-macosx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TEMPLATE_PROJECT-macosx.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		42C932C01491A0DB0098216A /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
 		42C932ED1491A4CB0098216A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = "<group>"; };
@@ -87,6 +89,7 @@
 				42C933291491A6E50098216A /* libvorbisfile.a in Frameworks */,
 				42C9332C1491A7680098216A /* libpng.a in Frameworks */,
 				42C9332F1491A78D0098216A /* libz.dylib in Frameworks */,
+				424CC03C161FCBDD00577827 /* IOKit.framework in Frameworks */,
 				42C932C11491A0DB0098216A /* Cocoa.framework in Frameworks */,
 				42C9331D1491A6750098216A /* QuartzCore.framework in Frameworks */,
 				42C933171491A5EB0098216A /* OpenGL.framework in Frameworks */,
@@ -192,6 +195,7 @@
 		5B61613A14CCC3590073B857 /* MacOSX */ = {
 			isa = PBXGroup;
 			children = (
+				424CC03B161FCBDD00577827 /* IOKit.framework */,
 				42C932C01491A0DB0098216A /* Cocoa.framework */,
 				42C9331C1491A6750098216A /* QuartzCore.framework */,
 				42C933161491A5EB0098216A /* OpenGL.framework */,
@@ -220,7 +224,6 @@
 				42C932B91491A0DB0098216A /* Frameworks */,
 				42C933301491A7B50098216A /* ShellScript */,
 				42C932BA1491A0DB0098216A /* Resources */,
-				5BAF20D7152F30C3003E2AC3 /* Copy Gameplay Resources - Run Script */,
 			);
 			buildRules = (
 			);
@@ -239,7 +242,6 @@
 				5B61611714CCC24C0073B857 /* Frameworks */,
 				5B61612414CCC24C0073B857 /* ShellScript */,
 				5B61612514CCC24C0073B857 /* Resources */,
-				5BAF20A3152F2FCE003E2AC3 /* Copy Gameplay Resources Run Script */,
 			);
 			buildRules = (
 			);
@@ -310,7 +312,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "touch -cm ${SRCROOT}/res";
+			shellScript = "cp -rf GAMEPLAY_PATH/gameplay/res/shaders ${SRCROOT}/res\ncp -rf GAMEPLAY_PATH/gameplay/res/logo_powered_white.png ${SRCROOT}/res\ntouch -cm ${SRCROOT}/res";
 		};
 		5B61612414CCC24C0073B857 /* ShellScript */ = {
 			isa = PBXShellScriptBuildPhase;
@@ -323,35 +325,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "touch -cm ${SRCROOT}/res";
-		};
-		5BAF20A3152F2FCE003E2AC3 /* Copy Gameplay Resources Run Script */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			name = "Copy Gameplay Reousrces Run Script";
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "cp -rn GAMEPLAY_PATH/gameplay/res/shaders ${SRCROOT}/res\ncp -rf GAMEPLAY_PATH/gameplay/res/logo_powered_white.png ${SRCROOT}/res\ntouch -cm ${SRCROOT}/res";
-		};
-		5BAF20D7152F30C3003E2AC3 /* Copy Gameplay Resources - Run Script */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			name = "Copy Gameplay Resources - Run Script";
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "cp -rn GAMEPLAY_PATH/gameplay/res/shaders ${SRCROOT}/res\ncp -rn GAMEPLAY_PATH/gameplay/res/logo_powered_white.png ${SRCROOT}/res\ntouch -cm ${SRCROOT}/res";
+			shellScript = "cp -rf GAMEPLAY_PATH/gameplay/res/shaders ${SRCROOT}/res\ncp -rf GAMEPLAY_PATH/gameplay/res/logo_powered_white.png ${SRCROOT}/res\ntouch -cm ${SRCROOT}/res";
 		};
 /* End PBXShellScriptBuildPhase section */
 

BIN
gameplay-template/icon.png


+ 0 - 2
gameplay-template/template.bar-descriptor.xml

@@ -39,8 +39,6 @@
 
     <!--  Unique author ID assigned by signing authority. Required if using debug tokens. -->
     <!-- <authorId>gYAAgPkLP1tZlyYP1wiMaRFFNMw</authorId> -->
-    
-    <platformVersion>2.0.0.7971</platformVersion>
 
     <initialWindow>
         <aspectRatio>landscape</aspectRatio>

+ 28 - 21
gameplay-template/template.cproject

@@ -55,9 +55,9 @@
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/armle-v7/lib"/>
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/armle-v7/usr/lib"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/gameplay/${ConfigName}&quot;"/>
-                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/qnx/arm&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/qnx/arm&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/qnx/arm&quot;"/>
+                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/blackberry/arm&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/blackberry/arm&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/blackberry/arm&quot;"/>
 								</option>
 								<option id="com.qnx.qcc.option.linker.libraries.1174766388" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
 									<listOptionValue builtIn="false" value="GLESv2"/>
@@ -67,6 +67,7 @@
 									<listOptionValue builtIn="false" value="png14"/>
 									<listOptionValue builtIn="false" value="pps"/>
 									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="gestures"/>
 									<listOptionValue builtIn="false" value="OpenAL"/>
 									<listOptionValue builtIn="false" value="asound"/>
 									<listOptionValue builtIn="false" value="gameplay"/>
@@ -139,9 +140,9 @@
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/armle-v7/lib"/>
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/armle-v7/usr/lib"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/gameplay/${ConfigName}&quot;"/>
-                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/qnx/arm&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/qnx/arm&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/qnx/arm&quot;"/>
+                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/blackberry/arm&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/blackberry/arm&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/blackberry/arm&quot;"/>
 								</option>
 								<option id="com.qnx.qcc.option.linker.libraries.380839761" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
 									<listOptionValue builtIn="false" value="GLESv2"/>
@@ -151,6 +152,7 @@
 									<listOptionValue builtIn="false" value="png14"/>
 									<listOptionValue builtIn="false" value="pps"/>
 									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="gestures"/>
 									<listOptionValue builtIn="false" value="OpenAL"/>
 									<listOptionValue builtIn="false" value="asound"/>
 									<listOptionValue builtIn="false" value="gameplay"/>
@@ -226,9 +228,9 @@
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/armle-v7/lib"/>
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/armle-v7/usr/lib"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/gameplay/${ConfigName}&quot;"/>
-                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/qnx/arm&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/qnx/arm&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/qnx/arm&quot;"/>
+                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/blackberry/arm&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/blackberry/arm&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/blackberry/arm&quot;"/>
 								</option>
 								<option id="com.qnx.qcc.option.linker.libraries.248496823" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
 									<listOptionValue builtIn="false" value="GLESv2"/>
@@ -238,6 +240,7 @@
 									<listOptionValue builtIn="false" value="png14"/>
 									<listOptionValue builtIn="false" value="pps"/>
 									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="gestures"/>
 									<listOptionValue builtIn="false" value="OpenAL"/>
 									<listOptionValue builtIn="false" value="asound"/>
 									<listOptionValue builtIn="false" value="gameplay"/>
@@ -314,9 +317,9 @@
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/armle-v7/lib"/>
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/armle-v7/usr/lib"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/gameplay/${ConfigName}&quot;"/>
-                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/qnx/arm&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/qnx/arm&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/qnx/arm&quot;"/>
+                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/blackberry/arm&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/blackberry/arm&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/blackberry/arm&quot;"/>
 								</option>
 								<option id="com.qnx.qcc.option.linker.libraries.955918617" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
 									<listOptionValue builtIn="false" value="GLESv2"/>
@@ -326,6 +329,7 @@
 									<listOptionValue builtIn="false" value="png14"/>
 									<listOptionValue builtIn="false" value="pps"/>
 									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="gestures"/>
 									<listOptionValue builtIn="false" value="OpenAL"/>
 									<listOptionValue builtIn="false" value="asound"/>
 									<listOptionValue builtIn="false" value="gameplay"/>
@@ -399,9 +403,9 @@
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/x86/lib"/>
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/x86/usr/lib"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/gameplay/${ConfigName}&quot;"/>
-                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/qnx/x86&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/qnx/x86&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/qnx/x86&quot;"/>
+                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/blackberry/x86&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/blackberry/x86&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/blackberry/x86&quot;"/>
 								</option>
 								<option id="com.qnx.qcc.option.linker.libraries.298922406" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
 									<listOptionValue builtIn="false" value="GLESv2"/>
@@ -411,6 +415,7 @@
 									<listOptionValue builtIn="false" value="png14"/>
 									<listOptionValue builtIn="false" value="pps"/>
 									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="gestures"/>
 									<listOptionValue builtIn="false" value="OpenAL"/>
 									<listOptionValue builtIn="false" value="asound"/>
 									<listOptionValue builtIn="false" value="gameplay"/>
@@ -486,9 +491,9 @@
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/x86/lib"/>
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/x86/usr/lib"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/gameplay/${ConfigName}&quot;"/>
-                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/qnx/x86&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/qnx/x86&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/qnx/x86&quot;"/>
+                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/blackberry/x86&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/blackberry/x86&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/blackberry/x86&quot;"/>
 								</option>
 								<option id="com.qnx.qcc.option.linker.libraries.1203875316" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
 									<listOptionValue builtIn="false" value="GLESv2"/>
@@ -498,6 +503,7 @@
 									<listOptionValue builtIn="false" value="png14"/>
 									<listOptionValue builtIn="false" value="pps"/>
 									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="gestures"/>
 									<listOptionValue builtIn="false" value="OpenAL"/>
 									<listOptionValue builtIn="false" value="asound"/>
 									<listOptionValue builtIn="false" value="gameplay"/>
@@ -573,9 +579,9 @@
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/x86/lib"/>
 									<listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/x86/usr/lib"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/gameplay/${ConfigName}&quot;"/>
-                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/qnx/x86&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/qnx/x86&quot;"/>
-									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/qnx/x86&quot;"/>
+                                    <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/lua/lib/blackberry/x86&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/bullet/lib/blackberry/x86&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}/GAMEPLAY_PATH/external-deps/oggvorbis/lib/blackberry/x86&quot;"/>
 								</option>
 								<option id="com.qnx.qcc.option.linker.libraries.2055007034" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs">
 									<listOptionValue builtIn="false" value="GLESv2"/>
@@ -585,6 +591,7 @@
 									<listOptionValue builtIn="false" value="png14"/>
 									<listOptionValue builtIn="false" value="pps"/>
 									<listOptionValue builtIn="false" value="bps"/>
+									<listOptionValue builtIn="false" value="gestures"/>
 									<listOptionValue builtIn="false" value="OpenAL"/>
 									<listOptionValue builtIn="false" value="asound"/>
 									<listOptionValue builtIn="false" value="gameplay"/>

+ 23 - 15
gameplay.doxyfile

@@ -1,4 +1,4 @@
-# Doxyfile 1.8.1
+# Doxyfile 1.8.0
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project
@@ -32,7 +32,7 @@ PROJECT_NAME           = gameplay
 # This could be handy for archiving the generated documentation or 
 # if some version control system is used.
 
-PROJECT_NUMBER         = 1.4.0
+PROJECT_NUMBER         = 1.5.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description 
 # for a project that appears at the top of each page and should give viewer 
@@ -564,6 +564,12 @@ MAX_INITIALIZER_LINES  = 30
 
 SHOW_USED_FILES        = NO
 
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
 # Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
 # This will remove the Files entry from the Quick Index and from the 
 # Folder Tree View (if specified). The default is YES.
@@ -948,23 +954,20 @@ HTML_COLORSTYLE_GAMMA  = 80
 
 HTML_TIMESTAMP         = YES
 
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
 # documentation will contain sections that can be hidden and shown after the 
-# page has loaded.
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
 
 HTML_DYNAMIC_SECTIONS  = NO
 
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of 
-# entries shown in the various tree structured indices initially; the user 
-# can expand and collapse entries dynamically later on. Doxygen will expand 
-# the tree to such a level that at most the specified number of entries are 
-# visible (unless a fully collapsed tree already exceeds this amount). 
-# So setting the number of entries 1 will produce a full collapsed tree by 
-# default. 0 is a special value representing an infinite number of entries 
-# and will result in a full expanded tree by default.
-
-HTML_INDEX_NUM_ENTRIES = 100
-
 # If the GENERATE_DOCSET tag is set to YES, additional index files 
 # will be generated that can be used as input for Apple's Xcode 3 
 # integrated development environment, introduced with OSX 10.5 (Leopard). 
@@ -1143,6 +1146,11 @@ GENERATE_TREEVIEW      = NO
 
 ENUM_VALUES_PER_LINE   = 4
 
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
 # used to set the initial width (in pixels) of the frame in which the tree 
 # is shown.
@@ -1705,7 +1713,7 @@ CALLER_GRAPH           = NO
 
 GRAPHICAL_HIERARCHY    = YES
 
-# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES 
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
 # then doxygen will show the dependencies a directory has on other directories 
 # in a graphical way. The dependency relations are determined by the #include 
 # relations between the files in the directories.

+ 198 - 8
gameplay.sln

@@ -3,6 +3,16 @@ Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual Studio 2010
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay", "gameplay\gameplay.vcxproj", "{1032BA4B-57EB-4348-9E03-29DD63E80E4A}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay-tests", "gameplay-tests\gameplay-tests.vcxproj", "{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}"
+	ProjectSection(ProjectDependencies) = postProject
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample00-mesh", "gameplay-samples\sample00-mesh\sample00-mesh.vcxproj", "{D672DC66-3CE0-4878-B0D2-813CA731012F}"
+	ProjectSection(ProjectDependencies) = postProject
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample01-longboard", "gameplay-samples\sample01-longboard\sample01-longboard.vcxproj", "{9A515C8B-3320-4C5C-9754-211E91206C9D}"
 	ProjectSection(ProjectDependencies) = postProject
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
@@ -23,65 +33,245 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-particles", "gamep
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample00-mesh", "gameplay-samples\sample00-mesh\sample00-mesh.vcxproj", "{D672DC66-3CE0-4878-B0D2-813CA731012F}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample05-lua", "gameplay-samples\sample05-lua\sample05-lua.vcxproj", "{C6121A62-AA46-BA6D-A1CE-8000544456AA}"
 	ProjectSection(ProjectDependencies) = postProject
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample05-lua", "gameplay-samples\sample05-lua\sample05-lua.vcxproj", "{C6121A62-AA46-BA6D-A1CE-8000544456AA}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample06-racer", "gameplay-samples\sample06-racer\sample06-racer.vcxproj", "{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}"
 	ProjectSection(ProjectDependencies) = postProject
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 	EndProjectSection
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|BlackBerry = Debug|BlackBerry
+		Debug|BlackBerrySimulator = Debug|BlackBerrySimulator
 		Debug|Win32 = Debug|Win32
+		DebugMem|BlackBerry = DebugMem|BlackBerry
+		DebugMem|BlackBerrySimulator = DebugMem|BlackBerrySimulator
 		DebugMem|Win32 = DebugMem|Win32
+		Release|BlackBerry = Release|BlackBerry
+		Release|BlackBerrySimulator = Release|BlackBerrySimulator
 		Release|Win32 = Release|Win32
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Debug|Win32.ActiveCfg = Debug|Win32
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Debug|Win32.Build.0 = Debug|Win32
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|Win32.ActiveCfg = Release|Win32
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A}.Release|Win32.Build.0 = Release|Win32
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Debug|Win32.Build.0 = Debug|Win32
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|Win32.ActiveCfg = Release|Win32
+		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|Win32.Build.0 = Release|Win32
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
+		{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|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.ActiveCfg = Release|Win32
+		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.Build.0 = Release|Win32
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|Win32.ActiveCfg = Debug|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|Win32.Build.0 = Debug|Win32
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Release|Win32.ActiveCfg = Release|Win32
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Release|Win32.Build.0 = Release|Win32
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
 		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Debug|Win32.ActiveCfg = Debug|Win32
 		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Debug|Win32.Build.0 = Debug|Win32
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
 		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
 		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
 		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Release|Win32.ActiveCfg = Release|Win32
 		{CC37B8E9-6402-4841-8D6A-5D908A5909B3}.Release|Win32.Build.0 = Release|Win32
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
 		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Debug|Win32.ActiveCfg = Debug|Win32
 		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Debug|Win32.Build.0 = Debug|Win32
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
 		{87388E8B-F3CF-428F-BC2C-C1886248C111}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
 		{87388E8B-F3CF-428F-BC2C-C1886248C111}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
 		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Release|Win32.ActiveCfg = Release|Win32
 		{87388E8B-F3CF-428F-BC2C-C1886248C111}.Release|Win32.Build.0 = Release|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
 		{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|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
 		{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|BlackBerry.ActiveCfg = Release|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
 		{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
-		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|Win32.Build.0 = DebugMem|Win32
-		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.ActiveCfg = Release|Win32
-		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.Build.0 = Release|Win32
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
 		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Debug|Win32.ActiveCfg = Debug|Win32
 		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Debug|Win32.Build.0 = Debug|Win32
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
 		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
 		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
 		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Release|Win32.ActiveCfg = Release|Win32
 		{C6121A62-AA46-BA6D-A1CE-8000544456AA}.Release|Win32.Build.0 = Release|Win32
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Debug|Win32.ActiveCfg = Debug|Win32
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Debug|Win32.Build.0 = Debug|Win32
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Release|Win32.ActiveCfg = Release|Win32
+		{1808B3EA-1ED5-1219-6D3C-9F588D2D8385}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 30 - 0
gameplay.workspace

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_workspace_file>
+	<Workspace title="GamePlay">
+		<Project filename="gameplay/gameplay.cbp" />
+		<Project filename="gameplay-tests/gameplay-tests.cbp">
+			<Depends filename="gameplay/gameplay.cbp" />
+		</Project>
+		<Project filename="gameplay-samples/sample00-mesh/sample00-mesh.cbp">
+			<Depends filename="gameplay/gameplay.cbp" />
+		</Project>
+		<Project filename="gameplay-samples/sample01-longboard/sample01-longboard.cbp">
+			<Depends filename="gameplay/gameplay.cbp" />
+		</Project>
+		<Project filename="gameplay-samples/sample02-spaceship/sample02-spaceship.cbp">
+			<Depends filename="gameplay/gameplay.cbp" />
+		</Project>
+		<Project filename="gameplay-samples/sample03-character/sample03-character.cbp">
+			<Depends filename="gameplay/gameplay.cbp" />
+		</Project>
+		<Project filename="gameplay-samples/sample04-particles/sample04-particles.cbp">
+			<Depends filename="gameplay/gameplay.cbp" />
+		</Project>
+		<Project filename="gameplay-samples/sample05-lua/sample05-lua.cbp">
+			<Depends filename="gameplay/gameplay.cbp" />
+		</Project>
+		<Project filename="gameplay-samples/sample06-racer/sample06-racer.cbp" active="1">
+			<Depends filename="gameplay/gameplay.cbp" />
+		</Project>
+	</Workspace>
+</CodeBlocks_workspace_file>

+ 6 - 0
gameplay.xcworkspace/contents.xcworkspacedata

@@ -4,6 +4,9 @@
    <FileRef
       location = "group:gameplay/gameplay.xcodeproj">
    </FileRef>
+   <FileRef
+      location = "group:gameplay-tests/gameplay-tests.xcodeproj">
+   </FileRef>
    <FileRef
       location = "group:gameplay-samples/sample00-mesh/sample00-mesh.xcodeproj">
    </FileRef>
@@ -22,4 +25,7 @@
    <FileRef
       location = "group:gameplay-samples/sample05-lua/sample05-lua.xcodeproj">
    </FileRef>
+   <FileRef
+      location = "group:gameplay-samples/sample06-racer/sample06-racer.xcodeproj">
+   </FileRef>
 </Workspace>

+ 614 - 0
gameplay/CMakeLists.txt

@@ -0,0 +1,614 @@
+set(GAMEPLAY_SRC
+    src/AbsoluteLayout.cpp
+    src/AbsoluteLayout.h
+    src/AIAgent.cpp
+    src/AIAgent.h
+    src/AIController.cpp
+    src/AIController.h
+    src/AIMessage.cpp
+    src/AIMessage.h
+    src/AIState.cpp
+    src/AIState.h
+    src/AIStateMachine.cpp
+    src/AIStateMachine.h
+    src/Animation.cpp
+    src/Animation.h
+    src/AnimationClip.cpp
+    src/AnimationClip.h
+    src/AnimationController.cpp
+    src/AnimationController.h
+    src/AnimationTarget.cpp
+    src/AnimationTarget.h
+    src/AnimationValue.cpp
+    src/AnimationValue.h
+    src/AudioBuffer.cpp
+    src/AudioBuffer.h
+    src/AudioController.cpp
+    src/AudioController.h
+    src/AudioListener.cpp
+    src/AudioListener.h
+    src/AudioSource.cpp
+    src/AudioSource.h
+    src/Base.h
+    src/BoundingBox.cpp
+    src/BoundingBox.h
+    src/BoundingBox.inl
+    src/BoundingSphere.cpp
+    src/BoundingSphere.h
+    src/BoundingSphere.inl
+    src/Bundle.cpp
+    src/Bundle.h
+    src/Button.cpp
+    src/Button.h
+    src/Camera.cpp
+    src/Camera.h
+    src/CheckBox.cpp
+    src/CheckBox.h
+    src/Container.cpp
+    src/Container.h
+    src/Control.cpp
+    src/Control.h
+    src/Curve.cpp
+    src/Curve.h
+    src/DebugNew.cpp
+    src/DebugNew.h
+    src/DepthStencilTarget.cpp
+    src/DepthStencilTarget.h
+    src/Effect.cpp
+    src/Effect.h
+    src/FileSystem.cpp
+    src/FileSystem.h
+    src/FlowLayout.cpp
+    src/FlowLayout.h
+    src/Font.cpp
+    src/Font.h
+    src/Form.cpp
+    src/Form.h
+    src/FrameBuffer.cpp
+    src/FrameBuffer.h
+    src/Frustum.cpp
+    src/Frustum.h
+    src/Game.cpp
+    src/Game.h
+    src/Game.inl
+    src/Gamepad.cpp
+    src/Gamepad.h
+    src/gameplay-main-android.cpp
+    src/gameplay-main-blackberry.cpp
+    src/gameplay-main-linux.cpp
+    src/gameplay-main-windows.cpp
+	src/Gesture.h
+    src/Image.cpp
+    src/Image.h
+    src/Image.inl
+    src/Joint.cpp
+    src/Joint.h
+    src/Joystick.cpp
+    src/Joystick.h
+    src/Joystick.inl
+    src/Label.cpp
+    src/Label.h
+    src/Layout.cpp
+    src/Layout.h
+    src/Light.cpp
+    src/Light.h
+    src/Logger.cpp
+    src/Logger.h
+    src/Material.cpp
+    src/Material.h
+    src/MaterialParameter.cpp
+    src/MaterialParameter.h
+    src/MathUtil.cpp
+    src/MathUtil.h
+    src/MathUtil.inl
+    src/MathUtilNeon.inl
+    src/Matrix.cpp
+    src/Matrix.h
+    src/Matrix.inl
+    src/Mesh.cpp
+    src/Mesh.h
+    src/MeshBatch.cpp
+    src/MeshBatch.h
+    src/MeshBatch.inl
+    src/MeshPart.cpp
+    src/MeshPart.h
+    src/MeshSkin.cpp
+    src/MeshSkin.h
+    src/Model.cpp
+    src/Model.h
+    src/Node.cpp
+    src/Node.h
+    src/ParticleEmitter.cpp
+    src/ParticleEmitter.h
+    src/Pass.cpp
+    src/Pass.h
+    src/PhysicsCharacter.cpp
+    src/PhysicsCharacter.h
+    src/PhysicsCollisionObject.cpp
+    src/PhysicsCollisionObject.h
+    src/PhysicsCollisionShape.cpp
+    src/PhysicsCollisionShape.h
+    src/PhysicsConstraint.cpp
+    src/PhysicsConstraint.h
+    src/PhysicsController.cpp
+    src/PhysicsController.h
+    src/PhysicsFixedConstraint.cpp
+    src/PhysicsFixedConstraint.h
+    src/PhysicsGenericConstraint.cpp
+    src/PhysicsGenericConstraint.h
+    src/PhysicsGhostObject.cpp
+    src/PhysicsGhostObject.h
+    src/PhysicsHingeConstraint.cpp
+    src/PhysicsHingeConstraint.h
+    src/PhysicsRigidBody.cpp
+    src/PhysicsRigidBody.h
+    src/PhysicsSocketConstraint.cpp
+    src/PhysicsSocketConstraint.h
+    src/PhysicsSpringConstraint.cpp
+    src/PhysicsSpringConstraint.h
+	src/PhysicsVehicle.cpp
+	src/PhysicsVehicle.h
+	src/PhysicsVehicleWheel.cpp
+	src/PhysicsVehicle.h
+    src/Plane.cpp
+    src/Plane.h
+    src/Plane.inl
+    src/Platform.h
+    src/PlatformAndroid.cpp
+    src/PlatformBlackBerry.cpp
+    src/PlatformLinux.cpp
+    src/PlatformWindows.cpp
+    src/Properties.cpp
+    src/Properties.h
+    src/Quaternion.cpp
+    src/Quaternion.h
+    src/Quaternion.inl
+    src/RadioButton.cpp
+    src/RadioButton.h
+    src/Ray.cpp
+    src/Ray.h
+    src/Ray.inl
+    src/Rectangle.cpp
+    src/Rectangle.h
+    src/Ref.cpp
+    src/Ref.h
+    src/RenderState.cpp
+    src/RenderState.h
+    src/RenderTarget.cpp
+    src/RenderTarget.h
+    src/Scene.cpp
+    src/Scene.h
+    src/SceneLoader.cpp
+    src/SceneLoader.h
+    src/ScreenDisplayer.cpp
+    src/ScreenDisplayer.h
+    src/ScriptController.cpp
+    src/ScriptController.h
+    src/ScriptController.inl
+    src/ScriptTarget.cpp
+    src/ScriptTarget.h
+    src/Slider.cpp
+    src/Slider.h
+    src/SpriteBatch.cpp
+    src/SpriteBatch.h
+    src/Technique.cpp
+    src/Technique.h
+    src/TextBox.cpp
+    src/TextBox.h
+    src/Texture.cpp
+    src/Texture.h
+    src/Theme.cpp
+    src/Theme.h
+    src/ThemeStyle.cpp
+    src/ThemeStyle.h
+    src/Transform.cpp
+    src/Transform.h
+    src/Vector2.cpp
+    src/Vector2.h
+    src/Vector2.inl
+    src/Vector3.cpp
+    src/Vector3.h
+    src/Vector3.inl
+    src/Vector4.cpp
+    src/Vector4.h
+    src/Vector4.inl
+    src/VertexAttributeBinding.cpp
+    src/VertexAttributeBinding.h
+    src/VertexFormat.cpp
+    src/VertexFormat.h
+    src/VerticalLayout.cpp
+    src/VerticalLayout.h
+)
+
+set(GAMEPLAY_LUA
+    src/lua/lua_all_bindings.cpp
+    src/lua/lua_all_bindings.h
+    src/lua/lua_AbsoluteLayout.cpp
+    src/lua/lua_AbsoluteLayout.h
+    src/lua/lua_AIAgent.cpp
+    src/lua/lua_AIAgent.h
+    src/lua/lua_AIAgentListener.cpp
+    src/lua/lua_AIAgentListener.h
+    src/lua/lua_AIController.cpp
+    src/lua/lua_AIController.h
+    src/lua/lua_AIMessage.cpp
+    src/lua/lua_AIMessage.h
+    src/lua/lua_AIMessageParameterType.cpp
+    src/lua/lua_AIMessageParameterType.h
+    src/lua/lua_AIState.cpp
+    src/lua/lua_AIState.h
+    src/lua/lua_AIStateListener.cpp
+    src/lua/lua_AIStateListener.h
+    src/lua/lua_AIStateMachine.cpp
+    src/lua/lua_AIStateMachine.h
+    src/lua/lua_Animation.cpp
+    src/lua/lua_Animation.h
+    src/lua/lua_AnimationClip.cpp
+    src/lua/lua_AnimationClip.h
+    src/lua/lua_AnimationClipListener.cpp
+    src/lua/lua_AnimationClipListener.h
+    src/lua/lua_AnimationClipListenerEventType.cpp
+    src/lua/lua_AnimationClipListenerEventType.h
+    src/lua/lua_AnimationController.cpp
+    src/lua/lua_AnimationController.h
+    src/lua/lua_AnimationTarget.cpp
+    src/lua/lua_AnimationTarget.h
+    src/lua/lua_AnimationValue.cpp
+    src/lua/lua_AnimationValue.h
+    src/lua/lua_AudioBuffer.cpp
+    src/lua/lua_AudioBuffer.h
+    src/lua/lua_AudioController.cpp
+    src/lua/lua_AudioController.h
+    src/lua/lua_AudioListener.cpp
+    src/lua/lua_AudioListener.h
+    src/lua/lua_AudioSource.cpp
+    src/lua/lua_AudioSource.h
+    src/lua/lua_AudioSourceState.cpp
+    src/lua/lua_AudioSourceState.h
+    src/lua/lua_BoundingBox.cpp
+    src/lua/lua_BoundingBox.h
+    src/lua/lua_BoundingSphere.cpp
+    src/lua/lua_BoundingSphere.h
+    src/lua/lua_Bundle.cpp
+    src/lua/lua_Bundle.h
+    src/lua/lua_Button.cpp
+    src/lua/lua_Button.h
+    src/lua/lua_Camera.cpp
+    src/lua/lua_Camera.h
+    src/lua/lua_CameraType.cpp
+    src/lua/lua_CameraType.h
+    src/lua/lua_CheckBox.cpp
+    src/lua/lua_CheckBox.h
+    src/lua/lua_Container.cpp
+    src/lua/lua_Container.h
+    src/lua/lua_ContainerScroll.cpp
+    src/lua/lua_ContainerScroll.h
+    src/lua/lua_Control.cpp
+    src/lua/lua_Control.h
+    src/lua/lua_ControlAlignment.cpp
+    src/lua/lua_ControlAlignment.h
+    src/lua/lua_ControlListener.cpp
+    src/lua/lua_ControlListener.h
+    src/lua/lua_ControlListenerEventType.cpp
+    src/lua/lua_ControlListenerEventType.h
+    src/lua/lua_ControlState.cpp
+    src/lua/lua_ControlState.h
+    src/lua/lua_Curve.cpp
+    src/lua/lua_Curve.h
+    src/lua/lua_CurveInterpolationType.cpp
+    src/lua/lua_CurveInterpolationType.h
+    src/lua/lua_DepthStencilTarget.cpp
+    src/lua/lua_DepthStencilTarget.h
+    src/lua/lua_DepthStencilTargetFormat.cpp
+    src/lua/lua_DepthStencilTargetFormat.h
+    src/lua/lua_Effect.cpp
+    src/lua/lua_Effect.h
+    src/lua/lua_FileSystem.cpp
+    src/lua/lua_FileSystem.h
+    src/lua/lua_FlowLayout.cpp
+    src/lua/lua_FlowLayout.h
+    src/lua/lua_Font.cpp
+    src/lua/lua_Font.h
+    src/lua/lua_FontJustify.cpp
+    src/lua/lua_FontJustify.h
+    src/lua/lua_FontStyle.cpp
+    src/lua/lua_FontStyle.h
+    src/lua/lua_FontText.cpp
+    src/lua/lua_FontText.h
+    src/lua/lua_Form.cpp
+    src/lua/lua_Form.h
+    src/lua/lua_FrameBuffer.cpp
+    src/lua/lua_FrameBuffer.h
+    src/lua/lua_Frustum.cpp
+    src/lua/lua_Frustum.h
+    src/lua/lua_Game.cpp
+    src/lua/lua_Game.h
+    src/lua/lua_GameClearFlags.cpp
+    src/lua/lua_GameClearFlags.h
+    src/lua/lua_Gamepad.cpp
+    src/lua/lua_Gamepad.h
+    src/lua/lua_GamepadButtonState.cpp
+    src/lua/lua_GamepadButtonState.h
+    src/lua/lua_GamepadGamepadEvent.cpp
+    src/lua/lua_GamepadGamepadEvent.h
+    src/lua/lua_GameState.cpp
+    src/lua/lua_GameState.h
+	src/lua/lua_Gesture.cpp
+	src/lua/lua_Gesture.h
+	src/lua/lua_GestureGestureEvent.cpp
+	src/lua/lua_GestureGestureEvent.h
+    src/lua/lua_Global.cpp
+    src/lua/lua_Global.h
+    src/lua/lua_Image.cpp
+    src/lua/lua_Image.h
+    src/lua/lua_ImageFormat.cpp
+    src/lua/lua_ImageFormat.h
+    src/lua/lua_Joint.cpp
+    src/lua/lua_Joint.h
+    src/lua/lua_Joystick.cpp
+    src/lua/lua_Joystick.h
+    src/lua/lua_Keyboard.cpp
+    src/lua/lua_Keyboard.h
+    src/lua/lua_KeyboardKey.cpp
+    src/lua/lua_KeyboardKey.h
+    src/lua/lua_KeyboardKeyEvent.cpp
+    src/lua/lua_KeyboardKeyEvent.h
+    src/lua/lua_Label.cpp
+    src/lua/lua_Label.h
+    src/lua/lua_Layout.cpp
+    src/lua/lua_Layout.h
+    src/lua/lua_LayoutType.cpp
+    src/lua/lua_LayoutType.h
+    src/lua/lua_Light.cpp
+    src/lua/lua_Light.h
+    src/lua/lua_LightType.cpp
+    src/lua/lua_LightType.h
+    src/lua/lua_Logger.cpp
+    src/lua/lua_Logger.h
+    src/lua/lua_LoggerLevel.cpp
+    src/lua/lua_LoggerLevel.h
+    src/lua/lua_Material.cpp
+    src/lua/lua_Material.h
+    src/lua/lua_MaterialParameter.cpp
+    src/lua/lua_MaterialParameter.h
+    src/lua/lua_MathUtil.cpp
+    src/lua/lua_MathUtil.h
+    src/lua/lua_Matrix.cpp
+    src/lua/lua_Matrix.h
+    src/lua/lua_Mesh.cpp
+    src/lua/lua_Mesh.h
+    src/lua/lua_MeshBatch.cpp
+    src/lua/lua_MeshBatch.h
+    src/lua/lua_MeshIndexFormat.cpp
+    src/lua/lua_MeshIndexFormat.h
+    src/lua/lua_MeshPart.cpp
+    src/lua/lua_MeshPart.h
+    src/lua/lua_MeshPrimitiveType.cpp
+    src/lua/lua_MeshPrimitiveType.h
+    src/lua/lua_MeshSkin.cpp
+    src/lua/lua_MeshSkin.h
+    src/lua/lua_Model.cpp
+    src/lua/lua_Model.h
+    src/lua/lua_Mouse.cpp
+    src/lua/lua_Mouse.h
+    src/lua/lua_MouseMouseEvent.cpp
+    src/lua/lua_MouseMouseEvent.h
+    src/lua/lua_Node.cpp
+    src/lua/lua_Node.h
+    src/lua/lua_NodeCloneContext.cpp
+    src/lua/lua_NodeCloneContext.h
+    src/lua/lua_NodeType.cpp
+    src/lua/lua_NodeType.h
+    src/lua/lua_ParticleEmitter.cpp
+    src/lua/lua_ParticleEmitter.h
+    src/lua/lua_ParticleEmitterTextureBlending.cpp
+    src/lua/lua_ParticleEmitterTextureBlending.h
+    src/lua/lua_Pass.cpp
+    src/lua/lua_Pass.h
+    src/lua/lua_PhysicsCharacter.cpp
+    src/lua/lua_PhysicsCharacter.h
+    src/lua/lua_PhysicsCollisionObject.cpp
+    src/lua/lua_PhysicsCollisionObject.h
+    src/lua/lua_PhysicsCollisionObjectCollisionListener.cpp
+    src/lua/lua_PhysicsCollisionObjectCollisionListener.h
+    src/lua/lua_PhysicsCollisionObjectCollisionListenerEventType.cpp
+    src/lua/lua_PhysicsCollisionObjectCollisionListenerEventType.h
+    src/lua/lua_PhysicsCollisionObjectCollisionPair.cpp
+    src/lua/lua_PhysicsCollisionObjectCollisionPair.h
+    src/lua/lua_PhysicsCollisionObjectType.cpp
+    src/lua/lua_PhysicsCollisionObjectType.h
+    src/lua/lua_PhysicsCollisionShape.cpp
+    src/lua/lua_PhysicsCollisionShape.h
+    src/lua/lua_PhysicsCollisionShapeDefinition.cpp
+    src/lua/lua_PhysicsCollisionShapeDefinition.h
+    src/lua/lua_PhysicsCollisionShapeType.cpp
+    src/lua/lua_PhysicsCollisionShapeType.h
+    src/lua/lua_PhysicsConstraint.cpp
+    src/lua/lua_PhysicsConstraint.h
+    src/lua/lua_PhysicsController.cpp
+    src/lua/lua_PhysicsController.h
+    src/lua/lua_PhysicsControllerHitFilter.cpp
+    src/lua/lua_PhysicsControllerHitFilter.h
+    src/lua/lua_PhysicsControllerHitResult.cpp
+    src/lua/lua_PhysicsControllerHitResult.h
+    src/lua/lua_PhysicsControllerListener.cpp
+    src/lua/lua_PhysicsControllerListener.h
+    src/lua/lua_PhysicsControllerListenerEventType.cpp
+    src/lua/lua_PhysicsControllerListenerEventType.h
+    src/lua/lua_PhysicsFixedConstraint.cpp
+    src/lua/lua_PhysicsFixedConstraint.h
+    src/lua/lua_PhysicsGenericConstraint.cpp
+    src/lua/lua_PhysicsGenericConstraint.h
+    src/lua/lua_PhysicsGhostObject.cpp
+    src/lua/lua_PhysicsGhostObject.h
+    src/lua/lua_PhysicsHingeConstraint.cpp
+    src/lua/lua_PhysicsHingeConstraint.h
+    src/lua/lua_PhysicsRigidBody.cpp
+    src/lua/lua_PhysicsRigidBody.h
+    src/lua/lua_PhysicsRigidBodyParameters.cpp
+    src/lua/lua_PhysicsRigidBodyParameters.h
+    src/lua/lua_PhysicsSocketConstraint.cpp
+    src/lua/lua_PhysicsSocketConstraint.h
+    src/lua/lua_PhysicsSpringConstraint.cpp
+    src/lua/lua_PhysicsSpringConstraint.h
+	src/lua/lua_PhysicsVehicle.cpp
+	src/lua/lua_PhysicsVehicle.h
+	src/lua/lua_PhysicsVehicleWheel.cpp
+	src/lua/lua_PhysicsVehicleWheel.h
+    src/lua/lua_Plane.cpp
+    src/lua/lua_Plane.h
+    src/lua/lua_Platform.cpp
+    src/lua/lua_Platform.h
+    src/lua/lua_Properties.cpp
+    src/lua/lua_Properties.h
+    src/lua/lua_PropertiesType.cpp
+    src/lua/lua_PropertiesType.h
+    src/lua/lua_Quaternion.cpp
+    src/lua/lua_Quaternion.h
+    src/lua/lua_RadioButton.cpp
+    src/lua/lua_RadioButton.h
+    src/lua/lua_Ray.cpp
+    src/lua/lua_Ray.h
+    src/lua/lua_Rectangle.cpp
+    src/lua/lua_Rectangle.h
+    src/lua/lua_Ref.cpp
+    src/lua/lua_Ref.h
+    src/lua/lua_RenderState.cpp
+    src/lua/lua_RenderState.h
+    src/lua/lua_RenderStateAutoBinding.cpp
+    src/lua/lua_RenderStateAutoBinding.h
+    src/lua/lua_RenderStateBlend.cpp
+    src/lua/lua_RenderStateBlend.h
+    src/lua/lua_RenderStateStateBlock.cpp
+    src/lua/lua_RenderStateStateBlock.h
+    src/lua/lua_RenderTarget.cpp
+    src/lua/lua_RenderTarget.h
+    src/lua/lua_Scene.cpp
+    src/lua/lua_Scene.h
+    src/lua/lua_SceneDebugFlags.cpp
+    src/lua/lua_SceneDebugFlags.h
+    src/lua/lua_ScreenDisplayer.cpp
+    src/lua/lua_ScreenDisplayer.h
+    src/lua/lua_ScriptController.cpp
+    src/lua/lua_ScriptController.h
+    src/lua/lua_ScriptTarget.cpp
+    src/lua/lua_ScriptTarget.h
+    src/lua/lua_Slider.cpp
+    src/lua/lua_Slider.h
+    src/lua/lua_SpriteBatch.cpp
+    src/lua/lua_SpriteBatch.h
+    src/lua/lua_Technique.cpp
+    src/lua/lua_Technique.h
+    src/lua/lua_TextBox.cpp
+    src/lua/lua_TextBox.h
+    src/lua/lua_Texture.cpp
+    src/lua/lua_Texture.h
+    src/lua/lua_TextureFilter.cpp
+    src/lua/lua_TextureFilter.h
+    src/lua/lua_TextureFormat.cpp
+    src/lua/lua_TextureFormat.h
+    src/lua/lua_TextureSampler.cpp
+    src/lua/lua_TextureSampler.h
+    src/lua/lua_TextureWrap.cpp
+    src/lua/lua_TextureWrap.h
+    src/lua/lua_Theme.cpp
+    src/lua/lua_Theme.h
+    src/lua/lua_ThemeSideRegions.cpp
+    src/lua/lua_ThemeSideRegions.h
+    src/lua/lua_ThemeStyle.cpp
+    src/lua/lua_ThemeStyle.h
+    src/lua/lua_ThemeThemeImage.cpp
+    src/lua/lua_ThemeThemeImage.h
+    src/lua/lua_ThemeUVs.cpp
+    src/lua/lua_ThemeUVs.h
+    src/lua/lua_Touch.cpp
+    src/lua/lua_Touch.h
+    src/lua/lua_TouchTouchEvent.cpp
+    src/lua/lua_TouchTouchEvent.h
+    src/lua/lua_Transform.cpp
+    src/lua/lua_Transform.h
+    src/lua/lua_TransformListener.cpp
+    src/lua/lua_TransformListener.h
+    src/lua/lua_Uniform.cpp
+    src/lua/lua_Uniform.h
+    src/lua/lua_Vector2.cpp
+    src/lua/lua_Vector2.h
+    src/lua/lua_Vector3.cpp
+    src/lua/lua_Vector3.h
+    src/lua/lua_Vector4.cpp
+    src/lua/lua_Vector4.h
+    src/lua/lua_VertexAttributeBinding.cpp
+    src/lua/lua_VertexAttributeBinding.h
+    src/lua/lua_VertexFormat.cpp
+    src/lua/lua_VertexFormat.h
+    src/lua/lua_VertexFormatElement.cpp
+    src/lua/lua_VertexFormatElement.h
+    src/lua/lua_VertexFormatUsage.cpp
+    src/lua/lua_VertexFormatUsage.h
+    src/lua/lua_VerticalLayout.cpp
+    src/lua/lua_VerticalLayout.h
+)
+
+set(GAMEPLAY_RES
+    res/logo_black.png
+    res/logo_powered_black.png
+    res/logo_powered_white.png
+    res/logo_white.png
+)
+
+set(GAMEPLAY_RES_SHADERS
+    res/shaders/colored-unlit.frag
+    res/shaders/colored-unlit.vert
+    res/shaders/colored.frag
+    res/shaders/colored.vert
+    res/shaders/textured-bumped.frag
+    res/shaders/textured-bumped.vert
+    res/shaders/textured-unlit.frag
+    res/shaders/textured-unlit.vert
+    res/shaders/textured.frag
+    res/shaders/textured.vert
+)
+
+set(GAMEPLAY_RES_SHADERS_LIB
+    res/shaders/lib/attributes-skinning.vert
+    res/shaders/lib/attributes.vert
+    res/shaders/lib/lighting-directional.frag
+    res/shaders/lib/lighting-directional.vert
+    res/shaders/lib/lighting-point.frag
+    res/shaders/lib/lighting-point.vert
+    res/shaders/lib/lighting-spot.frag
+    res/shaders/lib/lighting-spot.vert
+    res/shaders/lib/lighting.frag
+)
+
+include_directories( 
+    src
+    ../external-deps/lua/include
+    ../external-deps/bullet/include
+    ../external-deps/libpng/include
+    ../external-deps/zlib/include
+    ../external-deps/oggvorbis/include
+    ../external-deps/openal/include
+    ../external-deps/glew/include
+)
+
+add_definitions(-D__linux__)
+add_definitions(-lstdc++)
+
+add_library(gameplay STATIC
+    ${GAMEPLAY_SRC}
+    ${GAMEPLAY_LUA}
+)
+
+set_target_properties(gameplay PROPERTIES
+    OUTPUT_NAME "gameplay"
+    CLEAN_DIRECT_OUTPUT 1
+    VERSION ${GAMEPLAY_VERSION}
+)
+
+source_group(lua FILES ${GAMEPLAY_LUA})
+source_group(res FILES ${GAMEPLAY_RES} ${GAMEPLAY_RES} ${GAMEPLAY_RES_SHADERS} ${GAMEPLAY_RES_SHADERS_LIB})
+source_group(src FILES ${GAMEPLAY_SRC})
+
+
+

+ 11 - 2
gameplay/android/jni/Android.mk

@@ -52,15 +52,16 @@ LOCAL_SRC_FILES := \
     Frustum.cpp \
     Game.cpp \
     Gamepad.cpp \
-    gameplay-main-android.cpp \
     Image.cpp \
     Joint.cpp \
     Joystick.cpp \
     Label.cpp \
     Layout.cpp \
     Light.cpp \
+    Logger.cpp \
     Material.cpp \
     MaterialParameter.cpp \
+    MathUtil.cpp \
     Matrix.cpp \
     Mesh.cpp \
     MeshBatch.cpp \
@@ -82,6 +83,8 @@ LOCAL_SRC_FILES := \
     PhysicsRigidBody.cpp \
     PhysicsSocketConstraint.cpp \
     PhysicsSpringConstraint.cpp \
+    PhysicsVehicle.cpp \
+    PhysicsVehicleWheel.cpp \
     Plane.cpp \
     PlatformAndroid.cpp \
     Properties.cpp \
@@ -167,6 +170,8 @@ LOCAL_SRC_FILES := \
     lua/lua_GamepadButtonState.cpp \
     lua/lua_GamepadGamepadEvent.cpp \
     lua/lua_GameState.cpp \
+    lua/lua_Gesture.cpp \
+    lua/lua_GestureGestureEvent.cpp \
     lua/lua_Global.cpp \
     lua/lua_Image.cpp \
     lua/lua_ImageFormat.cpp \
@@ -180,6 +185,8 @@ LOCAL_SRC_FILES := \
     lua/lua_LayoutType.cpp \
     lua/lua_Light.cpp \
     lua/lua_LightType.cpp \
+    lua/lua_Logger.cpp \
+    lua/lua_LoggerLevel.cpp \
     lua/lua_Material.cpp \
     lua/lua_MaterialParameter.cpp \
     lua/lua_MathUtil.cpp \
@@ -222,6 +229,8 @@ LOCAL_SRC_FILES := \
     lua/lua_PhysicsRigidBodyParameters.cpp \
     lua/lua_PhysicsSocketConstraint.cpp \
     lua/lua_PhysicsSpringConstraint.cpp \
+    lua/lua_PhysicsVehicle.cpp \
+    lua/lua_PhysicsVehicleWheel.cpp \
     lua/lua_Plane.cpp \
     lua/lua_Platform.cpp \
     lua/lua_Properties.cpp \
@@ -275,4 +284,4 @@ LOCAL_STATIC_LIBRARIES := android_native_app_glue
 
 include $(BUILD_STATIC_LIBRARY)
 
-$(call import-module,android/native_app_glue)
+$(call import-module,android/native_app_glue)

+ 591 - 0
gameplay/gameplay.cbp

@@ -0,0 +1,591 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="gameplay" />
+		<Option pch_mode="2" />
+		<Option compiler="gcc" />
+		<Build>
+			<Target title="Debug">
+				<Option output="Debug/libgameplay" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="" />
+				<Option object_output="Debug/" />
+				<Option type="2" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Compiler>
+					<Add option="-g" />
+				</Compiler>
+			</Target>
+			<Target title="Release">
+				<Option output="Release/libgameplay" prefix_auto="1" extension_auto="1" />
+				<Option working_dir="" />
+				<Option object_output="Release/" />
+				<Option type="2" />
+				<Option compiler="gcc" />
+				<Option createDefFile="1" />
+				<Compiler>
+					<Add option="-O2" />
+				</Compiler>
+				<Linker>
+					<Add option="-s" />
+				</Linker>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="-pedantic" />
+			<Add option="-Wswitch" />
+			<Add option="-Wunused-variable" />
+			<Add directory="../external-deps/zlib/include" />
+			<Add directory="../external-deps/lua/include" />
+			<Add directory="../external-deps/libpng/include" />
+			<Add directory="../external-deps/bullet/include" />
+			<Add directory="../external-deps/oggvorbis/include" />
+			<Add directory="../gameplay/src" />
+		</Compiler>
+		<Linker>
+			<Add directory="../external-deps/lua/lib/linux" />
+			<Add directory="../external-deps/libpng/lib/linux" />
+			<Add directory="../external-deps/bullet/lib/linux" />
+			<Add directory="../external-deps/oggvorbis/lib/linux" />
+		</Linker>
+		<Unit filename="src/AIAgent.cpp" />
+		<Unit filename="src/AIAgent.h" />
+		<Unit filename="src/AIController.cpp" />
+		<Unit filename="src/AIController.h" />
+		<Unit filename="src/AIMessage.cpp" />
+		<Unit filename="src/AIMessage.h" />
+		<Unit filename="src/AIState.cpp" />
+		<Unit filename="src/AIState.h" />
+		<Unit filename="src/AIStateMachine.cpp" />
+		<Unit filename="src/AIStateMachine.h" />
+		<Unit filename="src/AbsoluteLayout.cpp" />
+		<Unit filename="src/AbsoluteLayout.h" />
+		<Unit filename="src/Animation.cpp" />
+		<Unit filename="src/Animation.h" />
+		<Unit filename="src/AnimationClip.cpp" />
+		<Unit filename="src/AnimationClip.h" />
+		<Unit filename="src/AnimationController.cpp" />
+		<Unit filename="src/AnimationController.h" />
+		<Unit filename="src/AnimationTarget.cpp" />
+		<Unit filename="src/AnimationTarget.h" />
+		<Unit filename="src/AnimationValue.cpp" />
+		<Unit filename="src/AnimationValue.h" />
+		<Unit filename="src/AudioBuffer.cpp" />
+		<Unit filename="src/AudioBuffer.h" />
+		<Unit filename="src/AudioController.cpp" />
+		<Unit filename="src/AudioController.h" />
+		<Unit filename="src/AudioListener.cpp" />
+		<Unit filename="src/AudioListener.h" />
+		<Unit filename="src/AudioSource.cpp" />
+		<Unit filename="src/AudioSource.h" />
+		<Unit filename="src/Base.h" />
+		<Unit filename="src/BoundingBox.cpp" />
+		<Unit filename="src/BoundingBox.h" />
+		<Unit filename="src/BoundingSphere.cpp" />
+		<Unit filename="src/BoundingSphere.h" />
+		<Unit filename="src/Bundle.cpp" />
+		<Unit filename="src/Bundle.h" />
+		<Unit filename="src/Button.cpp" />
+		<Unit filename="src/Button.h" />
+		<Unit filename="src/Camera.cpp" />
+		<Unit filename="src/Camera.h" />
+		<Unit filename="src/CheckBox.cpp" />
+		<Unit filename="src/CheckBox.h" />
+		<Unit filename="src/Container.cpp" />
+		<Unit filename="src/Container.h" />
+		<Unit filename="src/Control.cpp" />
+		<Unit filename="src/Control.h" />
+		<Unit filename="src/Curve.cpp" />
+		<Unit filename="src/Curve.h" />
+		<Unit filename="src/DebugNew.cpp" />
+		<Unit filename="src/DebugNew.h" />
+		<Unit filename="src/DepthStencilTarget.cpp" />
+		<Unit filename="src/DepthStencilTarget.h" />
+		<Unit filename="src/Effect.cpp" />
+		<Unit filename="src/Effect.h" />
+		<Unit filename="src/FileSystem.cpp" />
+		<Unit filename="src/FileSystem.h" />
+		<Unit filename="src/FlowLayout.cpp" />
+		<Unit filename="src/FlowLayout.h" />
+		<Unit filename="src/Font.cpp" />
+		<Unit filename="src/Font.h" />
+		<Unit filename="src/Form.cpp" />
+		<Unit filename="src/Form.h" />
+		<Unit filename="src/FrameBuffer.cpp" />
+		<Unit filename="src/FrameBuffer.h" />
+		<Unit filename="src/Frustum.cpp" />
+		<Unit filename="src/Frustum.h" />
+		<Unit filename="src/Game.cpp" />
+		<Unit filename="src/Game.h" />
+		<Unit filename="src/Gamepad.cpp" />
+		<Unit filename="src/Gamepad.h" />
+		<Unit filename="src/gameplay.h" />
+        <Unit filename="src/gameplay-main-android.cpp" />
+		<Unit filename="src/gameplay-main-blackberry.cpp" />
+		<Unit filename="src/gameplay-main-linux.cpp" />
+		<Unit filename="src/gameplay-main-windows.cpp" />
+		<Unit filename="src/Gesture.h" />
+		<Unit filename="src/Image.cpp" />
+		<Unit filename="src/Image.h" />
+		<Unit filename="src/Joint.cpp" />
+		<Unit filename="src/Joint.h" />
+		<Unit filename="src/Joystick.cpp" />
+		<Unit filename="src/Joystick.h" />
+		<Unit filename="src/Keyboard.h" />
+		<Unit filename="src/Label.cpp" />
+		<Unit filename="src/Label.h" />
+		<Unit filename="src/Layout.cpp" />
+		<Unit filename="src/Layout.h" />
+		<Unit filename="src/Light.cpp" />
+		<Unit filename="src/Light.h" />
+		<Unit filename="src/Logger.cpp" />
+		<Unit filename="src/Logger.h" />
+		<Unit filename="src/Material.cpp" />
+		<Unit filename="src/Material.h" />
+		<Unit filename="src/MaterialParameter.cpp" />
+		<Unit filename="src/MaterialParameter.h" />
+		<Unit filename="src/MathUtil.cpp" />
+		<Unit filename="src/MathUtil.h" />
+		<Unit filename="src/Matrix.cpp" />
+		<Unit filename="src/Matrix.h" />
+		<Unit filename="src/Mesh.cpp" />
+		<Unit filename="src/Mesh.h" />
+		<Unit filename="src/MeshBatch.cpp" />
+		<Unit filename="src/MeshBatch.h" />
+		<Unit filename="src/MeshPart.cpp" />
+		<Unit filename="src/MeshPart.h" />
+		<Unit filename="src/MeshSkin.cpp" />
+		<Unit filename="src/MeshSkin.h" />
+		<Unit filename="src/Model.cpp" />
+		<Unit filename="src/Model.h" />
+		<Unit filename="src/Mouse.h" />
+		<Unit filename="src/Node.cpp" />
+		<Unit filename="src/Node.h" />
+		<Unit filename="src/ParticleEmitter.cpp" />
+		<Unit filename="src/ParticleEmitter.h" />
+		<Unit filename="src/Pass.cpp" />
+		<Unit filename="src/Pass.h" />
+		<Unit filename="src/PhysicsCharacter.cpp" />
+		<Unit filename="src/PhysicsCharacter.h" />
+		<Unit filename="src/PhysicsCollisionObject.cpp" />
+		<Unit filename="src/PhysicsCollisionObject.h" />
+		<Unit filename="src/PhysicsCollisionShape.cpp" />
+		<Unit filename="src/PhysicsCollisionShape.h" />
+		<Unit filename="src/PhysicsConstraint.cpp" />
+		<Unit filename="src/PhysicsConstraint.h" />
+		<Unit filename="src/PhysicsController.cpp" />
+		<Unit filename="src/PhysicsController.h" />
+		<Unit filename="src/PhysicsFixedConstraint.cpp" />
+		<Unit filename="src/PhysicsFixedConstraint.h" />
+		<Unit filename="src/PhysicsGenericConstraint.cpp" />
+		<Unit filename="src/PhysicsGenericConstraint.h" />
+		<Unit filename="src/PhysicsGhostObject.cpp" />
+		<Unit filename="src/PhysicsGhostObject.h" />
+		<Unit filename="src/PhysicsHingeConstraint.cpp" />
+		<Unit filename="src/PhysicsHingeConstraint.h" />
+		<Unit filename="src/PhysicsRigidBody.cpp" />
+		<Unit filename="src/PhysicsRigidBody.h" />
+		<Unit filename="src/PhysicsSocketConstraint.cpp" />
+		<Unit filename="src/PhysicsSocketConstraint.h" />
+		<Unit filename="src/PhysicsSpringConstraint.cpp" />
+		<Unit filename="src/PhysicsSpringConstraint.h" />
+		<Unit filename="src/PhysicsVehicle.cpp" />
+		<Unit filename="src/PhysicsVehicle.h" />
+		<Unit filename="src/PhysicsVehicleWheel.cpp" />
+		<Unit filename="src/PhysicsVehicleWheel.h" />
+		<Unit filename="src/Plane.cpp" />
+		<Unit filename="src/Plane.h" />
+		<Unit filename="src/Platform.h" />
+		<Unit filename="src/PlatformAndroid.cpp" />
+		<Unit filename="src/PlatformBlackBerry.cpp" />
+		<Unit filename="src/PlatformLinux.cpp" />
+		<Unit filename="src/PlatformWindows.cpp" />
+		<Unit filename="src/Properties.cpp" />
+		<Unit filename="src/Properties.h" />
+		<Unit filename="src/Quaternion.cpp" />
+		<Unit filename="src/Quaternion.h" />
+		<Unit filename="src/RadioButton.cpp" />
+		<Unit filename="src/RadioButton.h" />
+		<Unit filename="src/Ray.cpp" />
+		<Unit filename="src/Ray.h" />
+		<Unit filename="src/Rectangle.cpp" />
+		<Unit filename="src/Rectangle.h" />
+		<Unit filename="src/Ref.cpp" />
+		<Unit filename="src/Ref.h" />
+		<Unit filename="src/RenderState.cpp" />
+		<Unit filename="src/RenderState.h" />
+		<Unit filename="src/RenderTarget.cpp" />
+		<Unit filename="src/RenderTarget.h" />
+		<Unit filename="src/Scene.cpp" />
+		<Unit filename="src/Scene.h" />
+		<Unit filename="src/SceneLoader.cpp" />
+		<Unit filename="src/SceneLoader.h" />
+		<Unit filename="src/ScreenDisplayer.cpp" />
+		<Unit filename="src/ScreenDisplayer.h" />
+		<Unit filename="src/ScriptController.cpp" />
+		<Unit filename="src/ScriptController.h" />
+		<Unit filename="src/ScriptTarget.cpp" />
+		<Unit filename="src/ScriptTarget.h" />
+		<Unit filename="src/Slider.cpp" />
+		<Unit filename="src/Slider.h" />
+		<Unit filename="src/SpriteBatch.cpp" />
+		<Unit filename="src/SpriteBatch.h" />
+		<Unit filename="src/Technique.cpp" />
+		<Unit filename="src/Technique.h" />
+		<Unit filename="src/TextBox.cpp" />
+		<Unit filename="src/TextBox.h" />
+		<Unit filename="src/Texture.cpp" />
+		<Unit filename="src/Texture.h" />
+		<Unit filename="src/Theme.cpp" />
+		<Unit filename="src/Theme.h" />
+		<Unit filename="src/ThemeStyle.cpp" />
+		<Unit filename="src/ThemeStyle.h" />
+		<Unit filename="src/TimeListener.h" />
+		<Unit filename="src/Touch.h" />
+		<Unit filename="src/Transform.cpp" />
+		<Unit filename="src/Transform.h" />
+		<Unit filename="src/Vector2.cpp" />
+		<Unit filename="src/Vector2.h" />
+		<Unit filename="src/Vector3.cpp" />
+		<Unit filename="src/Vector3.h" />
+		<Unit filename="src/Vector4.cpp" />
+		<Unit filename="src/Vector4.h" />
+		<Unit filename="src/VertexAttributeBinding.cpp" />
+		<Unit filename="src/VertexAttributeBinding.h" />
+		<Unit filename="src/VertexFormat.cpp" />
+		<Unit filename="src/VertexFormat.h" />
+		<Unit filename="src/VerticalLayout.cpp" />
+		<Unit filename="src/VerticalLayout.h" />
+		<Unit filename="src/lua/lua_AIAgent.cpp" />
+		<Unit filename="src/lua/lua_AIAgent.h" />
+		<Unit filename="src/lua/lua_AIAgentListener.cpp" />
+		<Unit filename="src/lua/lua_AIAgentListener.h" />
+		<Unit filename="src/lua/lua_AIController.cpp" />
+		<Unit filename="src/lua/lua_AIController.h" />
+		<Unit filename="src/lua/lua_AIMessage.cpp" />
+		<Unit filename="src/lua/lua_AIMessage.h" />
+		<Unit filename="src/lua/lua_AIMessageParameterType.cpp" />
+		<Unit filename="src/lua/lua_AIMessageParameterType.h" />
+		<Unit filename="src/lua/lua_AIState.cpp" />
+		<Unit filename="src/lua/lua_AIState.h" />
+		<Unit filename="src/lua/lua_AIStateListener.cpp" />
+		<Unit filename="src/lua/lua_AIStateListener.h" />
+		<Unit filename="src/lua/lua_AIStateMachine.cpp" />
+		<Unit filename="src/lua/lua_AIStateMachine.h" />
+		<Unit filename="src/lua/lua_AbsoluteLayout.cpp" />
+		<Unit filename="src/lua/lua_AbsoluteLayout.h" />
+		<Unit filename="src/lua/lua_Animation.cpp" />
+		<Unit filename="src/lua/lua_Animation.h" />
+		<Unit filename="src/lua/lua_AnimationClip.cpp" />
+		<Unit filename="src/lua/lua_AnimationClip.h" />
+		<Unit filename="src/lua/lua_AnimationClipListener.cpp" />
+		<Unit filename="src/lua/lua_AnimationClipListener.h" />
+		<Unit filename="src/lua/lua_AnimationClipListenerEventType.cpp" />
+		<Unit filename="src/lua/lua_AnimationClipListenerEventType.h" />
+		<Unit filename="src/lua/lua_AnimationController.cpp" />
+		<Unit filename="src/lua/lua_AnimationController.h" />
+		<Unit filename="src/lua/lua_AnimationTarget.cpp" />
+		<Unit filename="src/lua/lua_AnimationTarget.h" />
+		<Unit filename="src/lua/lua_AnimationValue.cpp" />
+		<Unit filename="src/lua/lua_AnimationValue.h" />
+		<Unit filename="src/lua/lua_AudioBuffer.cpp" />
+		<Unit filename="src/lua/lua_AudioBuffer.h" />
+		<Unit filename="src/lua/lua_AudioController.cpp" />
+		<Unit filename="src/lua/lua_AudioController.h" />
+		<Unit filename="src/lua/lua_AudioListener.cpp" />
+		<Unit filename="src/lua/lua_AudioListener.h" />
+		<Unit filename="src/lua/lua_AudioSource.cpp" />
+		<Unit filename="src/lua/lua_AudioSource.h" />
+		<Unit filename="src/lua/lua_AudioSourceState.cpp" />
+		<Unit filename="src/lua/lua_AudioSourceState.h" />
+		<Unit filename="src/lua/lua_BoundingBox.cpp" />
+		<Unit filename="src/lua/lua_BoundingBox.h" />
+		<Unit filename="src/lua/lua_BoundingSphere.cpp" />
+		<Unit filename="src/lua/lua_BoundingSphere.h" />
+		<Unit filename="src/lua/lua_Bundle.cpp" />
+		<Unit filename="src/lua/lua_Bundle.h" />
+		<Unit filename="src/lua/lua_Button.cpp" />
+		<Unit filename="src/lua/lua_Button.h" />
+		<Unit filename="src/lua/lua_Camera.cpp" />
+		<Unit filename="src/lua/lua_Camera.h" />
+		<Unit filename="src/lua/lua_CameraType.cpp" />
+		<Unit filename="src/lua/lua_CameraType.h" />
+		<Unit filename="src/lua/lua_CheckBox.cpp" />
+		<Unit filename="src/lua/lua_CheckBox.h" />
+		<Unit filename="src/lua/lua_Container.cpp" />
+		<Unit filename="src/lua/lua_Container.h" />
+		<Unit filename="src/lua/lua_ContainerScroll.cpp" />
+		<Unit filename="src/lua/lua_ContainerScroll.h" />
+		<Unit filename="src/lua/lua_Control.cpp" />
+		<Unit filename="src/lua/lua_Control.h" />
+		<Unit filename="src/lua/lua_ControlAlignment.cpp" />
+		<Unit filename="src/lua/lua_ControlAlignment.h" />
+		<Unit filename="src/lua/lua_ControlListener.cpp" />
+		<Unit filename="src/lua/lua_ControlListener.h" />
+		<Unit filename="src/lua/lua_ControlListenerEventType.cpp" />
+		<Unit filename="src/lua/lua_ControlListenerEventType.h" />
+		<Unit filename="src/lua/lua_ControlState.cpp" />
+		<Unit filename="src/lua/lua_ControlState.h" />
+		<Unit filename="src/lua/lua_Curve.cpp" />
+		<Unit filename="src/lua/lua_Curve.h" />
+		<Unit filename="src/lua/lua_CurveInterpolationType.cpp" />
+		<Unit filename="src/lua/lua_CurveInterpolationType.h" />
+		<Unit filename="src/lua/lua_DepthStencilTarget.cpp" />
+		<Unit filename="src/lua/lua_DepthStencilTarget.h" />
+		<Unit filename="src/lua/lua_DepthStencilTargetFormat.cpp" />
+		<Unit filename="src/lua/lua_DepthStencilTargetFormat.h" />
+		<Unit filename="src/lua/lua_Effect.cpp" />
+		<Unit filename="src/lua/lua_Effect.h" />
+		<Unit filename="src/lua/lua_FileSystem.cpp" />
+		<Unit filename="src/lua/lua_FileSystem.h" />
+		<Unit filename="src/lua/lua_FlowLayout.cpp" />
+		<Unit filename="src/lua/lua_FlowLayout.h" />
+		<Unit filename="src/lua/lua_Font.cpp" />
+		<Unit filename="src/lua/lua_Font.h" />
+		<Unit filename="src/lua/lua_FontJustify.cpp" />
+		<Unit filename="src/lua/lua_FontJustify.h" />
+		<Unit filename="src/lua/lua_FontStyle.cpp" />
+		<Unit filename="src/lua/lua_FontStyle.h" />
+		<Unit filename="src/lua/lua_FontText.cpp" />
+		<Unit filename="src/lua/lua_FontText.h" />
+		<Unit filename="src/lua/lua_Form.cpp" />
+		<Unit filename="src/lua/lua_Form.h" />
+		<Unit filename="src/lua/lua_FrameBuffer.cpp" />
+		<Unit filename="src/lua/lua_FrameBuffer.h" />
+		<Unit filename="src/lua/lua_Frustum.cpp" />
+		<Unit filename="src/lua/lua_Frustum.h" />
+		<Unit filename="src/lua/lua_Game.cpp" />
+		<Unit filename="src/lua/lua_Game.h" />
+		<Unit filename="src/lua/lua_GameClearFlags.cpp" />
+		<Unit filename="src/lua/lua_GameClearFlags.h" />
+		<Unit filename="src/lua/lua_GameState.cpp" />
+		<Unit filename="src/lua/lua_GameState.h" />
+		<Unit filename="src/lua/lua_Gamepad.cpp" />
+		<Unit filename="src/lua/lua_Gamepad.h" />
+		<Unit filename="src/lua/lua_GamepadButtonState.cpp" />
+		<Unit filename="src/lua/lua_GamepadButtonState.h" />
+		<Unit filename="src/lua/lua_GamepadGamepadEvent.cpp" />
+		<Unit filename="src/lua/lua_GamepadGamepadEvent.h" />
+		<Unit filename="src/lua/lua_Gesture.cpp" />
+		<Unit filename="src/lua/lua_Gesture.h" />
+		<Unit filename="src/lua/lua_GestureGestureEvent.cpp" />
+		<Unit filename="src/lua/lua_GestureGestureEvent.h" />
+		<Unit filename="src/lua/lua_Global.cpp" />
+		<Unit filename="src/lua/lua_Global.h" />
+		<Unit filename="src/lua/lua_Image.cpp" />
+		<Unit filename="src/lua/lua_Image.h" />
+		<Unit filename="src/lua/lua_ImageFormat.cpp" />
+		<Unit filename="src/lua/lua_ImageFormat.h" />
+		<Unit filename="src/lua/lua_Joint.cpp" />
+		<Unit filename="src/lua/lua_Joint.h" />
+		<Unit filename="src/lua/lua_Joystick.cpp" />
+		<Unit filename="src/lua/lua_Joystick.h" />
+		<Unit filename="src/lua/lua_Keyboard.cpp" />
+		<Unit filename="src/lua/lua_Keyboard.h" />
+		<Unit filename="src/lua/lua_KeyboardKey.cpp" />
+		<Unit filename="src/lua/lua_KeyboardKey.h" />
+		<Unit filename="src/lua/lua_KeyboardKeyEvent.cpp" />
+		<Unit filename="src/lua/lua_KeyboardKeyEvent.h" />
+		<Unit filename="src/lua/lua_Label.cpp" />
+		<Unit filename="src/lua/lua_Label.h" />
+		<Unit filename="src/lua/lua_Layout.cpp" />
+		<Unit filename="src/lua/lua_Layout.h" />
+		<Unit filename="src/lua/lua_LayoutType.cpp" />
+		<Unit filename="src/lua/lua_LayoutType.h" />
+		<Unit filename="src/lua/lua_Light.cpp" />
+		<Unit filename="src/lua/lua_Light.h" />
+		<Unit filename="src/lua/lua_LightType.cpp" />
+		<Unit filename="src/lua/lua_LightType.h" />
+		<Unit filename="src/lua/lua_Logger.cpp" />
+		<Unit filename="src/lua/lua_Logger.h" />
+		<Unit filename="src/lua/lua_LoggerLevel.cpp" />
+		<Unit filename="src/lua/lua_LoggerLevel.h" />
+		<Unit filename="src/lua/lua_Material.cpp" />
+		<Unit filename="src/lua/lua_Material.h" />
+		<Unit filename="src/lua/lua_MaterialParameter.cpp" />
+		<Unit filename="src/lua/lua_MaterialParameter.h" />
+		<Unit filename="src/lua/lua_MathUtil.cpp" />
+		<Unit filename="src/lua/lua_MathUtil.h" />
+		<Unit filename="src/lua/lua_Matrix.cpp" />
+		<Unit filename="src/lua/lua_Matrix.h" />
+		<Unit filename="src/lua/lua_Mesh.cpp" />
+		<Unit filename="src/lua/lua_Mesh.h" />
+		<Unit filename="src/lua/lua_MeshBatch.cpp" />
+		<Unit filename="src/lua/lua_MeshBatch.h" />
+		<Unit filename="src/lua/lua_MeshIndexFormat.cpp" />
+		<Unit filename="src/lua/lua_MeshIndexFormat.h" />
+		<Unit filename="src/lua/lua_MeshPart.cpp" />
+		<Unit filename="src/lua/lua_MeshPart.h" />
+		<Unit filename="src/lua/lua_MeshPrimitiveType.cpp" />
+		<Unit filename="src/lua/lua_MeshPrimitiveType.h" />
+		<Unit filename="src/lua/lua_MeshSkin.cpp" />
+		<Unit filename="src/lua/lua_MeshSkin.h" />
+		<Unit filename="src/lua/lua_Model.cpp" />
+		<Unit filename="src/lua/lua_Model.h" />
+		<Unit filename="src/lua/lua_Mouse.cpp" />
+		<Unit filename="src/lua/lua_Mouse.h" />
+		<Unit filename="src/lua/lua_MouseMouseEvent.cpp" />
+		<Unit filename="src/lua/lua_MouseMouseEvent.h" />
+		<Unit filename="src/lua/lua_Node.cpp" />
+		<Unit filename="src/lua/lua_Node.h" />
+		<Unit filename="src/lua/lua_NodeCloneContext.cpp" />
+		<Unit filename="src/lua/lua_NodeCloneContext.h" />
+		<Unit filename="src/lua/lua_NodeType.cpp" />
+		<Unit filename="src/lua/lua_NodeType.h" />
+		<Unit filename="src/lua/lua_ParticleEmitter.cpp" />
+		<Unit filename="src/lua/lua_ParticleEmitter.h" />
+		<Unit filename="src/lua/lua_ParticleEmitterTextureBlending.cpp" />
+		<Unit filename="src/lua/lua_ParticleEmitterTextureBlending.h" />
+		<Unit filename="src/lua/lua_Pass.cpp" />
+		<Unit filename="src/lua/lua_Pass.h" />
+		<Unit filename="src/lua/lua_PhysicsCharacter.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCharacter.h" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObject.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObject.h" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObjectCollisionListener.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObjectCollisionListener.h" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObjectCollisionListenerEventType.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObjectCollisionListenerEventType.h" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObjectCollisionPair.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObjectCollisionPair.h" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObjectType.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCollisionObjectType.h" />
+		<Unit filename="src/lua/lua_PhysicsCollisionShape.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCollisionShape.h" />
+		<Unit filename="src/lua/lua_PhysicsCollisionShapeDefinition.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCollisionShapeDefinition.h" />
+		<Unit filename="src/lua/lua_PhysicsCollisionShapeType.cpp" />
+		<Unit filename="src/lua/lua_PhysicsCollisionShapeType.h" />
+		<Unit filename="src/lua/lua_PhysicsConstraint.cpp" />
+		<Unit filename="src/lua/lua_PhysicsConstraint.h" />
+		<Unit filename="src/lua/lua_PhysicsController.cpp" />
+		<Unit filename="src/lua/lua_PhysicsController.h" />
+		<Unit filename="src/lua/lua_PhysicsControllerHitFilter.cpp" />
+		<Unit filename="src/lua/lua_PhysicsControllerHitFilter.h" />
+		<Unit filename="src/lua/lua_PhysicsControllerHitResult.cpp" />
+		<Unit filename="src/lua/lua_PhysicsControllerHitResult.h" />
+		<Unit filename="src/lua/lua_PhysicsControllerListener.cpp" />
+		<Unit filename="src/lua/lua_PhysicsControllerListener.h" />
+		<Unit filename="src/lua/lua_PhysicsControllerListenerEventType.cpp" />
+		<Unit filename="src/lua/lua_PhysicsControllerListenerEventType.h" />
+		<Unit filename="src/lua/lua_PhysicsFixedConstraint.cpp" />
+		<Unit filename="src/lua/lua_PhysicsFixedConstraint.h" />
+		<Unit filename="src/lua/lua_PhysicsGenericConstraint.cpp" />
+		<Unit filename="src/lua/lua_PhysicsGenericConstraint.h" />
+		<Unit filename="src/lua/lua_PhysicsGhostObject.cpp" />
+		<Unit filename="src/lua/lua_PhysicsGhostObject.h" />
+		<Unit filename="src/lua/lua_PhysicsHingeConstraint.cpp" />
+		<Unit filename="src/lua/lua_PhysicsHingeConstraint.h" />
+		<Unit filename="src/lua/lua_PhysicsRigidBody.cpp" />
+		<Unit filename="src/lua/lua_PhysicsRigidBody.h" />
+		<Unit filename="src/lua/lua_PhysicsRigidBodyParameters.cpp" />
+		<Unit filename="src/lua/lua_PhysicsRigidBodyParameters.h" />
+		<Unit filename="src/lua/lua_PhysicsSocketConstraint.cpp" />
+		<Unit filename="src/lua/lua_PhysicsSocketConstraint.h" />
+		<Unit filename="src/lua/lua_PhysicsSpringConstraint.cpp" />
+		<Unit filename="src/lua/lua_PhysicsSpringConstraint.h" />
+		<Unit filename="src/lua/lua_PhysicsVehicle.cpp" />
+		<Unit filename="src/lua/lua_PhysicsVehicle.h" />
+		<Unit filename="src/lua/lua_PhysicsVehicleWheel.cpp" />
+		<Unit filename="src/lua/lua_PhysicsVehicleWheel.h" />
+		<Unit filename="src/lua/lua_Plane.cpp" />
+		<Unit filename="src/lua/lua_Plane.h" />
+		<Unit filename="src/lua/lua_Platform.cpp" />
+		<Unit filename="src/lua/lua_Platform.h" />
+		<Unit filename="src/lua/lua_Properties.cpp" />
+		<Unit filename="src/lua/lua_Properties.h" />
+		<Unit filename="src/lua/lua_PropertiesType.cpp" />
+		<Unit filename="src/lua/lua_PropertiesType.h" />
+		<Unit filename="src/lua/lua_Quaternion.cpp" />
+		<Unit filename="src/lua/lua_Quaternion.h" />
+		<Unit filename="src/lua/lua_RadioButton.cpp" />
+		<Unit filename="src/lua/lua_RadioButton.h" />
+		<Unit filename="src/lua/lua_Ray.cpp" />
+		<Unit filename="src/lua/lua_Ray.h" />
+		<Unit filename="src/lua/lua_Rectangle.cpp" />
+		<Unit filename="src/lua/lua_Rectangle.h" />
+		<Unit filename="src/lua/lua_Ref.cpp" />
+		<Unit filename="src/lua/lua_Ref.h" />
+		<Unit filename="src/lua/lua_RenderState.cpp" />
+		<Unit filename="src/lua/lua_RenderState.h" />
+		<Unit filename="src/lua/lua_RenderStateAutoBinding.cpp" />
+		<Unit filename="src/lua/lua_RenderStateAutoBinding.h" />
+		<Unit filename="src/lua/lua_RenderStateBlend.cpp" />
+		<Unit filename="src/lua/lua_RenderStateBlend.h" />
+		<Unit filename="src/lua/lua_RenderStateStateBlock.cpp" />
+		<Unit filename="src/lua/lua_RenderStateStateBlock.h" />
+		<Unit filename="src/lua/lua_RenderTarget.cpp" />
+		<Unit filename="src/lua/lua_RenderTarget.h" />
+		<Unit filename="src/lua/lua_Scene.cpp" />
+		<Unit filename="src/lua/lua_Scene.h" />
+		<Unit filename="src/lua/lua_SceneDebugFlags.cpp" />
+		<Unit filename="src/lua/lua_SceneDebugFlags.h" />
+		<Unit filename="src/lua/lua_ScreenDisplayer.cpp" />
+		<Unit filename="src/lua/lua_ScreenDisplayer.h" />
+		<Unit filename="src/lua/lua_ScriptController.cpp" />
+		<Unit filename="src/lua/lua_ScriptController.h" />
+		<Unit filename="src/lua/lua_ScriptTarget.cpp" />
+		<Unit filename="src/lua/lua_ScriptTarget.h" />
+		<Unit filename="src/lua/lua_Slider.cpp" />
+		<Unit filename="src/lua/lua_Slider.h" />
+		<Unit filename="src/lua/lua_SpriteBatch.cpp" />
+		<Unit filename="src/lua/lua_SpriteBatch.h" />
+		<Unit filename="src/lua/lua_Technique.cpp" />
+		<Unit filename="src/lua/lua_Technique.h" />
+		<Unit filename="src/lua/lua_TextBox.cpp" />
+		<Unit filename="src/lua/lua_TextBox.h" />
+		<Unit filename="src/lua/lua_Texture.cpp" />
+		<Unit filename="src/lua/lua_Texture.h" />
+		<Unit filename="src/lua/lua_TextureFilter.cpp" />
+		<Unit filename="src/lua/lua_TextureFilter.h" />
+		<Unit filename="src/lua/lua_TextureFormat.cpp" />
+		<Unit filename="src/lua/lua_TextureFormat.h" />
+		<Unit filename="src/lua/lua_TextureSampler.cpp" />
+		<Unit filename="src/lua/lua_TextureSampler.h" />
+		<Unit filename="src/lua/lua_TextureWrap.cpp" />
+		<Unit filename="src/lua/lua_TextureWrap.h" />
+		<Unit filename="src/lua/lua_Theme.cpp" />
+		<Unit filename="src/lua/lua_Theme.h" />
+		<Unit filename="src/lua/lua_ThemeSideRegions.cpp" />
+		<Unit filename="src/lua/lua_ThemeSideRegions.h" />
+		<Unit filename="src/lua/lua_ThemeStyle.cpp" />
+		<Unit filename="src/lua/lua_ThemeStyle.h" />
+		<Unit filename="src/lua/lua_ThemeThemeImage.cpp" />
+		<Unit filename="src/lua/lua_ThemeThemeImage.h" />
+		<Unit filename="src/lua/lua_ThemeUVs.cpp" />
+		<Unit filename="src/lua/lua_ThemeUVs.h" />
+		<Unit filename="src/lua/lua_Touch.cpp" />
+		<Unit filename="src/lua/lua_Touch.h" />
+		<Unit filename="src/lua/lua_TouchTouchEvent.cpp" />
+		<Unit filename="src/lua/lua_TouchTouchEvent.h" />
+		<Unit filename="src/lua/lua_Transform.cpp" />
+		<Unit filename="src/lua/lua_Transform.h" />
+		<Unit filename="src/lua/lua_TransformListener.cpp" />
+		<Unit filename="src/lua/lua_TransformListener.h" />
+		<Unit filename="src/lua/lua_Uniform.cpp" />
+		<Unit filename="src/lua/lua_Uniform.h" />
+		<Unit filename="src/lua/lua_Vector2.cpp" />
+		<Unit filename="src/lua/lua_Vector2.h" />
+		<Unit filename="src/lua/lua_Vector3.cpp" />
+		<Unit filename="src/lua/lua_Vector3.h" />
+		<Unit filename="src/lua/lua_Vector4.cpp" />
+		<Unit filename="src/lua/lua_Vector4.h" />
+		<Unit filename="src/lua/lua_VertexAttributeBinding.cpp" />
+		<Unit filename="src/lua/lua_VertexAttributeBinding.h" />
+		<Unit filename="src/lua/lua_VertexFormat.cpp" />
+		<Unit filename="src/lua/lua_VertexFormat.h" />
+		<Unit filename="src/lua/lua_VertexFormatElement.cpp" />
+		<Unit filename="src/lua/lua_VertexFormatElement.h" />
+		<Unit filename="src/lua/lua_VertexFormatUsage.cpp" />
+		<Unit filename="src/lua/lua_VertexFormatUsage.h" />
+		<Unit filename="src/lua/lua_VerticalLayout.cpp" />
+		<Unit filename="src/lua/lua_VerticalLayout.h" />
+		<Unit filename="src/lua/lua_all_bindings.cpp" />
+		<Unit filename="src/lua/lua_all_bindings.h" />
+		<Extensions>
+			<code_completion />
+			<debugger />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>

+ 255 - 8
gameplay/gameplay.vcxproj

@@ -1,14 +1,38 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="DebugMem|BlackBerry">
+      <Configuration>DebugMem</Configuration>
+      <Platform>BlackBerry</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="DebugMem|BlackBerrySimulator">
+      <Configuration>DebugMem</Configuration>
+      <Platform>BlackBerrySimulator</Platform>
+    </ProjectConfiguration>
     <ProjectConfiguration Include="DebugMem|Win32">
       <Configuration>DebugMem</Configuration>
       <Platform>Win32</Platform>
     </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|BlackBerry">
+      <Configuration>Debug</Configuration>
+      <Platform>BlackBerry</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|BlackBerrySimulator">
+      <Configuration>Debug</Configuration>
+      <Platform>BlackBerrySimulator</Platform>
+    </ProjectConfiguration>
     <ProjectConfiguration Include="Debug|Win32">
       <Configuration>Debug</Configuration>
       <Platform>Win32</Platform>
     </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|BlackBerry">
+      <Configuration>Release</Configuration>
+      <Platform>BlackBerry</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|BlackBerrySimulator">
+      <Configuration>Release</Configuration>
+      <Platform>BlackBerrySimulator</Platform>
+    </ProjectConfiguration>
     <ProjectConfiguration Include="Release|Win32">
       <Configuration>Release</Configuration>
       <Platform>Win32</Platform>
@@ -50,14 +74,16 @@
     <ClCompile Include="src\Game.cpp" />
     <ClCompile Include="src\Gamepad.cpp" />
     <ClCompile Include="src\gameplay-main-android.cpp" />
-    <ClCompile Include="src\gameplay-main-qnx.cpp" />
-    <ClCompile Include="src\gameplay-main-win32.cpp" />
+    <ClCompile Include="src\gameplay-main-blackberry.cpp" />
+    <ClCompile Include="src\gameplay-main-linux.cpp" />
+    <ClCompile Include="src\gameplay-main-windows.cpp" />
     <ClCompile Include="src\Image.cpp" />
     <ClCompile Include="src\Joint.cpp" />
     <ClCompile Include="src\Joystick.cpp" />
     <ClCompile Include="src\Label.cpp" />
     <ClCompile Include="src\Layout.cpp" />
     <ClCompile Include="src\Light.cpp" />
+    <ClCompile Include="src\Logger.cpp" />
     <ClCompile Include="src\lua\lua_AbsoluteLayout.cpp" />
     <ClCompile Include="src\lua\lua_AIAgent.cpp" />
     <ClCompile Include="src\lua\lua_AIAgentListener.cpp" />
@@ -114,6 +140,8 @@
     <ClCompile Include="src\lua\lua_GamepadButtonState.cpp" />
     <ClCompile Include="src\lua\lua_GamepadGamepadEvent.cpp" />
     <ClCompile Include="src\lua\lua_GameState.cpp" />
+    <ClCompile Include="src\lua\lua_Gesture.cpp" />
+    <ClCompile Include="src\lua\lua_GestureGestureEvent.cpp" />
     <ClCompile Include="src\lua\lua_Global.cpp" />
     <ClCompile Include="src\lua\lua_Image.cpp" />
     <ClCompile Include="src\lua\lua_ImageFormat.cpp" />
@@ -127,6 +155,8 @@
     <ClCompile Include="src\lua\lua_LayoutType.cpp" />
     <ClCompile Include="src\lua\lua_Light.cpp" />
     <ClCompile Include="src\lua\lua_LightType.cpp" />
+    <ClCompile Include="src\lua\lua_Logger.cpp" />
+    <ClCompile Include="src\lua\lua_LoggerLevel.cpp" />
     <ClCompile Include="src\lua\lua_Material.cpp" />
     <ClCompile Include="src\lua\lua_MaterialParameter.cpp" />
     <ClCompile Include="src\lua\lua_MathUtil.cpp" />
@@ -169,6 +199,8 @@
     <ClCompile Include="src\lua\lua_PhysicsRigidBodyParameters.cpp" />
     <ClCompile Include="src\lua\lua_PhysicsSocketConstraint.cpp" />
     <ClCompile Include="src\lua\lua_PhysicsSpringConstraint.cpp" />
+    <ClCompile Include="src\lua\lua_PhysicsVehicle.cpp" />
+    <ClCompile Include="src\lua\lua_PhysicsVehicleWheel.cpp" />
     <ClCompile Include="src\lua\lua_Plane.cpp" />
     <ClCompile Include="src\lua\lua_Platform.cpp" />
     <ClCompile Include="src\lua\lua_Properties.cpp" />
@@ -216,6 +248,7 @@
     <ClCompile Include="src\lua\lua_VertexFormatUsage.cpp" />
     <ClCompile Include="src\lua\lua_VerticalLayout.cpp" />
     <ClCompile Include="src\Material.cpp" />
+    <ClCompile Include="src\MathUtil.cpp" />
     <ClCompile Include="src\MeshBatch.cpp" />
     <ClCompile Include="src\Pass.cpp" />
     <ClCompile Include="src\MaterialParameter.cpp" />
@@ -239,10 +272,13 @@
     <ClCompile Include="src\PhysicsRigidBody.cpp" />
     <ClCompile Include="src\PhysicsSocketConstraint.cpp" />
     <ClCompile Include="src\PhysicsSpringConstraint.cpp" />
+    <ClCompile Include="src\PhysicsVehicle.cpp" />
+    <ClCompile Include="src\PhysicsVehicleWheel.cpp" />
     <ClCompile Include="src\Plane.cpp" />
     <ClCompile Include="src\PlatformAndroid.cpp" />
-    <ClCompile Include="src\PlatformQNX.cpp" />
-    <ClCompile Include="src\PlatformWin32.cpp" />
+    <ClCompile Include="src\PlatformBlackBerry.cpp" />
+    <ClCompile Include="src\PlatformLinux.cpp" />
+    <ClCompile Include="src\PlatformWindows.cpp" />
     <ClCompile Include="src\Properties.cpp" />
     <ClCompile Include="src\Quaternion.cpp" />
     <ClCompile Include="src\RadioButton.cpp" />
@@ -308,6 +344,7 @@
     <ClInclude Include="src\Game.h" />
     <ClInclude Include="src\Gamepad.h" />
     <ClInclude Include="src\gameplay.h" />
+    <ClInclude Include="src\Gesture.h" />
     <ClInclude Include="src\Image.h" />
     <ClInclude Include="src\Joint.h" />
     <ClInclude Include="src\Joystick.h" />
@@ -315,6 +352,7 @@
     <ClInclude Include="src\Label.h" />
     <ClInclude Include="src\Layout.h" />
     <ClInclude Include="src\Light.h" />
+    <ClInclude Include="src\Logger.h" />
     <ClInclude Include="src\lua\lua_AbsoluteLayout.h" />
     <ClInclude Include="src\lua\lua_AIAgent.h" />
     <ClInclude Include="src\lua\lua_AIAgentListener.h" />
@@ -371,6 +409,8 @@
     <ClInclude Include="src\lua\lua_GamepadButtonState.h" />
     <ClInclude Include="src\lua\lua_GamepadGamepadEvent.h" />
     <ClInclude Include="src\lua\lua_GameState.h" />
+    <ClInclude Include="src\lua\lua_Gesture.h" />
+    <ClInclude Include="src\lua\lua_GestureGestureEvent.h" />
     <ClInclude Include="src\lua\lua_Global.h" />
     <ClInclude Include="src\lua\lua_Image.h" />
     <ClInclude Include="src\lua\lua_ImageFormat.h" />
@@ -384,6 +424,8 @@
     <ClInclude Include="src\lua\lua_LayoutType.h" />
     <ClInclude Include="src\lua\lua_Light.h" />
     <ClInclude Include="src\lua\lua_LightType.h" />
+    <ClInclude Include="src\lua\lua_Logger.h" />
+    <ClInclude Include="src\lua\lua_LoggerLevel.h" />
     <ClInclude Include="src\lua\lua_Material.h" />
     <ClInclude Include="src\lua\lua_MaterialParameter.h" />
     <ClInclude Include="src\lua\lua_MathUtil.h" />
@@ -426,6 +468,8 @@
     <ClInclude Include="src\lua\lua_PhysicsRigidBodyParameters.h" />
     <ClInclude Include="src\lua\lua_PhysicsSocketConstraint.h" />
     <ClInclude Include="src\lua\lua_PhysicsSpringConstraint.h" />
+    <ClInclude Include="src\lua\lua_PhysicsVehicle.h" />
+    <ClInclude Include="src\lua\lua_PhysicsVehicleWheel.h" />
     <ClInclude Include="src\lua\lua_Plane.h" />
     <ClInclude Include="src\lua\lua_Platform.h" />
     <ClInclude Include="src\lua\lua_Properties.h" />
@@ -498,6 +542,8 @@
     <ClInclude Include="src\PhysicsRigidBody.h" />
     <ClInclude Include="src\PhysicsSocketConstraint.h" />
     <ClInclude Include="src\PhysicsSpringConstraint.h" />
+    <ClInclude Include="src\PhysicsVehicle.h" />
+    <ClInclude Include="src\PhysicsVehicleWheel.h" />
     <ClInclude Include="src\Plane.h" />
     <ClInclude Include="src\Platform.h" />
     <ClInclude Include="src\Properties.h" />
@@ -557,8 +603,6 @@
     <None Include="src\BoundingBox.inl" />
     <None Include="src\BoundingSphere.inl" />
     <None Include="src\Game.inl" />
-    <None Include="src\gameplay-main-ios.mm" />
-    <None Include="src\gameplay-main-macosx.mm" />
     <None Include="src\Image.inl" />
     <None Include="src\MathUtil.inl" />
     <None Include="src\MathUtilNeon.inl" />
@@ -566,8 +610,6 @@
     <None Include="src\Matrix.inl" />
     <None Include="src\MeshBatch.inl" />
     <None Include="src\Plane.inl" />
-    <None Include="src\PlatformiOS.mm" />
-    <None Include="src\PlatformMacOSX.mm" />
     <None Include="src\Quaternion.inl" />
     <None Include="src\Ray.inl" />
     <None Include="src\ScriptController.inl" />
@@ -593,48 +635,140 @@
     <UseDebugLibraries>true</UseDebugLibraries>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerry'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerrySimulator'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerry'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerrySimulator'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerry'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerrySimulator'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   </ImportGroup>
   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerry'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerrySimulator'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
   <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|Win32'" Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerry'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerrySimulator'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerry'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerrySimulator'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <OutDir>$(Configuration)\</OutDir>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerry'">
+    <OutDir>Device-$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerrySimulator'">
+    <OutDir>Simulator\</OutDir>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|Win32'">
     <OutDir>$(Configuration)\</OutDir>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerry'">
+    <OutDir>Device-$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerrySimulator'">
+    <OutDir>Simulator\</OutDir>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <IntDir>$(Configuration)\</IntDir>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerry'">
+    <IntDir>Device-$(Configuration)\</IntDir>
+    <TargetName>lib$(ProjectName)</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerrySimulator'">
+    <IntDir>Simulator\</IntDir>
+    <TargetName>lib$(ProjectName)</TargetName>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|Win32'">
     <IntDir>$(Configuration)\</IntDir>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerry'">
+    <IntDir>Device-$(Configuration)\</IntDir>
+    <TargetName>lib$(ProjectName)</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerrySimulator'">
+    <IntDir>Simulator\</IntDir>
+    <TargetName>lib$(ProjectName)</TargetName>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <OutDir>$(Configuration)\</OutDir>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerry'">
+    <OutDir>Device-$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerrySimulator'">
+    <OutDir>Simulator\</OutDir>
+  </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <IntDir>$(Configuration)\</IntDir>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerry'">
+    <IntDir>Device-$(Configuration)\</IntDir>
+    <TargetName>lib$(ProjectName)</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerrySimulator'">
+    <IntDir>Simulator\</IntDir>
+    <TargetName>lib$(ProjectName)</TargetName>
+  </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <PrecompiledHeader>
@@ -652,6 +786,41 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerry'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <RuntimeTypeInfo>
+      </RuntimeTypeInfo>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <AdditionalOptions>-mfpu=neon %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|BlackBerrySimulator'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <RuntimeTypeInfo>
+      </RuntimeTypeInfo>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|Win32'">
     <ClCompile>
       <PrecompiledHeader>
@@ -672,6 +841,47 @@
       </Verbose>
     </Lib>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerry'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <AdditionalOptions>-mfpu=neon %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <Lib>
+      <Verbose>
+      </Verbose>
+    </Lib>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|BlackBerrySimulator'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <Lib>
+      <Verbose>
+      </Verbose>
+    </Lib>
+  </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
       <WarningLevel>Level3</WarningLevel>
@@ -690,6 +900,43 @@
       <OptimizeReferences>true</OptimizeReferences>
     </Link>
   </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerry'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalOptions>-mfpu=neon %(AdditionalOptions)</AdditionalOptions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|BlackBerrySimulator'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>

+ 74 - 20
gameplay/gameplay.vcxproj.filters

@@ -81,10 +81,16 @@
     <ClCompile Include="src\Plane.cpp">
       <Filter>src</Filter>
     </ClCompile>
-    <ClCompile Include="src\PlatformQNX.cpp">
+    <ClCompile Include="src\gameplay-main-blackberry.cpp">
       <Filter>src</Filter>
     </ClCompile>
-    <ClCompile Include="src\PlatformWin32.cpp">
+    <ClCompile Include="src\PlatformBlackBerry.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\gameplay-main-windows.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PlatformWindows.cpp">
       <Filter>src</Filter>
     </ClCompile>
     <ClCompile Include="src\Quaternion.cpp">
@@ -165,12 +171,6 @@
     <ClCompile Include="src\RenderState.cpp">
       <Filter>src</Filter>
     </ClCompile>
-    <ClCompile Include="src\gameplay-main-qnx.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\gameplay-main-win32.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
     <ClCompile Include="src\DebugNew.cpp">
       <Filter>src</Filter>
     </ClCompile>
@@ -783,6 +783,42 @@
     <ClCompile Include="src\lua\lua_ScriptTarget.cpp">
       <Filter>lua</Filter>
     </ClCompile>
+    <ClCompile Include="src\gameplay-main-linux.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PlatformLinux.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\lua\lua_Gesture.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
+    <ClCompile Include="src\lua\lua_GestureGestureEvent.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsVehicle.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsVehicleWheel.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\lua\lua_PhysicsVehicle.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
+    <ClCompile Include="src\lua\lua_PhysicsVehicleWheel.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
+    <ClCompile Include="src\MathUtil.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Logger.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\lua\lua_LoggerLevel.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
+    <ClCompile Include="src\lua\lua_Logger.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -1556,14 +1592,38 @@
     <ClInclude Include="src\lua\lua_ScriptTarget.h">
       <Filter>lua</Filter>
     </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="src\gameplay-main-macosx.mm">
+    <ClInclude Include="src\Gesture.h">
       <Filter>src</Filter>
-    </None>
-    <None Include="src\PlatformMacOSX.mm">
+    </ClInclude>
+    <ClInclude Include="src\lua\lua_Gesture.h">
+      <Filter>lua</Filter>
+    </ClInclude>
+    <ClInclude Include="src\lua\lua_GestureGestureEvent.h">
+      <Filter>lua</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsVehicleWheel.h">
       <Filter>src</Filter>
-    </None>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsVehicle.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\lua\lua_PhysicsVehicle.h">
+      <Filter>lua</Filter>
+    </ClInclude>
+    <ClInclude Include="src\lua\lua_PhysicsVehicleWheel.h">
+      <Filter>lua</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Logger.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\lua\lua_Logger.h">
+      <Filter>lua</Filter>
+    </ClInclude>
+    <ClInclude Include="src\lua\lua_LoggerLevel.h">
+      <Filter>lua</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
     <None Include="src\Game.inl">
       <Filter>src</Filter>
     </None>
@@ -1573,12 +1633,6 @@
     <None Include="src\MeshBatch.inl">
       <Filter>src</Filter>
     </None>
-    <None Include="src\gameplay-main-ios.mm">
-      <Filter>src</Filter>
-    </None>
-    <None Include="src\PlatformiOS.mm">
-      <Filter>src</Filter>
-    </None>
     <None Include="res\logo_black.png">
       <Filter>res</Filter>
     </None>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 996 - 3
gameplay/gameplay.xcodeproj/project.pbxproj


+ 58 - 0
gameplay/gameplay.xcodeproj/xcshareddata/xcschemes/gameplay-ios.xcscheme

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "5B04C52B14BFCFE100EB0071"
+               BuildableName = "libgameplay.a"
+               BlueprintName = "gameplay-ios"
+               ReferencedContainer = "container:gameplay.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 58 - 0
gameplay/gameplay.xcodeproj/xcshareddata/xcschemes/gameplay-macosx.xcscheme

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "4234D99914686C52003031B3"
+               BuildableName = "libgameplay.a"
+               BlueprintName = "gameplay-macosx"
+               ReferencedContainer = "container:gameplay.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 4 - 1
gameplay/res/shaders/colored-unlit.frag

@@ -6,6 +6,9 @@ precision highp float;
 #if defined(VERTEX_COLOR)
 varying vec3 v_color;						// Input Vertex color ( r g b )
 #endif
+#if defined(TEXTURE_LIGHTMAP)
+varying vec2 v_texCoord;
+#endif
 
 // Uniforms
 uniform vec4 u_diffuseColor;               	// Diffuse color
@@ -30,7 +33,7 @@ void main()
     #endif
 	#if defined(TEXTURE_LIGHTMAP)
 	vec4 lightColor = texture2D(u_lightmapTexture, v_texCoord);
-	gl_FragColor.a *= lightColor.a;
+	gl_FragColor.rgb *= lightColor.rgb;
 	#endif
 	// Global color modulation
 	#if defined(MODULATE_COLOR)

+ 16 - 2
gameplay/res/shaders/colored-unlit.vert

@@ -1,14 +1,23 @@
 // Inputs
 attribute vec4 a_position;									// Vertex Position							(x, y, z, w)
+#if defined(TEXTURE_LIGHTMAP)
+attribute vec2 a_texCoord;                                  // Texture Coordinate (for lightmapping)
+#endif
 #if defined(SKINNING)
 attribute vec4 a_blendWeights;								// Vertex blend weight, up to 4				(0, 1, 2, 3) 
 attribute vec4 a_blendIndices;								// Vertex blend index int u_matrixPalette	(0, 1, 2, 3)
 #endif
 #if defined(VERTEX_COLOR)
 attribute vec3 a_color;										// Vertex Color								(r, g, b)
-varying vec3 v_color;										// Output Vertex color						(r, g, b)
 #endif
 
+// Outputs
+#if defined(TEXTURE_LIGHTMAP)
+varying vec2 v_texCoord;                                    // Output Texture Coordinate
+#endif
+#if defined(VERTEX_COLOR)
+varying vec3 v_color;										// Output Vertex color						(r, g, b)
+#endif
 
 // Uniforms
 uniform mat4 u_worldViewProjectionMatrix;					// Matrix to transform a position to clip space.
@@ -32,8 +41,13 @@ void main()
     // Transform position to clip space.a
     gl_Position = u_worldViewProjectionMatrix *  position;
     
+    // Pass lightmap tex coord to fragment shader
+    #if defined(TEXTURE_LIGHTMAP)
+    v_texCoord0 = a_texCoord0;
+    #endif
+
      // Pass on vertex color to fragment shader
     #if defined(VERTEX_COLOR)
 	v_color = a_color;
     #endif
-}
+}

+ 11 - 4
gameplay/res/shaders/textured-unlit.frag

@@ -15,16 +15,23 @@ uniform float u_modulateAlpha;              // Modulation alpha
 #endif
 
 // Inputs
-varying vec2 v_texCoord;                	// Texture coordinate(u, v)
+varying vec2 v_texCoord0;                	// Texture coordinate(u, v)
+#if defined(TEXCOORD1)
+varying vec2 v_texCoord1;                   // Second tex coord for multi-texturing
+#endif
 
 // Fragment Program
 void main()
 {
     // Sample the texture for the color
-    gl_FragColor = texture2D(u_diffuseTexture, v_texCoord);
+    gl_FragColor = texture2D(u_diffuseTexture, v_texCoord0);
 	#if defined(TEXTURE_LIGHTMAP)
-	vec4 lightColor = texture2D(u_lightmapTexture, v_texCoord);
-	gl_FragColor.a *= lightColor.a;
+    #if defined(TEXCOORD1)
+    vec4 lightColor = texture2D(u_lightmapTexture, v_texCoord1);
+    #else
+    vec4 lightColor = texture2D(u_lightmapTexture, v_texCoord0);
+    #endif
+    gl_FragColor.rgb *= lightColor.rgb;
 	#endif
 	// Global color modulation
 	#if defined(MODULATE_COLOR)

+ 14 - 5
gameplay/res/shaders/textured-unlit.vert

@@ -1,6 +1,9 @@
 // Inputs
 attribute vec4 a_position;									// Vertex Position							(x, y, z, w)
-attribute vec2 a_texCoord;									// Vertex Texture Coordinate				(u, v)
+attribute vec2 a_texCoord0;									// Vertex Texture Coordinate				(u, v)
+#if defined(TEXCOORD1)
+attribute vec2 a_texCoord1;                                 // Second tex coord for multi-texturing
+#endif
 #if defined(SKINNING)
 attribute vec4 a_blendWeights;								// Vertex blend weight, up to 4				(0, 1, 2, 3) 
 attribute vec4 a_blendIndices;								// Vertex blend index int u_matrixPalette	(0, 1, 2, 3)
@@ -19,7 +22,10 @@ uniform vec2 u_textureOffset;								// Texture offset
 #endif
 
 // Outputs
-varying vec2 v_texCoord;									// Texture Coordinate
+varying vec2 v_texCoord0;									// Texture Coordinate
+#if defined(TEXCOORD1)
+varying vec2 v_texCoord1;                                   // Second tex coord for multi-texturing
+#endif
 
 // Vertex attribute accessors
 #if defined(SKINNING)
@@ -38,11 +44,14 @@ void main()
     gl_Position = u_worldViewProjectionMatrix * position;
 
     // Texture transformation.
-    v_texCoord = a_texCoord;
+    v_texCoord0 = a_texCoord0;
+    #if defined(TEXCOORD1)
+    v_texCoord1 = a_texCoord1;
+    #endif
     #if defined(TEXTURE_REPEAT)
-    v_texCoord *= u_textureRepeat;
+    v_texCoord0 *= u_textureRepeat;
     #endif
     #if defined(TEXTURE_OFFSET)
-    v_texCoord += u_textureOffset;
+    v_texCoord0 += u_textureOffset;
     #endif
 }

+ 24 - 23
gameplay/src/Animation.cpp

@@ -15,17 +15,18 @@
 namespace gameplay
 {
 
-Animation::Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, unsigned int type)
-    : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0), _defaultClip(NULL), _clips(NULL)
+Animation::Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, unsigned int type)
+    : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0L), _defaultClip(NULL), _clips(NULL)
 {
-    createChannel(target, propertyId, keyCount, keyTimes, keyValues, type);
+    createChannel(target, propertyId, keyCount, keyTimes, keyValues, type);
+
     // Release the animation because a newly created animation has a ref count of 1 and the channels hold the ref to animation.
     release();
     GP_ASSERT(getRefCount() == 1);
 }
 
-Animation::Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type)
-    : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0), _defaultClip(NULL), _clips(NULL)
+Animation::Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type)
+    : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0L), _defaultClip(NULL), _clips(NULL)
 {
     createChannel(target, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
     // Release the animation because a newly created animation has a ref count of 1 and the channels hold the ref to animation.
@@ -34,7 +35,7 @@ Animation::Animation(const char* id, AnimationTarget* target, int propertyId, un
 }
 
 Animation::Animation(const char* id)
-    : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0), _defaultClip(NULL), _clips(NULL)
+    : _controller(Game::getInstance()->getAnimationController()), _id(id), _duration(0L), _defaultClip(NULL), _clips(NULL)
 {
 }
 
@@ -55,9 +56,9 @@ Animation::~Animation()
     if (_clips)
     {
         std::vector<AnimationClip*>::iterator clipIter = _clips->begin();
-    
+
         while (clipIter != _clips->end())
-        {   
+        {
             AnimationClip* clip = *clipIter;
             GP_ASSERT(clip);
             if (clip->isClipStateBitSet(AnimationClip::CLIP_IS_PLAYING_BIT))
@@ -127,7 +128,7 @@ void Animation::createClips(const char* url)
 
     Properties* pAnimation = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace();
     GP_ASSERT(pAnimation);
-    
+
     int frameCount = pAnimation->getInt("frameCount");
     if (frameCount <= 0)
         GP_ERROR("The animation's frame count must be greater than 0.");
@@ -180,7 +181,7 @@ void Animation::play(const char* clipId)
     {
         if (_defaultClip == NULL)
             createDefaultClip();
-        
+
         _defaultClip->play();
     }
     else
@@ -245,9 +246,9 @@ void Animation::createDefaultClip()
 void Animation::createClips(Properties* animationProperties, unsigned int frameCount)
 {
     GP_ASSERT(animationProperties);
-    
+
     Properties* pClip = animationProperties->getNextNamespace();
-    
+
     while (pClip != NULL && std::strcmp(pClip->getNamespace(), "clip") == 0)
     {
         int begin = pClip->getInt("begin");
@@ -296,8 +297,8 @@ AnimationClip* Animation::findClip(const char* id) const
     if (_clips)
     {
         AnimationClip* clip = NULL;
-        unsigned int clipCount = _clips->size();
-        for (unsigned int i = 0; i < clipCount; i++)
+        size_t clipCount = _clips->size();
+        for (size_t i = 0; i < clipCount; i++)
         {
             clip = _clips->at(i);
             GP_ASSERT(clip);
@@ -310,7 +311,7 @@ AnimationClip* Animation::findClip(const char* id) const
     return NULL;
 }
 
-Animation::Channel* Animation::createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, unsigned int type)
+Animation::Channel* Animation::createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, unsigned int type)
 {
     GP_ASSERT(target);
     GP_ASSERT(keyTimes);
@@ -324,7 +325,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     if (target->_targetType == AnimationTarget::TRANSFORM)
         setTransformRotationOffset(curve, propertyId);
 
-    unsigned long lowest = keyTimes[0];
+    unsigned int lowest = keyTimes[0];
     unsigned long duration = keyTimes[keyCount-1] - lowest;
 
     float* normalizedKeyTimes = new float[keyCount];
@@ -344,7 +345,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     normalizedKeyTimes[i] = 1.0f;
     curve->setPoint(i, normalizedKeyTimes[i], keyValues + pointOffset, (Curve::InterpolationType) type);
 
-    SAFE_DELETE(normalizedKeyTimes);
+    SAFE_DELETE_ARRAY(normalizedKeyTimes);
 
     Channel* channel = new Channel(this, target, propertyId, curve, duration);
     curve->release();
@@ -352,7 +353,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     return channel;
 }
 
-Animation::Channel* Animation::createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type)
+Animation::Channel* Animation::createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type)
 {
     GP_ASSERT(target);
     GP_ASSERT(keyTimes);
@@ -365,12 +366,12 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     GP_ASSERT(curve);
     if (target->_targetType == AnimationTarget::TRANSFORM)
         setTransformRotationOffset(curve, propertyId);
-    
+
     unsigned long lowest = keyTimes[0];
     unsigned long duration = keyTimes[keyCount-1] - lowest;
 
     float* normalizedKeyTimes = new float[keyCount];
-    
+
     normalizedKeyTimes[0] = 0.0f;
     curve->setPoint(0, normalizedKeyTimes[0], keyValues, (Curve::InterpolationType) type, keyInValue, keyOutValue);
 
@@ -386,7 +387,7 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
     normalizedKeyTimes[i] = 1.0f;
     curve->setPoint(i, normalizedKeyTimes[i], keyValues + pointOffset, (Curve::InterpolationType) type, keyInValue + pointOffset, keyOutValue + pointOffset);
 
-    SAFE_DELETE(normalizedKeyTimes);
+    SAFE_DELETE_ARRAY(normalizedKeyTimes);
 
     Channel* channel = new Channel(this, target, propertyId, curve, duration);
     curve->release();
@@ -398,7 +399,7 @@ void Animation::addChannel(Channel* channel)
 {
     GP_ASSERT(channel);
     _channels.push_back(channel);
-    
+
     if (channel->_duration > _duration)
         _duration = channel->_duration;
 }
@@ -409,7 +410,7 @@ void Animation::removeChannel(Channel* channel)
     while (itr != _channels.end())
     {
         Animation::Channel* chan = *itr;
-        if (channel == chan) 
+        if (channel == chan)
         {
             _channels.erase(itr);
             return;

+ 30 - 29
gameplay/src/Animation.h

@@ -27,14 +27,14 @@ class Animation : public Ref
     friend class Bundle;
 
 public:
-    
+
     /**
      * Gets the Animation's ID.
-     * 
+     *
      * @return The Animation's ID.
      */
     const char* getId() const;
-    
+
     /**
      * Gets the Animation's duration.
      *
@@ -43,28 +43,29 @@ public:
     unsigned long getDuration() const;
 
     /**
-     * Creates an AnimationClip from the Properties object defined at the specified URL, 
+     * Creates an AnimationClip from the Properties object defined at the specified URL,
      * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
      * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional).
-     * 
+     *
      * @param url The URL pointing to the Properties object containing the clip definitions.
      */
     void createClips(const char* url);
-    
+
     /**
      * Creates an AnimationClip from the Animation.
-     * 
+     *
      * @param id The ID to the give the AnimationClip.
      * @param start The time (in milliseconds) that the AnimationClip will begin from.
      * @param end The time (in milliseconds) that the AnimationClip will end.
-     * 
+     *
      * @return The newly created AnimationClip; NULL if an AnimationClip already exists with the same ID.
+     * @script{create}
      */
     AnimationClip* createClip(const char* id, unsigned long start, unsigned long end);
-    
+
     /**
      * Finds the AnimationClip with the specified name. If NULL, gets the default clip.
-     * 
+     *
      * @param clipId The ID of the AnimationClip to get.
      *
      * @return The AnimationClip with the specified ID; NULL if an AnimationClip with the given ID is not found.
@@ -82,22 +83,22 @@ public:
      * Returns the number of animation clips in this animation.
      */
     unsigned int getClipCount() const;
-    
+
     /**
-     * Plays the AnimationClip with the specified name. 
+     * Plays the AnimationClip with the specified name.
      *
      * @param clipId The ID of the AnimationClip to play. If NULL, plays the default clip.
-     */ 
+     */
     void play(const char* clipId = NULL);
 
     /**
-     * Stops the AnimationClip with the specified name. 
-     * 
+     * Stops the AnimationClip with the specified name.
+     *
      * @param clipId The ID of the AnimationClip to stop. If NULL, stops the default clip.
      */
     void stop(const char* clipId = NULL);
 
-    /** 
+    /**
      * Pauses the AnimationClip with the specified name.
      *
      * @param clipId The ID of the AnimationClip to pause. If NULL, pauses the default clip.
@@ -108,7 +109,7 @@ public:
      * Returns true if this animation targets the given AnimationTarget.
      */
     bool targets(AnimationTarget* target) const;
-    
+
 private:
 
     /**
@@ -147,12 +148,12 @@ private:
     /**
      * Constructor.
      */
-    Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type);
-    
+    Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type);
+
     /**
      * Constructor.
      */
-    Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, unsigned int type);
+    Animation(const char* id, AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, unsigned int type);
 
     /**
      * Constructor.
@@ -163,12 +164,12 @@ private:
      * Destructor.
      */
     ~Animation();
-    
+
     /**
      * Hidden copy assignment operator.
      */
     Animation& operator=(const Animation&);
-    
+
     /**
      * Creates the default clip.
      */
@@ -191,13 +192,13 @@ private:
 
     /**
      * Creates a channel within this animation.
-     */ 
-    Channel* createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, unsigned int type);
+     */
+    Channel* createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, unsigned int type);
 
     /**
      * Creates a channel within this animation.
      */
-    Channel* createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type);
+    Channel* createChannel(AnimationTarget* target, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, unsigned int type);
 
     /**
      * Adds a channel to the animation.
@@ -216,17 +217,17 @@ private:
 
     /**
      * Clones this animation.
-     * 
+     *
      * @param channel The channel to clone and add to the animation.
      * @param target The target of the animation.
-     * 
+     *
      * @return The newly created animation.
      */
     Animation* clone(Channel* channel, AnimationTarget* target);
-    
+
     AnimationController* _controller;       // The AnimationController that this Animation will run on.
     std::string _id;                        // The Animation's ID.
-    unsigned long _duration;                // the length of the animation (in milliseconds).
+    unsigned long _duration;              // the length of the animation (in milliseconds).
     std::vector<Channel*> _channels;        // The channels within this Animation.
     AnimationClip* _defaultClip;            // The Animation's default clip.
     std::vector<AnimationClip*>* _clips;    // All the clips created from this Animation.

+ 5 - 5
gameplay/src/AnimationClip.cpp

@@ -43,7 +43,7 @@ AnimationClip::~AnimationClip()
 
     if (_scriptListeners)
     {
-        for (unsigned int i = 0; i < _scriptListeners->size(); i++)
+        for (size_t i = 0; i < _scriptListeners->size(); i++)
         {
             SAFE_DELETE((*_scriptListeners)[i]);
         }
@@ -169,7 +169,7 @@ float AnimationClip::getBlendWeight() const
 
 bool AnimationClip::isPlaying() const
 {
-    return isClipStateBitSet(CLIP_IS_PLAYING_BIT);
+    return (isClipStateBitSet(CLIP_IS_PLAYING_BIT) && !isClipStateBitSet(CLIP_IS_PAUSED_BIT));
 }
 
 void AnimationClip::play()
@@ -498,8 +498,8 @@ bool AnimationClip::update(float elapsedTime)
     Animation::Channel* channel = NULL;
     AnimationValue* value = NULL;
     AnimationTarget* target = NULL;
-    unsigned int channelCount = _animation->_channels.size();
-    for (unsigned int i = 0; i < channelCount; i++)
+    size_t channelCount = _animation->_channels.size();
+    for (size_t i = 0; i < channelCount; i++)
     {
         channel = _animation->_channels[i];
         GP_ASSERT(channel);
@@ -627,4 +627,4 @@ void AnimationClip::ScriptListener::animationEvent(AnimationClip* clip, EventTyp
 }
 
 
-}
+}

+ 1 - 1
gameplay/src/AnimationController.cpp

@@ -97,7 +97,7 @@ void AnimationController::update(float elapsedTime)
 {
     if (_state != RUNNING)
         return;
-
+    
     Transform::suspendTransformChanged();
 
     // Loop through running clips and call update() on them.

+ 35 - 35
gameplay/src/AnimationTarget.cpp

@@ -31,7 +31,7 @@ AnimationTarget::~AnimationTarget()
     }
 }
 
-Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, Curve::InterpolationType type)
+Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, Curve::InterpolationType type)
 {
     GP_ASSERT(type != Curve::BEZIER && type != Curve::HERMITE);
     GP_ASSERT(keyCount >= 1 && keyTimes && keyValues);
@@ -41,7 +41,7 @@ Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsi
     return animation;
 }
 
-Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type)
+Animation* AnimationTarget::createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type)
 {
     GP_ASSERT(keyCount >= 1 && keyTimes && keyValues && keyInValue && keyOutValue);
     Animation* animation = new Animation(id, this, propertyId, keyCount, keyTimes, keyValues, keyInValue, keyOutValue, type);
@@ -73,9 +73,9 @@ Animation* AnimationTarget::createAnimationFromTo(const char* id, int propertyId
     memcpy(keyValues, from, sizeof(float) * propertyComponentCount);
     memcpy(keyValues + propertyComponentCount, to, sizeof(float) * propertyComponentCount);
 
-    unsigned long* keyTimes = new unsigned long[2];
+    unsigned int* keyTimes = new unsigned int[2];
     keyTimes[0] = 0;
-    keyTimes[1] = duration;
+    keyTimes[1] = (unsigned int)duration;
 
     Animation* animation = createAnimation(id, propertyId, 2, keyTimes, keyValues, type);
 
@@ -99,9 +99,9 @@ Animation* AnimationTarget::createAnimationFromBy(const char* id, int propertyId
     convertByValues(propertyId, propertyComponentCount, from, by);
     memcpy(keyValues + propertyComponentCount, by, sizeof(float) * propertyComponentCount);
 
-    unsigned long* keyTimes = new unsigned long[2];
+    unsigned int* keyTimes = new unsigned int[2];
     keyTimes[0] = 0;
-    keyTimes[1] = duration;
+    keyTimes[1] = (unsigned int)duration;
 
     Animation* animation = createAnimation(id, propertyId, 2, keyTimes, keyValues, type);
 
@@ -119,14 +119,14 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
         GP_ERROR("Invalid animation namespace '%s'.", animationProperties->getNamespace());
         return NULL;
     }
-    
+
     const char* propertyIdStr = animationProperties->getString("property");
     if (propertyIdStr == NULL)
     {
         GP_ERROR("Attribute 'property' must be specified for an animation.");
         return NULL;
     }
-    
+
     // Get animation target property id
     int propertyId = AnimationTarget::getPropertyId(_targetType, propertyIdStr);
     if (propertyId == -1)
@@ -134,7 +134,7 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
         GP_ERROR("Property ID is invalid.");
         return NULL;
     }
-    
+
     unsigned int keyCount = animationProperties->getInt("keyCount");
     if (keyCount == 0)
     {
@@ -148,27 +148,27 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
         GP_ERROR("Attribute 'keyTimes' must be specified for an animation.");
         return NULL;
     }
-    
+
     const char* keyValuesStr = animationProperties->getString("keyValues");
     if (keyValuesStr == NULL)
     {
         GP_ERROR("Attribute 'keyValues' must be specified for an animation.");
         return NULL;
     }
-    
+
     const char* curveStr = animationProperties->getString("curve");
     if (curveStr == NULL)
     {
         GP_ERROR("Attribute 'curve' must be specified for an animation.");
         return NULL;
     }
-    
+
     char delimeter = ' ';
-    unsigned int startOffset = 0;
-    unsigned int endOffset = (unsigned int)std::string::npos;
-    
-    unsigned long* keyTimes = new unsigned long[keyCount];
-    for (unsigned int i = 0; i < keyCount; i++)
+    size_t startOffset = 0;
+    size_t endOffset = std::string::npos;
+
+    unsigned int* keyTimes = new unsigned int[keyCount];
+    for (size_t i = 0; i < keyCount; i++)
     {
         endOffset = static_cast<std::string>(keyTimesStr).find_first_of(delimeter, startOffset);
         if (endOffset != std::string::npos)
@@ -183,19 +183,19 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
     }
 
     startOffset = 0;
-    endOffset = (unsigned int)std::string::npos;
-    
+    endOffset = std::string::npos;
+
     int componentCount = getAnimationPropertyComponentCount(propertyId);
     GP_ASSERT(componentCount > 0);
-    
+
     unsigned int components = keyCount * componentCount;
-    
+
     float* keyValues = new float[components];
     for (unsigned int i = 0; i < components; i++)
     {
         endOffset = static_cast<std::string>(keyValuesStr).find_first_of(delimeter, startOffset);
         if (endOffset != std::string::npos)
-        {   
+        {
             keyValues[i] = std::atof(static_cast<std::string>(keyValuesStr).substr(startOffset, endOffset - startOffset).c_str());
         }
         else
@@ -211,12 +211,12 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
     {
         keyIn = new float[components];
         startOffset = 0;
-        endOffset = (unsigned int)std::string::npos;
+        endOffset = std::string::npos;
         for (unsigned int i = 0; i < components; i++)
         {
             endOffset = static_cast<std::string>(keyInStr).find_first_of(delimeter, startOffset);
             if (endOffset != std::string::npos)
-            {   
+            {
                 keyIn[i] = std::atof(static_cast<std::string>(keyInStr).substr(startOffset, endOffset - startOffset).c_str());
             }
             else
@@ -226,19 +226,19 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
             startOffset = endOffset + 1;
         }
     }
-    
+
     const char* keyOutStr = animationProperties->getString("keyOut");
     float* keyOut = NULL;
     if (keyOutStr)
-    {   
+    {
         keyOut = new float[components];
         startOffset = 0;
-        endOffset = (unsigned int)std::string::npos;
+        endOffset = std::string::npos;
         for (unsigned int i = 0; i < components; i++)
         {
             endOffset = static_cast<std::string>(keyOutStr).find_first_of(delimeter, startOffset);
             if (endOffset != std::string::npos)
-            {   
+            {
                 keyOut[i] = std::atof(static_cast<std::string>(keyOutStr).substr(startOffset, endOffset - startOffset).c_str());
             }
             else
@@ -261,10 +261,10 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
         animation = createAnimation(id, propertyId, keyCount, keyTimes, keyValues, (Curve::InterpolationType) curve);
     }
 
-    SAFE_DELETE(keyOut);
-    SAFE_DELETE(keyIn);
-    SAFE_DELETE(keyValues);
-    SAFE_DELETE(keyTimes);
+    SAFE_DELETE_ARRAY(keyOut);
+    SAFE_DELETE_ARRAY(keyIn);
+    SAFE_DELETE_ARRAY(keyValues);
+    SAFE_DELETE_ARRAY(keyTimes);
 
     Properties* pClip = animationProperties->getNextNamespace();
     if (pClip && std::strcmp(pClip->getNamespace(), "clip") == 0)
@@ -325,7 +325,7 @@ Animation* AnimationTarget::getAnimation(const char* id) const
 int AnimationTarget::getPropertyId(TargetType type, const char* propertyIdStr)
 {
     GP_ASSERT(propertyIdStr);
-    
+
     if (type == AnimationTarget::TRANSFORM)
     {
         if (strcmp(propertyIdStr, "ANIMATE_SCALE") == 0)
@@ -467,7 +467,7 @@ void AnimationTarget::cloneInto(AnimationTarget* target, NodeCloneContext &conte
 void AnimationTarget::convertByValues(unsigned int propertyId, unsigned int componentCount, float* from, float* by)
 {
     if (_targetType == AnimationTarget::TRANSFORM)
-    {    
+    {
         switch(propertyId)
         {
             case Transform::ANIMATE_SCALE:
@@ -497,7 +497,7 @@ void AnimationTarget::convertByValues(unsigned int propertyId, unsigned int comp
                 convertQuaternionByValues(from, by);
                 convertByValues(from + 4, by + 4, 3);
                 break;
-            }   
+            }
             case Transform::ANIMATE_SCALE_ROTATE_TRANSLATE:
             {
                 convertScaleByValues(from, by, 3);

+ 23 - 23
gameplay/src/AnimationTarget.h

@@ -23,9 +23,9 @@ class AnimationTarget
 public:
 
     /**
-     * Creates an animation on this target from a set of key value and key time pairs. 
+     * Creates an animation on this target from a set of key value and key time pairs.
      * Cannot use Curve::BEZIER or CURVE::HERMITE as the interpolation type since they require tangents/control points.
-     * 
+     *
      * @param id The ID of the animation.
      * @param propertyId The property on this target to animate.
      * @param keyCount The number of keyframes in the animation. Must be greater than one.
@@ -35,11 +35,11 @@ public:
      *
      * @return The newly created animation.
      */
-    Animation* createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, Curve::InterpolationType type);
+    Animation* createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, Curve::InterpolationType type);
 
     /**
      * Creates an animation on this target from a set of key value and key time pairs.
-     * 
+     *
      * @param id The ID of the animation.
      * @param propertyId The property on this target to animate.
      * @param keyCount The number of keyframes in the animation. Must be greater than one.
@@ -51,13 +51,13 @@ public:
      *
      * @return The newly created animation.
      */
-    Animation* createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned long* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type);
+    Animation* createAnimation(const char* id, int propertyId, unsigned int keyCount, unsigned int* keyTimes, float* keyValues, float* keyInValue, float* keyOutValue, Curve::InterpolationType type);
 
     /**
-     * Creates an animation on this target using the data from the Properties object defined at the specified URL, 
+     * Creates an animation on this target using the data from the Properties object defined at the specified URL,
      * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
-     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
-     * 
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional).
+     *
      * @param id The ID of the animation.
      * @param url The URL pointing to the Properties object defining the animation data.
      *
@@ -66,8 +66,8 @@ public:
     Animation* createAnimation(const char* id, const char* url);
 
     /**
-     * Creates an animation on this target using the data from the given properties object. 
-     * 
+     * Creates an animation on this target using the data from the given properties object.
+     *
      * @param id The ID of the animation.
      * @param animationProperties The properties object defining the animation data.
      *
@@ -109,14 +109,14 @@ public:
      * Destroys the animation with the specified ID. Destroys the first animation if ID is NULL.
      *
      * @param id The ID of the animation to destroy.
-     */ 
+     */
     void destroyAnimation(const char* id = NULL);
 
     /**
      * Abstract method to return the property component count of the given property ID on the AnimationTarget.
-     * 
+     *
      * @param propertyId The ID of the property on the AnimationTarget to obtain the component count for.
-     * 
+     *
      * @return The property component count of the given property.
      */
     virtual unsigned int getAnimationPropertyComponentCount(int propertyId) const = 0;
@@ -131,14 +131,14 @@ public:
 
     /**
      * Abstract method for setting the animation property value for the given property ID on the AnimationTarget.
-     * 
+     *
      * @param propertyId The ID of the property on the AnimationTarget to set the animation property value on.
      * @param value The container to set the animation property value in.
      * @param blendWeight The blend weight.
      */
     virtual void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f) = 0;
 
-    /** 
+    /**
      * Gets the animation with the specified ID. If the ID is NULL, this function will return the first animation it finds.
      *
      * @param id The name of the animation to get.
@@ -146,9 +146,9 @@ public:
     Animation* getAnimation(const char* id = NULL) const;
 
 protected:
-    
+
     /**
-     * The type of animation target. 
+     * The type of animation target.
      */
     enum TargetType
     {
@@ -168,14 +168,14 @@ protected:
 
     /**
      * Adds the given animation channel to this animation target.
-     * 
+     *
      * @param channel The animation channel to add.
      */
     void addChannel(Animation::Channel* channel);
 
     /**
      * Removes the given animation channel from this animation target.
-     * 
+     *
      * @param channel The animation channel to delete.
      */
     void removeChannel(Animation::Channel* channel);
@@ -189,14 +189,14 @@ protected:
 
     /**
      * Copies data from this animation target into the given target for the purpose of cloning.
-     * 
+     *
      * @param target The target to copy into.
      * @param context The clone context.
      */
     void cloneInto(AnimationTarget* target, NodeCloneContext &context) const;
 
     /**
-     * The target's type. 
+     * The target's type.
      *
      * @see TargetType::SCALAR
      * @see TargetType::TRANSFORM
@@ -212,7 +212,7 @@ private:
 
     /**
      * Gets the TargetType's property ID value for the specified property ID string.
-     * 
+     *
      * @param type The TargetType of the AnimationTarget.
      * @param propertyIdStr The property ID string.
      * @return The property ID value for teh property ID string; -1 if the propertyIdStr does not exist
@@ -241,7 +241,7 @@ private:
     void convertByValues(float* from, float* by, unsigned int componentCount);
 
     std::vector<Animation::Channel*>* _animationChannels;   // Collection of all animation channels that target the AnimationTarget
-    
+
 };
 }
 

+ 6 - 6
gameplay/src/AnimationValue.cpp

@@ -56,18 +56,18 @@ void AnimationValue::setFloat(unsigned int index, float value)
     _value[index] = value;
 }
 
-void AnimationValue::getFloat(float* value, unsigned int offset, unsigned int length) const
+void AnimationValue::getFloats(unsigned int index, float* values, unsigned int count) const
 {
-    GP_ASSERT(_value && value && offset < _componentCount && (offset + length) <= _componentCount);
+    GP_ASSERT(_value && values && index < _componentCount && (index + count) <= _componentCount);
 
-    memcpy(value + offset, _value, length * sizeof(float));
+    memcpy(values, &_value[index], count * sizeof(float));
 }
 
-void AnimationValue::setFloat(float* value, unsigned int offset, unsigned int length)
+void AnimationValue::setFloats(unsigned int index, float* values, unsigned int count)
 {
-    GP_ASSERT(_value && value && offset < _componentCount && (offset + length) <= _componentCount);
+    GP_ASSERT(_value && values && index < _componentCount && (index + count) <= _componentCount);
 
-    memcpy(_value, value + offset, length * sizeof(float));
+    memcpy(&_value[index], values, count * sizeof(float));
 }
 
 }

+ 10 - 10
gameplay/src/AnimationValue.h

@@ -33,22 +33,22 @@ public:
     void setFloat(unsigned int index, float value);
 
     /**
-     * Gets the value of the AnimationValue in a float array.
+     * Copies one or more float values from this AnimationValue into the specified array.
      *
-     * @param value The array to populate with the AnimationValue's values.
-     * @param offset The offset into the value to start populating.
-     * @param length The number of values to copy into the array.
+     * @param index The index to start copying from.
+     * @param values Pointer to float array to copy values into.
+     * @param count Number of values to copy.
      */
-    void getFloat(float* value, unsigned int offset, unsigned int length) const;
+    void getFloats(unsigned int index, float* values, unsigned int count) const;
 
     /**
-     * Sets the value of the AnimationValue.
+     * Copies one or more float values into the AnimationValue.
      *
-     * @param value The array to populate the AnimationValue's values.
-     * @param offset The offset into the value array to start populating from.
-     * @param length The number of values to copy into the AnimationValue.
+     * @param index The index of the first component to set the value for.
+     * @param values Array of values to copy into the AnimationValue.
+     * @param count Number of values to in the array to copy in.
      */
-    void setFloat(float* value, unsigned int offset, unsigned int length);
+    void setFloats(unsigned int index, float* values, unsigned int count);
 
 private:
 

+ 8 - 6
gameplay/src/AudioBuffer.cpp

@@ -100,8 +100,10 @@ AudioBuffer* AudioBuffer::create(const char* path)
         GP_ERROR("Unsupported audio file: %s", path);
         goto cleanup;
     }
-    
-    fclose(file);
+
+    //NOTE: loadOgg actually sets this null, so it is expected
+    if (file)    
+        fclose(file);
 
     buffer = new AudioBuffer(path, alBuffer);
 
@@ -303,16 +305,16 @@ bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
     }
 }
     
-bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
+bool AudioBuffer::loadOgg(FILE*& file, ALuint buffer)
 {
     GP_ASSERT(file);
 
     OggVorbis_File ogg_file;
     vorbis_info* info;
     ALenum format;
-    int result;
+    long result;
     int section;
-    unsigned int size = 0;
+    long size = 0;
 
     rewind(file);
 
@@ -331,7 +333,7 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
         format = AL_FORMAT_STEREO16;
 
     // size = #samples * #channels * 2 (for 16 bit).
-    unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
+    long data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
     char* data = new char[data_size];
 
     while (size < data_size)

+ 1 - 1
gameplay/src/AudioBuffer.h

@@ -45,7 +45,7 @@ private:
     
     static bool loadWav(FILE* file, ALuint buffer);
     
-    static bool loadOgg(FILE* file, ALuint buffer);
+    static bool loadOgg(FILE*& file, ALuint buffer);
 
     std::string _filePath;
     ALuint _alBuffer;

+ 16 - 0
gameplay/src/AudioListener.cpp

@@ -41,6 +41,11 @@ void AudioListener::setPosition(const Vector3& position)
     _position = position;
 }
 
+void AudioListener::setPosition(float x, float y, float z)
+{
+    _position.set(x, y, z);
+}
+
 const Vector3& AudioListener::getVelocity() const 
 { 
     return _velocity; 
@@ -51,6 +56,11 @@ void AudioListener::setVelocity(const Vector3& velocity)
     _velocity = velocity;
 }
 
+void AudioListener::setVelocity(float x, float y, float z)
+{
+    _velocity.set(x, y, z);
+}
+
 const float* AudioListener::getOrientation() const
 {
     return (const float*)&_orientation[0];
@@ -77,6 +87,12 @@ void AudioListener::setOrientation(const Vector3& forward, const Vector3& up)
     _orientation[1].z = up.z;
 }
 
+void AudioListener::setOrientation(float forwardX, float forwardY, float forwardZ, float upX, float upY, float upZ)
+{
+    _orientation[0].set(forwardX, forwardY, forwardZ);
+    _orientation[1].set(upX, upY, upZ);
+}
+
 Camera* AudioListener::getCamera() const
 {
     return _camera;

+ 30 - 0
gameplay/src/AudioListener.h

@@ -40,6 +40,15 @@ public:
      */
     void setPosition(const Vector3& position);
 
+    /**
+     * Sets the position of the audio source.
+     * 
+     * @param x The x coordinate of the position.
+     * @param y The y coordinate of the position.
+     * @param z The z coordinate of the position.
+     */
+    void setPosition(float x, float y, float z);
+
     /**
      * Returns the gain of the audio listener.
      *
@@ -68,6 +77,15 @@ public:
      */
     void setVelocity(const Vector3& velocity);
 
+    /**
+     * Sets the velocity of the audio source
+     * 
+     * @param x The x coordinate of the velocity.
+     * @param y The y coordinate of the velocity.
+     * @param z The z coordinate of the velocity.
+     */
+    void setVelocity(float x, float y, float z);
+
     /**
      * Gets the float pointer to the orientation of the audio listener.
      * Orientation is represented as 6 floats. (forward.x, forward.y, forward.z, up.x, up.y, up.z).
@@ -99,6 +117,18 @@ public:
      */
     void setOrientation(const Vector3& forward, const Vector3& up);
 
+    /**
+     * Sets the orientation of the audio listener.
+     * 
+     * @param forwardX The x coordinate of the forward vector.
+     * @param forwardY The y coordinate of the forward vector.
+     * @param forwardZ The z coordinate of the forward vector.
+     * @param upX The x coordinate of the up vector.
+     * @param upY The y coordinate of the up vector.
+     * @param upZ The z coordinate of the up vector.
+     */
+    void setOrientation(float forwardX, float forwardY, float forwardZ, float upX, float upY, float upZ);
+
     /**
      * Gets the camera currently associated with the audio listener.
      *

+ 7 - 2
gameplay/src/AudioSource.cpp

@@ -10,7 +10,7 @@ namespace gameplay
 {
 
 AudioSource::AudioSource(AudioBuffer* buffer, ALuint source) 
-    : _alSource(source), _buffer(buffer), _looped(true), _gain(1.0f), _pitch(1.0f), _node(NULL)
+    : _alSource(source), _buffer(buffer), _looped(false), _gain(1.0f), _pitch(1.0f), _node(NULL)
 {
     GP_ASSERT(buffer);
     AL_CHECK( alSourcei(_alSource, AL_BUFFER, buffer->_alBuffer) );
@@ -34,7 +34,7 @@ AudioSource* AudioSource::create(const char* url)
 {
     // Load from a .audio file.
     std::string pathStr = url;
-    if (pathStr.find(".audio") != pathStr.npos)
+    if (pathStr.find(".audio") != std::string::npos)
     {
         Properties* properties = Properties::create(url);
         if (properties == NULL)
@@ -233,6 +233,11 @@ void AudioSource::setVelocity(const Vector3& velocity)
     _velocity = velocity;
 }
 
+void AudioSource::setVelocity(float x, float y, float z)
+{
+    setVelocity(Vector3(x, y, z));
+}
+
 Node* AudioSource::getNode() const
 {
     return _node;

+ 9 - 0
gameplay/src/AudioSource.h

@@ -141,6 +141,15 @@ public:
      */
     void setVelocity(const Vector3& velocity);
 
+    /**
+     * Sets the velocity of the audio source.
+     *
+     * @param x The x coordinate of the velocity.
+     * @param y The y coordinate of the velocity.
+     * @param z The z coordinate of the velocity.
+     */
+    void setVelocity(float x, float y, float z);
+
     /**
      * Gets the node that this source is attached to.
      * 

+ 27 - 11
gameplay/src/Base.h

@@ -15,6 +15,7 @@
 #include <ctime>
 #include <iostream>
 #include <string>
+#include <cstring>
 #include <vector>
 #include <list>
 #include <set>
@@ -23,6 +24,8 @@
 #include <algorithm>
 #include <limits>
 #include <functional>
+#include <bitset>
+#include "Logger.h"
 
 // Bring common functions from C into global namespace
 using std::memcpy;
@@ -40,7 +43,6 @@ using std::min;
 using std::max;
 using std::modf;
 
-
 // Common
 #ifndef NULL
 #define NULL     0
@@ -48,8 +50,11 @@ using std::modf;
 
 namespace gameplay
 {
-/** Print logging (implemented per platform). */
-extern void printError(const char* format, ...);
+/**
+ * Print logging (implemented per platform).
+ * @script{ignore}
+ */
+extern void print(const char* format, ...);
 }
 
 // Current function macro.
@@ -72,9 +77,9 @@ extern void printError(const char* format, ...);
 #else
 #define GP_ERROR(...) do \
     { \
-        printError("%s -- ", __current__func__); \
-        printError(__VA_ARGS__); \
-        printError("\n"); \
+        gameplay::Logger::log(gameplay::Logger::LEVEL_ERROR, "%s -- ", __current__func__); \
+        gameplay::Logger::log(gameplay::Logger::LEVEL_ERROR, __VA_ARGS__); \
+        gameplay::Logger::log(gameplay::Logger::LEVEL_ERROR, "\n"); \
         assert(0); \
         std::exit(-1); \
     } while (0)
@@ -83,9 +88,9 @@ extern void printError(const char* format, ...);
 // Warning macro.
 #define GP_WARN(...) do \
     { \
-        printError("%s -- ", __current__func__); \
-        printError(__VA_ARGS__); \
-        printError("\n"); \
+        gameplay::Logger::log(gameplay::Logger::LEVEL_WARN, "%s -- ", __current__func__); \
+        gameplay::Logger::log(gameplay::Logger::LEVEL_WARN, __VA_ARGS__); \
+        gameplay::Logger::log(gameplay::Logger::LEVEL_WARN, "\n"); \
     } while (0)
 
 // Bullet Physics
@@ -152,7 +157,13 @@ extern void printError(const char* format, ...);
 #endif
 
 // Audio (OpenAL/Vorbis)
-#if defined (__QNX__) || defined(__ANDROID__)
+#ifdef __QNX__
+#include <AL/al.h>
+#include <AL/alc.h>
+#elif __ANDROID__
+#include <AL/al.h>
+#include <AL/alc.h>
+#elif __linux__
 #include <AL/al.h>
 #include <AL/alc.h>
 #elif WIN32
@@ -190,7 +201,7 @@ using std::va_list;
         #define USE_NEON
     #endif
 #elif __ANDROID__
-	#include <EGL/egl.h>
+    #include <EGL/egl.h>
     #include <GLES2/gl2.h>
     #include <GLES2/gl2ext.h>
     extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray;
@@ -202,8 +213,13 @@ using std::va_list;
     #define OPENGL_ES
 #elif WIN32
     #define WIN32_LEAN_AND_MEAN
+    #define GLEW_STATIC
     #include <GL/glew.h>
     #define USE_VAO
+#elif __linux__
+        #define GLEW_STATIC
+        #include <GL/glew.h>
+        #define USE_VAO
 #elif __APPLE__
     #include "TargetConditionals.h"
     #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR

+ 11 - 0
gameplay/src/BoundingBox.cpp

@@ -15,6 +15,11 @@ BoundingBox::BoundingBox(const Vector3& min, const Vector3& max)
     set(min, max);
 }
 
+BoundingBox::BoundingBox(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
+{
+    set(minX, minY, minZ, maxX, maxY, maxZ);
+}
+
 BoundingBox::BoundingBox(const BoundingBox& copy)
 {
     set(copy);
@@ -247,6 +252,12 @@ void BoundingBox::set(const Vector3& min, const Vector3& max)
     this->max = max;
 }
 
+void BoundingBox::set(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
+{
+    min.set(minX, minY, minZ);
+    max.set(maxX, maxY, maxZ);
+}
+
 static void updateMinMax(Vector3* point, Vector3* min, Vector3* max)
 {
     GP_ASSERT(point);

+ 24 - 0
gameplay/src/BoundingBox.h

@@ -36,6 +36,18 @@ public:
      */
     BoundingBox(const Vector3& min, const Vector3& max);
 
+    /**
+     * Constructs a new bounding box from the specified values.
+     * 
+     * @param minX The x coordinate of the minimum point of the bounding box.
+     * @param minY The y coordinate of the minimum point of the bounding box.
+     * @param minZ The z coordinate of the minimum point of the bounding box.
+     * @param maxX The x coordinate of the maximum point of the bounding box.
+     * @param maxY The y coordinate of the maximum point of the bounding box.
+     * @param maxZ The z coordinate of the maximum point of the bounding box.
+     */
+    BoundingBox(float minX, float minY, float minZ, float maxX, float maxY, float maxZ);
+
     /**
      * Constructs a new bounding box from the given bounding box.
      *
@@ -163,6 +175,18 @@ public:
      */
     void set(const Vector3& min, const Vector3& max);
 
+    /**
+     * Sets this bounding box to the specified values.
+     * 
+     * @param minX The x coordinate of the minimum point of the bounding box.
+     * @param minY The y coordinate of the minimum point of the bounding box.
+     * @param minZ The z coordinate of the minimum point of the bounding box.
+     * @param maxX The x coordinate of the maximum point of the bounding box.
+     * @param maxY The y coordinate of the maximum point of the bounding box.
+     * @param maxZ The z coordinate of the maximum point of the bounding box.
+     */
+    void set(float minX, float minY, float minZ, float maxX, float maxY, float maxZ);
+
     /**
      * Sets this bounding box to the specified bounding box.
      *

+ 18 - 19
gameplay/src/Bundle.cpp

@@ -393,8 +393,8 @@ Scene* Bundle::loadScene(const char* id)
             return NULL;
         }
     }
-    
-    Scene* scene = Scene::createScene();
+
+    Scene* scene = Scene::create();
     scene->setId(getIdFromOffset());
 
     // Read the number of children.
@@ -505,7 +505,7 @@ Node* Bundle::loadNode(const char* id, Scene* sceneContext)
                 SAFE_DELETE(_trackedNodes);
                 return NULL;
             }
-            
+
             // Read the number of animations in this object.
             unsigned int animationCount;
             if (!read(&animationCount))
@@ -573,8 +573,8 @@ Node* Bundle::loadNode(const char* id, Scene* sceneContext)
                             SAFE_DELETE(_trackedNodes);
                             return NULL;
                         }
-                        
-                        // Skip the animation channel (passing a target attribute of 
+
+                        // Skip the animation channel (passing a target attribute of
                         // 0 causes the animation to not be created).
                         readAnimationChannelData(NULL, id.c_str(), NULL, 0);
                     }
@@ -636,7 +636,7 @@ bool Bundle::skipNode()
         GP_ERROR("Failed to skip node type for node '%s'.", id);
         return false;
     }
-    
+
     // Skip over the node's transform and parent ID.
     if (fseek(_file, sizeof(float) * 16, SEEK_CUR) != 0)
     {
@@ -660,7 +660,7 @@ bool Bundle::skipNode()
                 return false;
         }
     }
-    
+
     // Skip over the node's camera, light, and model attachments.
     Camera* camera = readCamera(); SAFE_RELEASE(camera);
     Light* light = readLight(); SAFE_RELEASE(light);
@@ -1109,7 +1109,7 @@ void Bundle::resolveJointReferences(Scene* sceneContext, Node* nodeContext)
             Node* node = rootJoint;
             GP_ASSERT(node);
             Node* parent = node->getParent();
-            
+
             std::vector<Node*> loadedNodes;
             while (true)
             {
@@ -1151,7 +1151,7 @@ void Bundle::resolveJointReferences(Scene* sceneContext, Node* nodeContext)
                             return;
                         }
                         std::string parentID = readString(_file);
-                        
+
                         if (!parentID.empty())
                             nodeId = parentID;
                         else
@@ -1259,11 +1259,11 @@ Animation* Bundle::readAnimationChannelData(Animation* animation, const char* id
 {
     GP_ASSERT(id);
 
-    std::vector<unsigned long> keyTimes;
+    std::vector<unsigned int> keyTimes;
     std::vector<float> values;
     std::vector<float> tangentsIn;
     std::vector<float> tangentsOut;
-    std::vector<unsigned long> interpolation;
+    std::vector<unsigned int> interpolation;
 
     // Length of the arrays.
     unsigned int keyTimesCount;
@@ -1278,28 +1278,28 @@ Animation* Bundle::readAnimationChannelData(Animation* animation, const char* id
         GP_ERROR("Failed to read key times for animation '%s'.", id);
         return NULL;
     }
-    
+
     // Read key values.
     if (!readArray(&valuesCount, &values))
     {
         GP_ERROR("Failed to read key values for animation '%s'.", id);
         return NULL;
     }
-    
+
     // Read in-tangents.
     if (!readArray(&tangentsInCount, &tangentsIn))
     {
         GP_ERROR("Failed to read in tangents for animation '%s'.", id);
         return NULL;
     }
-    
+
     // Read out-tangents.
     if (!readArray(&tangentsOutCount, &tangentsOut))
     {
         GP_ERROR("Failed to read out tangents for animation '%s'.", id);
         return NULL;
     }
-    
+
     // Read interpolations.
     if (!readArray(&interpolationCount, &interpolation, sizeof(unsigned int)))
     {
@@ -1307,7 +1307,6 @@ Animation* Bundle::readAnimationChannelData(Animation* animation, const char* id
         return NULL;
     }
 
-    // TODO: Handle other target attributes later.
     if (targetAttribute > 0)
     {
         GP_ASSERT(target);
@@ -1520,7 +1519,7 @@ Bundle::MeshData* Bundle::readMeshData()
 
         partData->primitiveType = (Mesh::PrimitiveType)pType;
         partData->indexFormat = (Mesh::IndexFormat)iFormat;
-        
+
         unsigned int indexSize = 0;
         switch (partData->indexFormat)
         {
@@ -1684,7 +1683,7 @@ Font* Bundle::loadFont(const char* id)
         SAFE_DELETE_ARRAY(glyphs);
         return NULL;
     }
-    
+
     // Read texture data.
     unsigned char* textureData = new unsigned char[textureByteCount];
     if (fread(textureData, 1, textureByteCount, _file) != textureByteCount)
@@ -1750,7 +1749,7 @@ unsigned int Bundle::getObjectCount() const
     return _referenceCount;
 }
 
-const char* Bundle::getObjectID(unsigned int index) const
+const char* Bundle::getObjectId(unsigned int index) const
 {
     GP_ASSERT(_references);
     return (index >= _referenceCount ? NULL : _references[index].id.c_str());

+ 1 - 1
gameplay/src/Bundle.h

@@ -95,7 +95,7 @@ public:
      * 
      * @return The ID of the object at the given index, or NULL if index is invalid.
      */
-    const char* getObjectID(unsigned int index) const;
+    const char* getObjectId(unsigned int index) const;
 
 private:
 

+ 27 - 26
gameplay/src/Button.cpp

@@ -40,41 +40,42 @@ bool Button::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contac
     case Touch::TOUCH_PRESS:
         if (_contactIndex == INVALID_CONTACT_INDEX)
         {
-			if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
-				y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
-			{
-				_contactIndex = (int) contactIndex;
+            if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+                y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
+            {
+                _contactIndex = (int) contactIndex;
 
-				setState(Control::ACTIVE);
+                setState(Control::ACTIVE);
 
-				notifyListeners(Listener::PRESS);
+                notifyListeners(Listener::PRESS);
 
-				return _consumeInputEvents;
-			}
-			else
-			{
-				setState(Control::NORMAL);
-			}
+                return _consumeInputEvents;
+            }
+            else
+            {
+                setState(Control::NORMAL);
+            }
         }
         break;
 
     case Touch::TOUCH_RELEASE:
         if (_contactIndex == (int) contactIndex)
         {
-			_contactIndex = INVALID_CONTACT_INDEX;
-			notifyListeners(Listener::RELEASE);
-			if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
-				y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
-			{
-				setState(Control::FOCUS);
-
-				notifyListeners(Listener::CLICK);
-			}
-			else
-			{
-				setState(Control::NORMAL);
-			}
-			return _consumeInputEvents;
+            _contactIndex = INVALID_CONTACT_INDEX;
+            notifyListeners(Listener::RELEASE);
+            if (!_parent->isScrolling() &&
+                x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+                y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
+            {
+                setState(Control::FOCUS);
+
+                notifyListeners(Listener::CLICK);
+            }
+            else
+            {
+                setState(Control::NORMAL);
+            }
+            return _consumeInputEvents;
         }
         break;
     case Touch::TOUCH_MOVE:

+ 1 - 0
gameplay/src/Button.h

@@ -1,6 +1,7 @@
 #ifndef BUTTON_H_
 #define BUTTON_H_
 
+#include "Container.h"
 #include "Label.h"
 #include "Touch.h"
 #include "Theme.h"

+ 10 - 9
gameplay/src/CheckBox.cpp

@@ -84,15 +84,16 @@ bool CheckBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int cont
     switch (evt)
     {
     case Touch::TOUCH_RELEASE:
-		if (_contactIndex == (int) contactIndex && _state == Control::ACTIVE)
-		{
-			if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
-				y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
-			{
-				_checked = !_checked;
-				notifyListeners(Control::Listener::VALUE_CHANGED);
-			}
-		}
+        if (_contactIndex == (int) contactIndex && _state == Control::ACTIVE)
+        {
+            if (!_parent->isScrolling() &&
+                x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+                y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
+            {
+                _checked = !_checked;
+                notifyListeners(Control::Listener::VALUE_CHANGED);
+            }
+        }
         break;
     }
 

+ 159 - 81
gameplay/src/Container.cpp

@@ -20,6 +20,8 @@ namespace gameplay
 static const long SCROLL_INERTIA_DELAY = 100L;
 // Factor to multiply friction by before applying to velocity.
 static const float SCROLL_FRICTION_FACTOR = 5.0f;
+// Distance that must be scrolled before isScrolling() will return true, used e.g. to cancel button-click events.
+static const float SCROLL_THRESHOLD = 10.0f;
 
 /**
  * Sort function for use with _controls.sort(), based on Z-Order.
@@ -41,7 +43,7 @@ Container::Container()
       _scrollingRight(false), _scrollingDown(false),
       _scrollingMouseVertically(false), _scrollingMouseHorizontally(false),
       _scrollBarOpacityClip(NULL), _zIndexDefault(0), _focusIndexDefault(0), _focusIndexMax(0), _totalWidth(0), _totalHeight(0),
-      _contactIndices(0)
+      _contactIndices(0), _initializedWithScroll(false)
 {
 }
 
@@ -172,6 +174,7 @@ void Container::addControls(Theme* theme, Properties* properties)
         if (control)
         {
             addControl(control);
+            control->release();
 
             if (control->getZIndex() == -1)
             {
@@ -204,32 +207,78 @@ Layout* Container::getLayout()
 unsigned int Container::addControl(Control* control)
 {
     GP_ASSERT(control);
-    _controls.push_back(control);
 
-    return _controls.size() - 1;
+    if (control->_parent && control->_parent != this)
+    {
+        control->_parent->removeControl(control);
+    }
+
+    if (control->_parent != this)
+    {
+        _controls.push_back(control);
+        control->addRef();
+        control->_parent = this;
+        return _controls.size() - 1;
+    }
+    else
+    {
+        // Control is already in this container.
+        // Do nothing but determine and return control's index.
+        const size_t size = _controls.size();
+        for (size_t i = 0; i < size; ++i)
+        {
+            Control* c = _controls[i];
+            if (c == control)
+            {
+                return i;
+            }
+        }
+
+        // Should never reach this.
+        GP_ASSERT(false);
+        return 0;
+    }
 }
 
 void Container::insertControl(Control* control, unsigned int index)
 {
     GP_ASSERT(control);
-    std::vector<Control*>::iterator it = _controls.begin() + index;
-    _controls.insert(it, control);
+
+    if (control->_parent && control->_parent != this)
+    {
+        control->_parent->removeControl(control);
+    }
+
+    if (control->_parent != this)
+    {
+        std::vector<Control*>::iterator it = _controls.begin() + index;
+        _controls.insert(it, control);
+        control->addRef();
+        control->_parent = this;
+    }
 }
 
 void Container::removeControl(unsigned int index)
 {
+    GP_ASSERT(index < _controls.size());
+
     std::vector<Control*>::iterator it = _controls.begin() + index;
     _controls.erase(it);
+    Control* control = *it;
+    control->_parent = NULL;
+    SAFE_RELEASE(control);
 }
 
 void Container::removeControl(const char* id)
 {
+    GP_ASSERT(id);
     std::vector<Control*>::iterator it;
     for (it = _controls.begin(); it < _controls.end(); it++)
     {
         Control* c = *it;
         if (strcmp(id, c->getId()) == 0)
         {
+            SAFE_RELEASE(c);
             _controls.erase(it);
             return;
         }
@@ -244,6 +293,7 @@ void Container::removeControl(Control* control)
     {
         if (*it == control)
         {
+            SAFE_RELEASE(control);
             _controls.erase(it);
             return;
         }
@@ -313,6 +363,16 @@ bool Container::isScrollBarsAutoHide() const
     return _scrollBarsAutoHide;
 }
 
+bool Container::isScrolling() const
+{
+    if (_parent && _parent->isScrolling())
+        return true;
+
+    return (_scrolling &&
+            (abs(_scrollingLastX - _scrollingFirstX) > SCROLL_THRESHOLD ||
+             abs(_scrollingLastY - _scrollingFirstY) > SCROLL_THRESHOLD));
+}
+
 Animation* Container::getAnimation(const char* id) const
 {
     std::vector<Control*>::const_iterator itr = _controls.begin();
@@ -533,6 +593,11 @@ bool Container::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
 
 bool Container::keyEvent(Keyboard::KeyEvent evt, int key)
 {
+    // This event may run untrusted code by notifying listeners of events.
+    // If the user calls exit() or otherwise releases this container, we
+    // need to keep it alive until the method returns.
+    addRef();
+
     std::vector<Control*>::const_iterator it;
     for (it = _controls.begin(); it < _controls.end(); it++)
     {
@@ -547,7 +612,8 @@ bool Container::keyEvent(Keyboard::KeyEvent evt, int key)
         {
             if (control->keyEvent(evt, key))
             {
-                return _consumeInputEvents;
+                release();
+                return true;
             }
             else if (evt == Keyboard::KEY_CHAR && key == Keyboard::KEY_TAB)
             {
@@ -566,6 +632,7 @@ bool Container::keyEvent(Keyboard::KeyEvent evt, int key)
                     if (nextControl->getFocusIndex() == focusIndex)
                     {
                         nextControl->setState(Control::FOCUS);
+                        release();
                         return _consumeInputEvents;
                     }
                 }
@@ -573,6 +640,7 @@ bool Container::keyEvent(Keyboard::KeyEvent evt, int key)
         }
     }
 
+    release();
     return false;
 }
 
@@ -602,10 +670,6 @@ Layout::Type Container::getLayoutType(const char* layoutString)
     {
         return Layout::LAYOUT_FLOW;
     }
-    else if (layoutName == "LAYOUT_SCROLL")
-    {
-        return Layout::LAYOUT_SCROLL;
-    }
     else
     {
         // Default.
@@ -615,6 +679,12 @@ Layout::Type Container::getLayoutType(const char* layoutString)
 
 void Container::updateScroll()
 {
+    if (!_initializedWithScroll)
+    {
+        _initializedWithScroll = true;
+        _layout->update(this, _scrollPosition);
+    }
+
     // Update Time.
     static double lastFrameTime = Game::getGameTime();
     double frameTime = Game::getGameTime();
@@ -730,26 +800,26 @@ bool Container::touchEventScroll(Touch::TouchEvent evt, int x, int y, unsigned i
     switch(evt)
     {
     case Touch::TOUCH_PRESS:
-    	if (_contactIndex == INVALID_CONTACT_INDEX)
-    	{
-    		_contactIndex = (int) contactIndex;
-    		_contactIndices++;
-			_scrollingLastX = _scrollingFirstX = x;
-			_scrollingLastY = _scrollingFirstY = y;
-			_scrollingVelocity.set(0, 0);
-			_scrolling = true;
-			_scrollingStartTimeX = _scrollingStartTimeY = 0;
-
-			if (_scrollBarOpacityClip && _scrollBarOpacityClip->isPlaying())
-			{
-				_scrollBarOpacityClip->stop();
-				_scrollBarOpacityClip = NULL;
-			}
-			_scrollBarOpacity = 1.0f;
+        if (_contactIndex == INVALID_CONTACT_INDEX)
+        {
+            _contactIndex = (int) contactIndex;
+            _contactIndices++;
+            _scrollingLastX = _scrollingFirstX = x;
+            _scrollingLastY = _scrollingFirstY = y;
+            _scrollingVelocity.set(0, 0);
+            _scrolling = true;
+            _scrollingStartTimeX = _scrollingStartTimeY = 0;
+
+            if (_scrollBarOpacityClip && _scrollBarOpacityClip->isPlaying())
+            {
+                _scrollBarOpacityClip->stop();
+                _scrollBarOpacityClip = NULL;
+            }
+            _scrollBarOpacity = 1.0f;
             _dirty = true;
-			return _consumeInputEvents;
-    	}
-		break;
+            return _consumeInputEvents;
+        }
+        break;
     case Touch::TOUCH_MOVE:
         if (_scrolling && _contactIndex == (int) contactIndex)
         {
@@ -814,58 +884,58 @@ bool Container::touchEventScroll(Touch::TouchEvent evt, int x, int y, unsigned i
         break;
 
     case Touch::TOUCH_RELEASE:
-    	if (_contactIndex == (int) contactIndex)
-    	{
-    		_contactIndex = INVALID_CONTACT_INDEX;
-    		_contactIndices--;
-			_scrolling = false;
-			double gameTime = Game::getAbsoluteTime();
-			float timeSinceLastMove = (float)(gameTime - _scrollingLastTime);
-			if (timeSinceLastMove > SCROLL_INERTIA_DELAY)
-			{
-				_scrollingVelocity.set(0, 0);
-				_scrollingMouseVertically = _scrollingMouseHorizontally = false;
+        if (_contactIndex == (int) contactIndex)
+        {
+            _contactIndex = INVALID_CONTACT_INDEX;
+            _contactIndices--;
+            _scrolling = false;
+            double gameTime = Game::getAbsoluteTime();
+            float timeSinceLastMove = (float)(gameTime - _scrollingLastTime);
+            if (timeSinceLastMove > SCROLL_INERTIA_DELAY)
+            {
+                _scrollingVelocity.set(0, 0);
+                _scrollingMouseVertically = _scrollingMouseHorizontally = false;
                 _dirty = true;
-				return _consumeInputEvents;
-			}
-
-			int dx = _scrollingLastX - _scrollingFirstX;
-			int dy = _scrollingLastY - _scrollingFirstY;
-
-			float timeTakenX = (float)(gameTime - _scrollingStartTimeX);
-			float elapsedSecsX = timeTakenX * 0.001f;
-			float timeTakenY = (float)(gameTime - _scrollingStartTimeY);
-			float elapsedSecsY = timeTakenY * 0.001f;
-
-			float vx = dx;
-			float vy = dy;
-			if (elapsedSecsX > 0)
-				vx = (float)dx / elapsedSecsX;
-			if (elapsedSecsY > 0)
-				vy = (float)dy / elapsedSecsY;
-
-			if (_scrollingMouseVertically)
-			{
-				float yRatio = _totalHeight / _absoluteBounds.height;
-				vy *= yRatio;
-				_scrollingVelocity.set(0, -vy);
-			}
-			else if (_scrollingMouseHorizontally)
-			{
-				float xRatio = _totalWidth / _absoluteBounds.width;
-				vx *= xRatio;
-				_scrollingVelocity.set(-vx, 0);
-			}
-			else
-			{
-				_scrollingVelocity.set(vx, vy);
-			}
-
-			_scrollingMouseVertically = _scrollingMouseHorizontally = false;
+                return _consumeInputEvents;
+            }
+
+            int dx = _scrollingLastX - _scrollingFirstX;
+            int dy = _scrollingLastY - _scrollingFirstY;
+
+            float timeTakenX = (float)(gameTime - _scrollingStartTimeX);
+            float elapsedSecsX = timeTakenX * 0.001f;
+            float timeTakenY = (float)(gameTime - _scrollingStartTimeY);
+            float elapsedSecsY = timeTakenY * 0.001f;
+
+            float vx = dx;
+            float vy = dy;
+            if (elapsedSecsX > 0)
+                vx = (float)dx / elapsedSecsX;
+            if (elapsedSecsY > 0)
+                vy = (float)dy / elapsedSecsY;
+
+            if (_scrollingMouseVertically)
+            {
+                float yRatio = _totalHeight / _absoluteBounds.height;
+                vy *= yRatio;
+                _scrollingVelocity.set(0, -vy);
+            }
+            else if (_scrollingMouseHorizontally)
+            {
+                float xRatio = _totalWidth / _absoluteBounds.width;
+                vx *= xRatio;
+                _scrollingVelocity.set(-vx, 0);
+            }
+            else
+            {
+                _scrollingVelocity.set(vx, vy);
+            }
+
+            _scrollingMouseVertically = _scrollingMouseHorizontally = false;
             _dirty = true;
-			return _consumeInputEvents;
-    	}
-    	break;
+            return _consumeInputEvents;
+        }
+        break;
     }
 
     return false;
@@ -955,6 +1025,11 @@ bool Container::pointerEvent(bool mouse, char evt, int x, int y, int data)
         return false;
     }
 
+    // This event may run untrusted code by notifying listeners of events.
+    // If the user calls exit() or otherwise releases this container, we
+    // need to keep it alive until the method returns.
+    addRef();
+
     bool eventConsumed = false;
     const Theme::Border& border = getBorder(_state);
     const Theme::Padding& padding = getPadding();
@@ -987,8 +1062,8 @@ bool Container::pointerEvent(bool mouse, char evt, int x, int y, int data)
         }
 
         Control::State currentState = control->getState();
-        if ((control->isContainer() && currentState == Control::FOCUS) || 
-            (currentState != Control::NORMAL) ||// && control->_contactIndex == data) ||
+        if ((control->isContainer() && currentState == Control::FOCUS) ||
+            (currentState != Control::NORMAL) ||
             ((evt == Touch::TOUCH_PRESS ||
               evt == Mouse::MOUSE_PRESS_LEFT_BUTTON ||
               evt == Mouse::MOUSE_PRESS_MIDDLE_BUTTON ||
@@ -1008,6 +1083,7 @@ bool Container::pointerEvent(bool mouse, char evt, int x, int y, int data)
 
     if (!isEnabled())
     {
+        release();
         return (_consumeInputEvents | eventConsumed);
     }
     
@@ -1027,6 +1103,7 @@ bool Container::pointerEvent(bool mouse, char evt, int x, int y, int data)
         {
             setState(Control::NORMAL);
             _contactIndex = INVALID_CONTACT_INDEX;
+            release();
             return false;
         }
         break;
@@ -1050,6 +1127,7 @@ bool Container::pointerEvent(bool mouse, char evt, int x, int y, int data)
         }
     }
 
+    release();
     return (_consumeInputEvents | eventConsumed);
 }
 

+ 9 - 0
gameplay/src/Container.h

@@ -175,6 +175,13 @@ public:
      */
     bool isScrollBarsAutoHide() const;
 
+    /**
+     * Whether this container is currently being scrolled.
+     *
+     * @return Whether this container is currently being scrolled.
+     */
+    bool isScrolling() const;
+
     /**
      * @see AnimationTarget::getAnimation
      */
@@ -507,6 +514,8 @@ private:
     float _totalHeight;
 
     int _contactIndices;
+
+    bool _initializedWithScroll;
 };
 
 }

+ 39 - 14
gameplay/src/Control.cpp

@@ -7,8 +7,8 @@ namespace gameplay
 
 Control::Control()
     : _id(""), _state(Control::NORMAL), _bounds(Rectangle::empty()), _clipBounds(Rectangle::empty()), _viewportClipBounds(Rectangle::empty()),
-    _clearBounds(Rectangle::empty()), _dirty(true), _consumeInputEvents(true), _listeners(NULL),
-    _contactIndex(INVALID_CONTACT_INDEX), _styleOverridden(false), _skin(NULL)
+    _clearBounds(Rectangle::empty()), _dirty(true), _consumeInputEvents(true), _alignment(ALIGN_TOP_LEFT), _autoWidth(false), _autoHeight(false), _listeners(NULL),
+    _contactIndex(INVALID_CONTACT_INDEX), _focusIndex(0), _parent(NULL), _styleOverridden(false), _skin(NULL)
 {
     addScriptEvent("controlEvent", "<Control>[Control::Listener::EventType]");
 }
@@ -41,7 +41,7 @@ void Control::initialize(Theme::Style* style, Properties* properties)
     _autoWidth = properties->getBool("autoWidth");
     _autoHeight = properties->getBool("autoHeight");
 
-    _consumeInputEvents = properties->getBool("consumeEvents", true);
+    _consumeInputEvents = properties->getBool("consumeInputEvents", true);
 
     if (properties->exists("zIndex"))
     {
@@ -153,6 +153,24 @@ void Control::setSize(float width, float height)
     }
 }
 
+void Control::setWidth(float width)
+{
+    if (width != _bounds.width)
+    {
+        _bounds.width = width;
+        _dirty = true;
+    }
+}
+
+void Control::setHeight(float height)
+{
+    if (height != _bounds.height)
+    {
+        _bounds.height = height;
+        _dirty = true;
+    }
+}
+
 void Control::setBounds(const Rectangle& bounds)
 {
     if (bounds != _bounds)
@@ -726,20 +744,20 @@ bool Control::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int conta
     case Touch::TOUCH_RELEASE:
         if (_contactIndex == (int)contactIndex)
         {
-			_contactIndex = INVALID_CONTACT_INDEX;
+            _contactIndex = INVALID_CONTACT_INDEX;
 
-			// Always trigger Listener::RELEASE
-			notifyListeners(Listener::RELEASE);
+            // Always trigger Listener::RELEASE
+            notifyListeners(Listener::RELEASE);
 
-			// Only trigger Listener::CLICK if both PRESS and RELEASE took place within the control's bounds.
-			if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
-				y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
-			{
-				// Leave this control in the FOCUS state.
-				notifyListeners(Listener::CLICK);
-			}
+            // Only trigger Listener::CLICK if both PRESS and RELEASE took place within the control's bounds.
+            if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+                y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
+            {
+                // Leave this control in the FOCUS state.
+                notifyListeners(Listener::CLICK);
+            }
 
-			return _consumeInputEvents;
+            return _consumeInputEvents;
         }
         break;
     }
@@ -780,6 +798,11 @@ bool Control::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
 
 void Control::notifyListeners(Listener::EventType eventType)
 {
+    // This method runs untrusted code by notifying listeners of events.
+    // If the user calls exit() or otherwise releases this control, we
+    // need to keep it alive until the method returns.
+    addRef();
+
     if (_listeners)
     {
         std::map<Listener::EventType, std::list<Listener*>*>::const_iterator itr = _listeners->find(eventType);
@@ -795,6 +818,8 @@ void Control::notifyListeners(Listener::EventType eventType)
     }
 
     fireScriptEvent<void>("controlEvent", this, eventType);
+
+    release();
 }
 
 void Control::update(const Control* container, const Vector2& offset)

+ 21 - 0
gameplay/src/Control.h

@@ -15,6 +15,8 @@
 namespace gameplay
 {
 
+class Container;
+
 /**
  * Base class for UI controls.
  */
@@ -212,6 +214,20 @@ public:
      */
     virtual void setSize(float width, float height);
 
+    /** 
+     * Set the desired width of the control, including it's border and padding, before clipping.
+     *
+     * @param width The width.
+     */
+    virtual void setWidth(float width);
+
+    /** 
+     * Set the desired height of the control, including it's border and padding, before clipping.
+     *
+     * @param height The height.
+     */
+    virtual void setHeight(float height);
+
     /**
      * Set the bounds of this control, relative to its parent container and including its
      * border and padding, before clipping.
@@ -990,6 +1006,11 @@ protected:
      */
     int _focusIndex;
 
+    /**
+     * The control's parent container.
+     */
+    Container* _parent;
+
 private:
 
     /*

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels