Procházet zdrojové kódy

Merge remote-tracking branch 'upstream/next' into next

Brandon Slack před 13 roky
rodič
revize
cfe1377930
52 změnil soubory, kde provedl 2774 přidání a 317 odebrání
  1. 3 2
      CHANGES.md
  2. 7 0
      CMakeLists.txt
  3. 145 0
      gameplay-encoder/CMakeLists.txt
  4. 37 22
      gameplay-encoder/README.md
  5. 2 0
      gameplay-encoder/src/Base.h
  6. 1 1
      gameplay-encoder/src/Curve.cpp
  7. 1 1
      gameplay-encoder/src/DAEOptimizer.cpp
  8. 5 5
      gameplay-encoder/src/DAESceneEncoder.cpp
  9. 16 16
      gameplay-encoder/src/DAEUtil.cpp
  10. 1 5
      gameplay-encoder/src/FBXSceneEncoder.cpp
  11. 1 1
      gameplay-encoder/src/FBXSceneEncoder.h
  12. 2 0
      gameplay-encoder/src/FileIO.h
  13. 1 2
      gameplay-encoder/src/GPBFile.cpp
  14. 2 2
      gameplay-encoder/src/Quaternion.cpp
  15. 54 36
      gameplay-newproject.sh
  16. 13 9
      gameplay-template/gameplay-template.xcodeproj/project.pbxproj
  17. 180 12
      gameplay.sln
  18. 6 0
      gameplay/CMakeLists.txt
  19. 9 6
      gameplay/android/jni/Android.mk
  20. 235 0
      gameplay/gameplay.vcxproj
  21. 18 0
      gameplay/gameplay.vcxproj.filters
  22. 36 0
      gameplay/gameplay.xcodeproj/project.pbxproj
  23. 1 1
      gameplay/src/AudioSource.cpp
  24. 7 7
      gameplay/src/Base.h
  25. 1 1
      gameplay/src/Container.cpp
  26. 5 0
      gameplay/src/Game.cpp
  27. 99 0
      gameplay/src/Logger.cpp
  28. 124 0
      gameplay/src/Logger.h
  29. 4 4
      gameplay/src/Mesh.cpp
  30. 208 9
      gameplay/src/PhysicsVehicle.cpp
  31. 223 0
      gameplay/src/PhysicsVehicle.h
  32. 56 22
      gameplay/src/PhysicsVehicleWheel.cpp
  33. 54 14
      gameplay/src/PhysicsVehicleWheel.h
  34. 67 26
      gameplay/src/PlatformAndroid.cpp
  35. 9 0
      gameplay/src/PlatformMacOSX.mm
  36. 36 5
      gameplay/src/PlatformQNX.cpp
  37. 7 0
      gameplay/src/PlatformWin32.cpp
  38. 74 38
      gameplay/src/PlatformiOS.mm
  39. 44 13
      gameplay/src/TextBox.cpp
  40. 1 0
      gameplay/src/gameplay.h
  41. 11 0
      gameplay/src/lua/lua_Global.cpp
  42. 1 0
      gameplay/src/lua/lua_Global.h
  43. 195 0
      gameplay/src/lua/lua_Logger.cpp
  44. 17 0
      gameplay/src/lua/lua_Logger.h
  45. 38 0
      gameplay/src/lua/lua_LoggerLevel.cpp
  46. 15 0
      gameplay/src/lua/lua_LoggerLevel.h
  47. 654 27
      gameplay/src/lua/lua_PhysicsVehicle.cpp
  48. 16 0
      gameplay/src/lua/lua_PhysicsVehicle.h
  49. 26 26
      gameplay/src/lua/lua_PhysicsVehicleWheel.cpp
  50. 4 4
      gameplay/src/lua/lua_PhysicsVehicleWheel.h
  51. 1 0
      gameplay/src/lua/lua_all_bindings.cpp
  52. 1 0
      gameplay/src/lua/lua_all_bindings.h

+ 3 - 2
CHANGES.md

@@ -1,10 +1,10 @@
 ## v1.5.0
 
-- Linux support.
+- Linux x64 support tested on Ubuntu 12+.
 - CMake support for Linux makefile generation.
 - Gamepad controllers support for desktops.
 - Touch gesture support for tap, swipe and pinch.
-- Vehicle phyics support via new PhysicsVehicle adn PhysicsVehicleWheels classes.
+- Vehicle phyics support via new PhysicsVehicle and PhysicsVehicleWheel classes.
 - Adds gameplay-tests project as a test app for various engine features with initial basic tests.
 - Adds support for Scene files for wildcard identifiers.
 - Web community forums at http://www.gameplay3d.org/forums
@@ -15,6 +15,7 @@
 - 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.
 
 ## v1.4.0
 

+ 7 - 0
CMakeLists.txt

@@ -3,6 +3,7 @@ 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}" )
@@ -16,4 +17,10 @@ add_subdirectory(gameplay)
 # gameplay samples
 add_subdirectory(gameplay-samples)
 
+# gameplay samples
+add_subdirectory(gameplay-tests)
+
+# gameplay encoder (See gameplay/bin)
+#add_subdirectory(gameplay-encoder)
+
 

+ 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 - 22
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 x64 (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/FbxSdk/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/FbxSdk/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,26 @@ 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: /Applications/Autodesk/FBX SDK/2013.3/lib/gcc4/ub/libfbxsdk-2013.3-static.a  (Add Other)
   * Example: libiconv.dylib, Cocoa.framework, SystemConfiguration.framework
 - Build gameplay-encoder
 
+### Building with FBX Support on Linux x64
+- 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.
 

+ 2 - 0
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>

+ 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);

+ 5 - 5
gameplay-encoder/src/DAESceneEncoder.cpp

@@ -264,7 +264,7 @@ 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)
     {
@@ -889,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:
             {
@@ -1286,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();
@@ -1295,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());
@@ -1372,7 +1372,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
             {
                 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();

+ 16 - 16
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();
@@ -542,7 +542,7 @@ void findChannelsTargetingJoints(const domSourceRef& source, std::list<domChanne
     {
         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);

+ 1 - 5
gameplay-encoder/src/FBXSceneEncoder.cpp

@@ -310,10 +310,6 @@ void FBXSceneEncoder::loadAnimationChannels(FbxAnimLayer* animLayer, FbxNode* fb
 {
     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
@@ -1713,4 +1709,4 @@ bool isGroupAnimationPossible(FbxMesh* fbxMesh)
     return false;
 }
 
-#endif
+#endif

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

@@ -216,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"

+ 1 - 2
gameplay-encoder/src/GPBFile.cpp

@@ -67,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))
     {
@@ -310,7 +310,6 @@ void GPBFile::adjust()
         }
     }
 
-    LOG(1, "Computing bounding volumes.\n");
     for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
     {
         computeBounds(*i);

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

@@ -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()

+ 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

+ 13 - 9
gameplay-template/gameplay-template.xcodeproj/project.pbxproj

@@ -7,6 +7,7 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		04AB98CB161F3A2100CF90C5 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04AB98CA161F3A2100CF90C5 /* IOKit.framework */; };
 		42438B531491AD2000D218B8 /* libgameplay.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42438B521491AD2000D218B8 /* libgameplay.a */; };
 		428F7BDE15CB131A009ED24C /* game.config in Resources */ = {isa = PBXBuildFile; fileRef = 428F7BDD15CB131A009ED24C /* game.config */; };
 		42C932C11491A0DB0098216A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42C932C01491A0DB0098216A /* Cocoa.framework */; };
@@ -43,8 +44,9 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
-		428F7BDD15CB131A009ED24C /* game.config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = game.config; sourceTree = "<group>"; };
+		04AB98CA161F3A2100CF90C5 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
 		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>"; };
+		428F7BDD15CB131A009ED24C /* game.config */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = game.config; sourceTree = "<group>"; };
 		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>"; };
@@ -79,6 +81,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				04AB98CB161F3A2100CF90C5 /* IOKit.framework in Frameworks */,
 				42438B531491AD2000D218B8 /* libgameplay.a in Frameworks */,
 				42C933211491A6C70098216A /* libbullet.a in Frameworks */,
 				42C933261491A6E50098216A /* libogg.a in Frameworks */,
@@ -192,6 +195,7 @@
 		5B61613A14CCC3590073B857 /* MacOSX */ = {
 			isa = PBXGroup;
 			children = (
+				04AB98CA161F3A2100CF90C5 /* IOKit.framework */,
 				42C932C01491A0DB0098216A /* Cocoa.framework */,
 				42C9331C1491A6750098216A /* QuartzCore.framework */,
 				42C933161491A5EB0098216A /* OpenGL.framework */,
@@ -239,7 +243,7 @@
 				5B61611714CCC24C0073B857 /* Frameworks */,
 				5B61612414CCC24C0073B857 /* ShellScript */,
 				5B61612514CCC24C0073B857 /* Resources */,
-				5BAF20A3152F2FCE003E2AC3 /* Copy Gameplay Resources Run Script */,
+				5BAF20A3152F2FCE003E2AC3 /* Copy Gameplay Reousrces Run Script */,
 			);
 			buildRules = (
 			);
@@ -325,7 +329,7 @@
 			shellPath = /bin/sh;
 			shellScript = "touch -cm ${SRCROOT}/res";
 		};
-		5BAF20A3152F2FCE003E2AC3 /* Copy Gameplay Resources Run Script */ = {
+		5BAF20A3152F2FCE003E2AC3 /* Copy Gameplay Reousrces Run Script */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
@@ -483,7 +487,7 @@
 		5B61612A14CCC24C0073B857 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-                ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				GCC_PRECOMPILE_PREFIX_HEADER = NO;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
@@ -496,7 +500,7 @@
 					"GAMEPLAY_PATH/external-deps/lua/include",
 				);
 				INFOPLIST_FILE = "TEMPLATE_PROJECT-ios.plist";
-                IPHONEOS_DEPLOYMENT_TARGET = 5.1;
+				IPHONEOS_DEPLOYMENT_TARGET = 5.1;
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"GAMEPLAY_PATH/external-deps/libpng/lib/ios/$(CURRENT_ARCH)\"",
@@ -504,7 +508,7 @@
 					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/ios/$(CURRENT_ARCH)\"",
 				);
 				SDKROOT = iphoneos;
-                TARGETED_DEVICE_FAMILY = "1,2";
+				TARGETED_DEVICE_FAMILY = "1,2";
 				USER_HEADER_SEARCH_PATHS = "";
 				WRAPPER_EXTENSION = app;
 			};
@@ -513,7 +517,7 @@
 		5B61612B14CCC24C0073B857 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-                ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				GCC_PRECOMPILE_PREFIX_HEADER = NO;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
@@ -526,7 +530,7 @@
 					"GAMEPLAY_PATH/external-deps/lua/include",
 				);
 				INFOPLIST_FILE = "TEMPLATE_PROJECT-ios.plist";
-                IPHONEOS_DEPLOYMENT_TARGET = 5.1;
+				IPHONEOS_DEPLOYMENT_TARGET = 5.1;
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"GAMEPLAY_PATH/external-deps/libpng/lib/ios/$(CURRENT_ARCH)\"",
@@ -534,7 +538,7 @@
 					"\"GAMEPLAY_PATH/external-deps/oggvorbis/lib/ios/$(CURRENT_ARCH)\"",
 				);
 				SDKROOT = iphoneos;
-                TARGETED_DEVICE_FAMILY = "1,2";
+				TARGETED_DEVICE_FAMILY = "1,2";
 				USER_HEADER_SEARCH_PATHS = "";
 				WRAPPER_EXTENSION = app;
 			};

+ 180 - 12
gameplay.sln

@@ -45,63 +45,231 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample06-racer", "gameplay-
 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
-		{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|Win32.ActiveCfg = DebugMem|Win32
-		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.DebugMem|Win32.Build.0 = DebugMem|Win32
-		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.Release|Win32.ActiveCfg = Release|Win32
-		{D70B295E-A2FF-2CBB-737E-3876E8AF77F6}.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

+ 6 - 0
gameplay/CMakeLists.txt

@@ -92,6 +92,8 @@ set(GAMEPLAY_SRC
     src/Layout.h
     src/Light.cpp
     src/Light.h
+    src/Logger.cpp
+    src/Logger.h
     src/Material.cpp
     src/Material.h
     src/MaterialParameter.cpp
@@ -361,6 +363,10 @@ set(GAMEPLAY_LUA
     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

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

@@ -59,6 +59,7 @@ LOCAL_SRC_FILES := \
     Label.cpp \
     Layout.cpp \
     Light.cpp \
+    Logger.cpp \
     Material.cpp \
     MaterialParameter.cpp \
     MathUtil.cpp \
@@ -83,8 +84,8 @@ LOCAL_SRC_FILES := \
     PhysicsRigidBody.cpp \
     PhysicsSocketConstraint.cpp \
     PhysicsSpringConstraint.cpp \
-	PhysicsVehicle.cpp \
-	PhysicsVehicleWheel.cpp \
+    PhysicsVehicle.cpp \
+    PhysicsVehicleWheel.cpp \
     Plane.cpp \
     PlatformAndroid.cpp \
     Properties.cpp \
@@ -170,8 +171,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_Gesture.cpp \
+    lua/lua_GestureGestureEvent.cpp \
     lua/lua_Global.cpp \
     lua/lua_Image.cpp \
     lua/lua_ImageFormat.cpp \
@@ -185,6 +186,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 \
@@ -227,8 +230,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_PhysicsVehicle.cpp \
+    lua/lua_PhysicsVehicleWheel.cpp \
     lua/lua_Plane.cpp \
     lua/lua_Platform.cpp \
     lua/lua_Properties.cpp \

+ 235 - 0
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>
@@ -58,6 +82,7 @@
     <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" />
@@ -129,6 +154,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" />
@@ -324,6 +351,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" />
@@ -395,6 +423,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" />
@@ -608,48 +638,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>
@@ -667,6 +789,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>
@@ -687,6 +844,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>
@@ -705,6 +903,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>

+ 18 - 0
gameplay/gameplay.vcxproj.filters

@@ -807,6 +807,15 @@
     <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">
@@ -1601,6 +1610,15 @@
     <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\gameplay-main-macosx.mm">

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

@@ -1707,6 +1707,18 @@
 		5BD52674150F8258004C9099 /* PhysicsCollisionObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5BD5266D150F8257004C9099 /* PhysicsCollisionObject.cpp */; };
 		5BD52675150F8258004C9099 /* PhysicsCollisionObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5266E150F8258004C9099 /* PhysicsCollisionObject.h */; };
 		5BD52676150F8258004C9099 /* PhysicsCollisionObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BD5266E150F8258004C9099 /* PhysicsCollisionObject.h */; };
+		B67EC8EB161DFC8E000B4D12 /* lua_Logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B67EC8E7161DFC8E000B4D12 /* lua_Logger.cpp */; };
+		B67EC8EC161DFC8E000B4D12 /* lua_Logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B67EC8E7161DFC8E000B4D12 /* lua_Logger.cpp */; };
+		B67EC8ED161DFC8E000B4D12 /* lua_Logger.h in Headers */ = {isa = PBXBuildFile; fileRef = B67EC8E8161DFC8E000B4D12 /* lua_Logger.h */; };
+		B67EC8EE161DFC8E000B4D12 /* lua_Logger.h in Headers */ = {isa = PBXBuildFile; fileRef = B67EC8E8161DFC8E000B4D12 /* lua_Logger.h */; };
+		B67EC8EF161DFC8E000B4D12 /* lua_LoggerLevel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B67EC8E9161DFC8E000B4D12 /* lua_LoggerLevel.cpp */; };
+		B67EC8F0161DFC8E000B4D12 /* lua_LoggerLevel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B67EC8E9161DFC8E000B4D12 /* lua_LoggerLevel.cpp */; };
+		B67EC8F1161DFC8E000B4D12 /* lua_LoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = B67EC8EA161DFC8E000B4D12 /* lua_LoggerLevel.h */; };
+		B67EC8F2161DFC8E000B4D12 /* lua_LoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = B67EC8EA161DFC8E000B4D12 /* lua_LoggerLevel.h */; };
+		B67EC8F6161DFCA8000B4D12 /* Logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B67EC8F4161DFCA8000B4D12 /* Logger.cpp */; };
+		B67EC8F7161DFCA8000B4D12 /* Logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B67EC8F4161DFCA8000B4D12 /* Logger.cpp */; };
+		B67EC8F8161DFCA8000B4D12 /* Logger.h in Headers */ = {isa = PBXBuildFile; fileRef = B67EC8F5161DFCA8000B4D12 /* Logger.h */; };
+		B67EC8F9161DFCA8000B4D12 /* Logger.h in Headers */ = {isa = PBXBuildFile; fileRef = B67EC8F5161DFCA8000B4D12 /* Logger.h */; };
 		F1616ABC1614E24B008DD8B7 /* MathUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1616ABB1614E24B008DD8B7 /* MathUtil.cpp */; };
 		F1616ABD1614E24B008DD8B7 /* MathUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1616ABB1614E24B008DD8B7 /* MathUtil.cpp */; };
 /* End PBXBuildFile section */
@@ -2611,6 +2623,12 @@
 		5BD5266C150F8257004C9099 /* PhysicsCharacter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhysicsCharacter.h; path = src/PhysicsCharacter.h; sourceTree = SOURCE_ROOT; };
 		5BD5266D150F8257004C9099 /* PhysicsCollisionObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PhysicsCollisionObject.cpp; path = src/PhysicsCollisionObject.cpp; sourceTree = SOURCE_ROOT; };
 		5BD5266E150F8258004C9099 /* PhysicsCollisionObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhysicsCollisionObject.h; path = src/PhysicsCollisionObject.h; sourceTree = SOURCE_ROOT; };
+		B67EC8E7161DFC8E000B4D12 /* lua_Logger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_Logger.cpp; sourceTree = "<group>"; };
+		B67EC8E8161DFC8E000B4D12 /* lua_Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lua_Logger.h; sourceTree = "<group>"; };
+		B67EC8E9161DFC8E000B4D12 /* lua_LoggerLevel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_LoggerLevel.cpp; sourceTree = "<group>"; };
+		B67EC8EA161DFC8E000B4D12 /* lua_LoggerLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lua_LoggerLevel.h; sourceTree = "<group>"; };
+		B67EC8F4161DFCA8000B4D12 /* Logger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Logger.cpp; path = src/Logger.cpp; sourceTree = SOURCE_ROOT; };
+		B67EC8F5161DFCA8000B4D12 /* Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logger.h; path = src/Logger.h; sourceTree = SOURCE_ROOT; };
 		F1616ABB1614E24B008DD8B7 /* MathUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MathUtil.cpp; path = src/MathUtil.cpp; sourceTree = SOURCE_ROOT; };
 /* End PBXFileReference section */
 
@@ -2782,6 +2800,8 @@
 				5BD52643150F822A004C9099 /* Layout.h */,
 				42CD0DE6147D8FF50000361E /* Light.cpp */,
 				42CD0DE7147D8FF50000361E /* Light.h */,
+				B67EC8F4161DFCA8000B4D12 /* Logger.cpp */,
+				B67EC8F5161DFCA8000B4D12 /* Logger.h */,
 				42CD0DE8147D8FF50000361E /* Material.cpp */,
 				42CD0DE9147D8FF50000361E /* Material.h */,
 				42CD0DEA147D8FF50000361E /* MaterialParameter.cpp */,
@@ -3397,6 +3417,10 @@
 				42BCD3A615EFD0F300C0E076 /* lua_Light.h */,
 				42BCD3A715EFD0F300C0E076 /* lua_LightType.cpp */,
 				42BCD3A815EFD0F300C0E076 /* lua_LightType.h */,
+				B67EC8E7161DFC8E000B4D12 /* lua_Logger.cpp */,
+				B67EC8E8161DFC8E000B4D12 /* lua_Logger.h */,
+				B67EC8E9161DFC8E000B4D12 /* lua_LoggerLevel.cpp */,
+				B67EC8EA161DFC8E000B4D12 /* lua_LoggerLevel.h */,
 				42BCD3A915EFD0F300C0E076 /* lua_Material.cpp */,
 				42BCD3AA15EFD0F300C0E076 /* lua_Material.h */,
 				42BCD3AB15EFD0F300C0E076 /* lua_MaterialParameter.cpp */,
@@ -4076,6 +4100,9 @@
 				421FBD551602818800A61BC0 /* PhysicsVehicleWheel.h in Headers */,
 				421FBD5E1602827C00A61BC0 /* lua_PhysicsVehicle.h in Headers */,
 				421FBD621602827C00A61BC0 /* lua_PhysicsVehicleWheel.h in Headers */,
+				B67EC8ED161DFC8E000B4D12 /* lua_Logger.h in Headers */,
+				B67EC8F1161DFC8E000B4D12 /* lua_LoggerLevel.h in Headers */,
+				B67EC8F8161DFCA8000B4D12 /* Logger.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -4503,6 +4530,9 @@
 				421FBD561602818800A61BC0 /* PhysicsVehicleWheel.h in Headers */,
 				421FBD5F1602827C00A61BC0 /* lua_PhysicsVehicle.h in Headers */,
 				421FBD631602827C00A61BC0 /* lua_PhysicsVehicleWheel.h in Headers */,
+				B67EC8EE161DFC8E000B4D12 /* lua_Logger.h in Headers */,
+				B67EC8F2161DFC8E000B4D12 /* lua_LoggerLevel.h in Headers */,
+				B67EC8F9161DFCA8000B4D12 /* Logger.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -4991,6 +5021,9 @@
 				421FBD5C1602827C00A61BC0 /* lua_PhysicsVehicle.cpp in Sources */,
 				421FBD601602827C00A61BC0 /* lua_PhysicsVehicleWheel.cpp in Sources */,
 				F1616ABC1614E24B008DD8B7 /* MathUtil.cpp in Sources */,
+				B67EC8EB161DFC8E000B4D12 /* lua_Logger.cpp in Sources */,
+				B67EC8EF161DFC8E000B4D12 /* lua_LoggerLevel.cpp in Sources */,
+				B67EC8F6161DFCA8000B4D12 /* Logger.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -5415,6 +5448,9 @@
 				421FBD5D1602827C00A61BC0 /* lua_PhysicsVehicle.cpp in Sources */,
 				421FBD611602827C00A61BC0 /* lua_PhysicsVehicleWheel.cpp in Sources */,
 				F1616ABD1614E24B008DD8B7 /* MathUtil.cpp in Sources */,
+				B67EC8EC161DFC8E000B4D12 /* lua_Logger.cpp in Sources */,
+				B67EC8F0161DFC8E000B4D12 /* lua_LoggerLevel.cpp in Sources */,
+				B67EC8F7161DFCA8000B4D12 /* Logger.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 1 - 1
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) );

+ 7 - 7
gameplay/src/Base.h

@@ -25,6 +25,7 @@
 #include <limits>
 #include <functional>
 #include <bitset>
+#include "Logger.h"
 
 // Bring common functions from C into global namespace
 using std::memcpy;
@@ -42,7 +43,6 @@ using std::min;
 using std::max;
 using std::modf;
 
-
 // Common
 #ifndef NULL
 #define NULL     0
@@ -77,9 +77,9 @@ extern void print(const char* format, ...);
 #else
 #define GP_ERROR(...) do \
     { \
-        gameplay::print("%s -- ", __current__func__); \
-        gameplay::print(__VA_ARGS__); \
-        gameplay::print("\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)
@@ -88,9 +88,9 @@ extern void print(const char* format, ...);
 // Warning macro.
 #define GP_WARN(...) do \
     { \
-        gameplay::print("%s -- ", __current__func__); \
-        gameplay::print(__VA_ARGS__); \
-        gameplay::print("\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

+ 1 - 1
gameplay/src/Container.cpp

@@ -601,7 +601,7 @@ bool Container::keyEvent(Keyboard::KeyEvent evt, int key)
             if (control->keyEvent(evt, key))
             {
                 release();
-                return _consumeInputEvents;
+                return true;
             }
             else if (evt == Keyboard::KEY_CHAR && key == Keyboard::KEY_TAB)
             {

+ 5 - 0
gameplay/src/Game.cpp

@@ -563,6 +563,11 @@ void Game::loadConfig()
                 FileSystem::loadResourceAliases(aliases);
             }
         }
+        else
+        {
+            // Create an empty config
+            _properties = new Properties();
+        }
     }
 }
 

+ 99 - 0
gameplay/src/Logger.cpp

@@ -0,0 +1,99 @@
+#include "Base.h"
+#include "Game.h"
+#include "ScriptController.h"
+
+namespace gameplay
+{
+
+Logger::State Logger::_state[3];
+
+Logger::State::State() : logFunctionC(NULL), logFunctionLua(NULL), enabled(true)
+{
+}
+
+Logger::Logger()
+{
+}
+
+Logger::~Logger()
+{
+}
+
+void Logger::log(Level level, const char* message, ...)
+{
+    State& state = _state[level];
+    if (!state.enabled)
+        return;
+
+    va_list args;
+    va_start(args, message);
+
+    // Declare a moderately sized buffer on the stack that should be
+    // large enough to accomodate most log requests.
+    int size = 1024;
+    char stackBuffer[1024];
+    std::vector<char> dynamicBuffer;
+    char* str = stackBuffer;
+    for ( ; ; )
+    {
+        // Pass one less than size to leave room for NULL terminator
+        int needed = vsnprintf(str, size-1, message, args);
+
+        // NOTE: Some platforms return -1 when vsnprintf runs out of room, while others return
+        // the number of characters actually needed to fill the buffer.
+        if (needed >= 0 && needed < size)
+        {
+            // Successfully wrote buffer. Added a NULL terminator in case it wasn't written.
+            str[needed] = '\0';
+            break;
+        }
+
+        size = needed > 0 ? (needed + 1) : (size * 2);
+        dynamicBuffer.resize(size);
+        str = &dynamicBuffer[0];
+    }
+
+    if (state.logFunctionC)
+    {
+        // Pass call to registered C log function
+        (*state.logFunctionC)(level, str);
+    }
+    else if (state.logFunctionLua)
+    {
+        // Pass call to registered Lua log function
+        Game::getInstance()->getScriptController()->executeFunction<void>(state.logFunctionLua, "[Logger::Level]s", level, str);
+    }
+    else
+    {
+        // Log to the default output
+        gameplay::print(str);
+    }
+
+    va_end(args);
+}
+
+bool Logger::isEnabled(Level level)
+{
+    return _state[level].enabled;
+}
+
+void Logger::setEnabled(Level level, bool enabled)
+{
+    _state[level].enabled = enabled;
+}
+
+void Logger::set(Level level, void (*logFunction) (Level, const char*))
+{
+    State& state = _state[level];
+    state.logFunctionC = logFunction;
+    state.logFunctionLua = NULL;
+}
+
+void Logger::set(Level level, const char* logFunction)
+{
+    State& state = _state[level];
+    state.logFunctionLua = logFunction;
+    state.logFunctionC = NULL;
+}
+
+}

+ 124 - 0
gameplay/src/Logger.h

@@ -0,0 +1,124 @@
+#ifndef LOGGER_H_
+#define LOGGER_H_
+
+namespace gameplay
+{
+
+/**
+ * Provides a basic logging system for the game.
+ *
+ * By default, this class logs messages using the gameplay::print function, which
+ * is implemented in a platform dependent manner and typically prints to stderr
+ * as well as to other possibly platform specific locations. Logging behavior
+ * can be modified for a specific log level by passing a custom C or Lua logging
+ * function to the Logger::set method. Logging can also be toggled using the
+ * setEnabled method.
+ */
+class Logger
+{
+public:
+
+    /** 
+     * Enumeration of valid log levels.
+     */
+    enum Level
+    {
+        LEVEL_INFO = 0,
+        LEVEL_WARN = 1,
+        LEVEL_ERROR = 2
+    };
+
+    /**
+     * Logs a message at the specified log level.
+     *
+     * This method accepts a variable argument list with the same formatting specification
+     * as printf. Therefore, the message parameter can include any format specifiers that
+     * are supported by printf.
+     *
+     * @param level Log level.
+     * @param message Log message.
+     */
+    static void log(Level level, const char* message, ...);
+
+    /**
+     * Determines if logging is currently enabled for the given level.
+     *
+     * @param level Log level.
+     *
+     * @return True if logging is enabled for this level, or false if it is disabled.
+     */
+    static bool isEnabled(Level level);
+
+    /**
+     * Enables or disables logging at the given level.
+     *
+     * @param level Log level to enable or disable.
+     * @param enabled True to enable the logger for the given level, false to disable it.
+     */
+    static void setEnabled(Level level, bool enabled);
+
+    /**
+     * Sets a C callback function to handle logging requests for the specified
+     * log level.
+     *
+     * When a call to log is made with the given level, the specified C function will
+     * be called to handle the request.
+     *
+     * Passing NULL for logFunction restores the default log behavior for this level.
+     *
+     * @param level Log level to set logging callback for.
+     * @param logFunction Pointer to a C function to call for each log request at the given log level.
+     * @script{ignore}
+     */
+    static void set(Level level, void (*logFunction) (Level, const char*));
+
+    /**
+     * Sets a Lua function as the log handler for the specified log level.
+     *
+     * When a call to log is made with the given level, the specified 
+     * Lua function will be called to handle the request.
+     *
+     * Passing NULL for logFunction restores the default log behavior for this level.
+     *
+     * @param level Log level.
+     * @param logFunction The Lua function to call for each log request at the given log level.
+     */
+    static void set(Level level, const char* logFunction);
+
+private:
+
+    struct State
+    {
+        State();
+        void (*logFunctionC) (Level, const char*);
+        const char* logFunctionLua;
+        bool enabled;
+    };
+
+    /**
+     * Hidden constructor.
+     */
+    Logger();
+
+    /**
+     * Hidden destructor.
+     */
+    ~Logger();
+
+    /**
+     * Hidden copy constructor.
+     */
+    Logger(const Logger& copy);
+
+    /**
+     * Hidden copy assignment operator.
+     */
+    Logger& operator=(const Logger&);
+
+    static State _state[3];
+
+};
+
+}
+
+#endif

+ 4 - 4
gameplay/src/Mesh.cpp

@@ -109,10 +109,10 @@ Mesh* Mesh::createQuadFullscreen()
 
     float vertices[] =
     {
-        x, y2,   0, 0,
-        x, y,    0, 1,
-        x2, y2,  1, 0,
-        x2, y,   1, 1
+        x, y2,   0, 1,
+        x, y,    0, 0,
+        x2, y2,  1, 1,
+        x2, y,   1, 0
     };
 
     VertexFormat::Element elements[] =

+ 208 - 9
gameplay/src/PhysicsVehicle.cpp

@@ -1,9 +1,13 @@
 #include "Base.h"
 #include "Game.h"
+#include "MathUtil.h"
 #include "Node.h"
 #include "PhysicsVehicle.h"
 #include "PhysicsVehicleWheel.h"
 
+#define AIR_DENSITY (1.2f)
+#define KPH_TO_MPS (1.0f / 3.6f)
+
 namespace gameplay
 {
 
@@ -76,7 +80,7 @@ private:
 };
 
 PhysicsVehicle::PhysicsVehicle(Node* node, const PhysicsCollisionShape::Definition& shape, const PhysicsRigidBody::Parameters& parameters)
-    : PhysicsCollisionObject(node)
+    : PhysicsCollisionObject(node), _speedSmoothed(0)
 {
     // Note that the constructor for PhysicsRigidBody calls addCollisionObject and so
     // that is where the rigid body gets added to the dynamics world.
@@ -86,7 +90,7 @@ PhysicsVehicle::PhysicsVehicle(Node* node, const PhysicsCollisionShape::Definiti
 }
 
 PhysicsVehicle::PhysicsVehicle(Node* node, PhysicsRigidBody* rigidBody)
-    : PhysicsCollisionObject(node)
+    : PhysicsCollisionObject(node), _speedSmoothed(0)
 {
     _rigidBody = rigidBody;
 
@@ -117,6 +121,42 @@ PhysicsVehicle* PhysicsVehicle::create(Node* node, Properties* properties)
         {
             vehicle->setDrivingForce(properties->getFloat());
         }
+        else if (strcmp(name, "steerdownSpeed") == 0)
+        {
+            vehicle->_steerdownSpeed = properties->getFloat();
+        }
+        else if (strcmp(name, "steerdownGain") == 0)
+        {
+            vehicle->_steerdownGain = properties->getFloat();
+        }
+        else if (strcmp(name, "brakedownStart") == 0)
+        {
+            vehicle->_brakedownStart = properties->getFloat();
+        }
+        else if (strcmp(name, "brakedownFull") == 0)
+        {
+            vehicle->_brakedownFull = properties->getFloat();
+        }
+        else if (strcmp(name, "drivedownStart") == 0)
+        {
+            vehicle->_drivedownStart = properties->getFloat();
+        }
+        else if (strcmp(name, "drivedownFull") == 0)
+        {
+            vehicle->_drivedownFull = properties->getFloat();
+        }
+        else if (strcmp(name, "boostSpeed") == 0)
+        {
+            vehicle->_boostSpeed = properties->getFloat();
+        }
+        else if (strcmp(name, "boostGain") == 0)
+        {
+            vehicle->_boostGain = properties->getFloat();
+        }
+        else if (strcmp(name, "downforce") == 0)
+        {
+            vehicle->_downforce = properties->getFloat();
+        }
         else
         {
             // Ignore this case (we've already parsed the rigid body parameters).
@@ -134,6 +174,11 @@ void PhysicsVehicle::initialize()
     setSteeringGain(0.5f);
     setBrakingForce(350.0f);
     setDrivingForce(2000.0f);
+    setSteerdown(0, 1);
+    setBrakedown(1000, 0);
+    setDrivedown(1000, 0);
+    setBoost(0, 1);
+    setDownforce(0);
 
     // Create the vehicle and add it to world
     btRigidBody* body = static_cast<btRigidBody*>(_rigidBody->getCollisionObject());
@@ -181,6 +226,11 @@ PhysicsRigidBody* PhysicsVehicle::getRigidBody() const
     return _rigidBody;
 }
 
+void PhysicsVehicle::setEnabled(bool enable)
+{
+    getRigidBody()->setEnabled(enable);
+}
+
 unsigned int PhysicsVehicle::getNumWheels() const
 {
     return _wheels.size();
@@ -204,25 +254,39 @@ float PhysicsVehicle::getSpeedKph() const
     return _vehicle->getCurrentSpeedKmHour();
 }
 
+float PhysicsVehicle::getSpeedSmoothKph() const
+{
+    return _speedSmoothed;
+}
+
 void PhysicsVehicle::update(float elapsedTime, float steering, float braking, float driving)
 {
+    float v = getSpeedKph();
+    MathUtil::smooth(&_speedSmoothed, v, elapsedTime, 0, 1200);
+    applyDownforce();
+
+    // Adjust control inputs based on vehicle speed.
+    steering = getSteering(v, steering);
+    driving = getDriving(v, driving, braking);
+    braking = getBraking(v, braking);
+
+    // Allow braking to take precedence over driving.
+    if (driving > 0 && braking > 0)
+    {
+        driving = 0;
+    }
+
     PhysicsVehicleWheel* wheel;
     for (int i = 0; i < _vehicle->getNumWheels(); i++)
     {
         wheel = getWheel(i);
 
-        if (wheel->isFront())
+        if (wheel->isSteerable())
         {
             _vehicle->setSteeringValue(steering * _steeringGain, i);
         }
         else
         {
-            // Allow braking to take precedence over driving.
-            if (driving > 0 && braking > 0)
-            {
-                driving = 0;
-            }
-
             _vehicle->applyEngineForce(driving * _drivingForce, i);
             _vehicle->setBrake(braking * _brakingForce, i);
         }
@@ -232,6 +296,67 @@ void PhysicsVehicle::update(float elapsedTime, float steering, float braking, fl
     }
 }
 
+void PhysicsVehicle::reset()
+{
+    _rigidBody->setLinearVelocity(Vector3::zero());
+    _rigidBody->setAngularVelocity(Vector3::zero());
+    _speedSmoothed = 0;
+}
+
+float PhysicsVehicle::getSteering(float v, float rawSteering) const
+{
+    float gain = 1;
+    if (_steerdownSpeed > MATH_FLOAT_SMALL)
+    {
+        gain = max(_steerdownGain, 1 - (1 - _steerdownGain) * fabs(v) / _steerdownSpeed);
+    }
+
+    return rawSteering * gain;
+}
+
+float PhysicsVehicle::getBraking(float v, float rawBraking) const
+{
+    float reduc = 0;
+    float delta = _brakedownFull - _brakedownStart;
+    if (delta > MATH_FLOAT_SMALL)
+    {
+        reduc = max(0.0f, (v - _brakedownStart) / delta);
+        reduc *= reduc;
+    }
+
+    return max(0.0f, rawBraking - reduc);
+}
+
+float PhysicsVehicle::getDriving(float v, float rawDriving, float rawBraking) const
+{
+    float reduc = 0;
+    float delta = _drivedownFull - _drivedownStart;
+    if (rawBraking == 0 && delta > MATH_FLOAT_SMALL)
+    {
+        reduc = max(0.0f, (v - _drivedownStart) / delta);
+        reduc *= reduc;
+    }
+
+    float gain = 1;
+    if (_boostSpeed > MATH_FLOAT_SMALL)
+    {
+        gain = max(1.0f, _boostGain - (_boostGain - 1) * fabs(v) / _boostSpeed);
+    }
+
+    return gain * rawDriving - reduc;
+}
+
+void PhysicsVehicle::applyDownforce()
+{
+    float v = _speedSmoothed * KPH_TO_MPS;
+
+    // dynamic pressure
+    float q = 0.5f * AIR_DENSITY * v * v;
+
+    // _downforce is the product of reference area and the aerodynamic coefficient
+    _rigidBody->applyForce(Vector3(0, -_downforce * q, 0));
+}
+
 float PhysicsVehicle::getSteeringGain() const
 {
     return _steeringGain;
@@ -262,4 +387,78 @@ void PhysicsVehicle::setDrivingForce(float drivingForce)
     _drivingForce = drivingForce;
 }
 
+float PhysicsVehicle::getSteerdownSpeed() const
+{
+    return _steerdownSpeed;
+}
+
+float PhysicsVehicle::getSteerdownGain() const
+{
+    return _steerdownGain;
+}
+
+void PhysicsVehicle::setSteerdown(float steerdownSpeed, float steerdownGain)
+{
+    _steerdownSpeed = steerdownSpeed;
+    _steerdownGain = steerdownGain;
+}
+
+float PhysicsVehicle::getBrakedownStart() const
+{
+    return _brakedownStart;
+}
+
+float PhysicsVehicle::getBrakedownFull() const
+{
+    return _brakedownFull;
+}
+
+void PhysicsVehicle::setBrakedown(float brakedownStart, float brakedownFull)
+{
+    _brakedownStart = brakedownStart;
+    _brakedownFull = brakedownFull;
+}
+
+float PhysicsVehicle::getDrivedownStart() const
+{
+    return _drivedownStart;
+}
+
+float PhysicsVehicle::getDrivedownFull() const
+{
+    return _drivedownFull;
+}
+
+void PhysicsVehicle::setDrivedown(float drivedownStart, float drivedownFull)
+{
+    _drivedownStart = drivedownStart;
+    _drivedownFull = drivedownFull;
+}
+
+float PhysicsVehicle::getBoostSpeed() const
+{
+    return _boostSpeed;
+}
+
+float PhysicsVehicle::getBoostGain() const
+{
+    return _boostGain;
+}
+
+void PhysicsVehicle::setBoost(float boostSpeed, float boostGain)
+{
+    _boostSpeed = boostSpeed;
+    _boostGain = boostGain;
+}
+
+float PhysicsVehicle::getDownforce() const
+{
+    return _downforce;
+}
+
+void PhysicsVehicle::setDownforce(float downforce)
+{
+    _downforce = downforce;
+}
+
 }

+ 223 - 0
gameplay/src/PhysicsVehicle.h

@@ -33,6 +33,25 @@ class PhysicsVehicleWheel;
         steeringGain   = <float>    // steering at full deflection
         brakingForce   = <float>    // braking force at full braking
         drivingForce   = <float>    // driving force at full throttle
+
+        // Steering gain reduction with speed (optional)
+        steerdownSpeed = <float>    // steering gain fades to this point
+        steerdownGain  = <float>    // gain value at that point (less than 1)
+
+        // Brake force reduction at high speeds (optional)
+        brakedownStart = <float>    // braking fades above this speed
+        brakedownFull  = <float>    // braking is fully faded at this speed
+
+        // Driving force reduction at high speeds (optional)
+        drivedownStart = <float>    // driving force fades above this speed
+        drivedownFull  = <float>    // driving force is fully faded at this speed
+
+        // Driving force boost at low speeds (optional)
+        boostSpeed     = <float>    // Boost fades to 1 at this point
+        boostGain      = <float>    // Boost at zero speed (greater than 1)
+
+        // Aerodynamic downforce effect (optional)
+        downforce      = <float>    // proportional control of downforce
     }
  @endverbatim
  */
@@ -53,6 +72,14 @@ public:
      */
     PhysicsRigidBody* getRigidBody() const;
 
+    /**
+     * Sets whether the associated rigid body is enabled or disabled
+     * in the physics world.
+     *
+     * @param enable true enables the collision object, false disables it.
+     */
+    void setEnabled(bool enable);
+
     /**
      * Returns the number of wheels on this vehicle.
      *
@@ -80,6 +107,12 @@ public:
      */
     float getSpeedKph() const;
 
+    /**
+     * Returns a lagged version of vehicle speed in kilometers per hour,
+     * for example that might be used to control engine sounds.
+     */
+    float getSpeedSmoothKph() const;
+
     /**
      * Updates the vehicle state using the specified normalized command
      * inputs, and updates the transform on the visual node for each wheel.
@@ -91,6 +124,11 @@ public:
      */
     void update(float elapsedTime, float steering, float braking, float driving);
 
+    /**
+     * Resets the vehicle's state, for example in preparation for a reposition.
+     */
+    void reset();
+
     /**
      * Gets steering gain at full deflection.
      *
@@ -133,6 +171,151 @@ public:
      */
     void setDrivingForce(float drivingForce);
 
+    /**
+     * Returns speed at the point of reduced steering, in km/h.
+     * A point of reduced steering is defined by speed and gain.
+     * Steering authority will reduce linearly with speed up to
+     * this point, and remain constant above that.
+     *
+     * @return speed at the point of reduced steering, in km/h.
+     */
+    float getSteerdownSpeed() const;
+
+    /**
+     * Returns gain at the point of reduced steering, typically
+     * less than 1.
+     * A point of reduced steering is defined by speed and gain.
+     * Steering authority will reduce linearly with speed up to
+     * this point, and remain constant above that.
+     *
+     * @return gain at the point of reduced steering.
+     */
+    float getSteerdownGain() const;
+
+    /**
+     * Sets the point of reduced steering, defined by speed and
+     * gain. Typically the gain value is less than 1.
+     * Steering authority will reduce linearly with speed up to
+     * this point, and remain constant above that.
+     *
+     * @param steerdownSpeed speed at the point of reduced steering,
+     *     in km/h.
+     * @param steerdownGain gain at the point of reduced steering.
+     *     A gain of 1 will effectively disable the feature.
+     */
+    void setSteerdown(float steerdownSpeed, float steerdownGain);
+
+    /**
+     * Returns speed where braking starts to fade, in km/h.
+     *
+     * @return speed where braking starts to fade, in km/h.
+     */
+    float getBrakedownStart() const;
+
+    /**
+     * Returns speed where braking is fully faded, in km/h.
+     * This speed is typically greater than the brakedownStart
+     * speed.
+     *
+     * @return speed where braking is fully faded, in km/h.
+     */
+    float getBrakedownFull() const;
+
+    /**
+     * Sets points that control fade of brake force with speed,
+     * in km/h.
+     *
+     * @param brakedownStart braking fades above this speed.
+     *     A very large value will effectively disable the feature.
+     * @param brakedownFull braking is fully faded at this speed.
+     *     This speed is typically greater than the brakedownStart
+     *     speed.
+     */
+    void setBrakedown(float brakedownStart, float brakedownFull);
+
+    /**
+     * Returns speed where driving force starts to fade, in km/h.
+     *
+     * @return speed where driving force starts to fade, in km/h.
+     */
+    float getDrivedownStart() const;
+
+    /**
+     * Returns speed where driving force is fully faded, in km/h.
+     * This speed is typically greater than the drivedownStart
+     * speed.
+     *
+     * @return speed where driving force is fully faded, in km/h.
+     */
+    float getDrivedownFull() const;
+
+    /**
+     * Sets points that control fade of driving force with speed,
+     * in km/h.
+     *
+     * @param drivedownStart driving force fades above this speed.
+     *     A very large value will effectively disable the feature.
+     * @param drivedownFull driving force is fully faded at this speed.
+     *     This speed is typically greater than the drivedownStart
+     *     speed.
+     */
+    void setDrivedown(float drivedownStart, float drivedownFull);
+
+    /**
+     * Returns upper limit of low-speed boost effect, in km/h.
+     * Driving force is boosted by a specified factor at zero speed,
+     * and that factor fades linearly with speed reaching 1 at
+     * this speed.
+     *
+     * @return upper limit of low-speed boost effect, in km/h.
+     */
+    float getBoostSpeed() const;
+
+    /**
+     * Returns boost gain at zero speed, typically greater than 1.
+     * Driving force is boosted by this factor at zero speed, and
+     * that factor fades linearly with speed reaching 1 at a
+     * specified speed.
+     *
+     * @return boost gain at zero speed.
+     */
+    float getBoostGain() const;
+
+    /**
+     * Sets parameters that define low-speed boost of the driving force.
+     * Driving force is boosted by the specified factor at zero speed,
+     * and that factor fades linearly with speed reaching 1 at the
+     * specified speed.
+     *
+     * @param boostSpeed upper limit of low-speed boost effect, in km/h.
+     * @param boostGain boost gain at zero speed, typically greater than 1.
+     *     A gain of 1 will effectively disable the feature.
+     */
+    void setBoost(float boostSpeed, float boostGain);
+
+    /**
+     * Returns the lumped constant that controls aerodynamic downforce.
+     * Technically speaking, this constant lumps together the reference
+     * area and the down-force coefficient, and is in world-units squared.
+     * The actual aerodynamic down-force is calculated as a function of
+     * current speed, and is proportional to this constant.
+     *
+     * @return the lumped constant that controls aerodynamic downforce.
+     */
+    float getDownforce() const;
+
+    /**
+     * Sets the lumped constant that controls aerodynamic downforce.
+     * Technically speaking, this constant lumps together the reference
+     * area and the down-force coefficient, and is in world-units squared.
+     * The actual aerodynamic down-force is calculated as a function of
+     * current speed, and is proportional to this constant.
+     *
+     * @param downforce the lumped constant that controls aerodynamic downforce.
+     *     A value of 0 will effectively disable this feature.
+     */
+    void setDownforce(float downforce);
+
 protected:
 
     /**
@@ -191,9 +374,49 @@ private:
      */
     ~PhysicsVehicle();
 
+    /**
+     * Returns adjusted steering value.
+     *
+     * @param v vehicle speed.
+     * @param rawSteering raw steering command.
+     */
+    float getSteering(float v, float rawSteering) const;
+
+    /**
+     * Returns adjusted braking force value.
+     *
+     * @param v vehicle speed.
+     * @param rawBraking raw braking force command.
+     */
+    float getBraking(float v, float rawBraking) const;
+
+    /**
+     * Returns adjusted driving force value.
+     *
+     * @param v vehicle speed.
+     * @param rawDriving raw driving force command.
+     * @param rawBraking raw braking force command.
+     */
+    float getDriving(float v, float rawDriving, float rawBraking) const;
+
+    /**
+     * Applies effect of aerodynamic downforce.
+     */
+    void applyDownforce();
+
     float _steeringGain;
     float _brakingForce;
     float _drivingForce;
+    float _steerdownSpeed;
+    float _steerdownGain;
+    float _brakedownStart;
+    float _brakedownFull;
+    float _drivedownStart;
+    float _drivedownFull;
+    float _boostSpeed;
+    float _boostGain;
+    float _downforce;
+    float _speedSmoothed;
     PhysicsRigidBody* _rigidBody;
     btRaycastVehicle::btVehicleTuning _vehicleTuning;
     btVehicleRaycaster* _vehicleRaycaster;

+ 56 - 22
gameplay/src/PhysicsVehicleWheel.cpp

@@ -14,8 +14,6 @@ PhysicsVehicleWheel::PhysicsVehicleWheel(Node* node, const PhysicsCollisionShape
     _rigidBody = new PhysicsRigidBody(node, shape, parameters);
 
     findAncestorAndBind();
-
-    _initialOffset = node->getTranslation();
 }
 
 PhysicsVehicleWheel::PhysicsVehicleWheel(Node* node, PhysicsRigidBody* rigidBody)
@@ -24,8 +22,6 @@ PhysicsVehicleWheel::PhysicsVehicleWheel(Node* node, PhysicsRigidBody* rigidBody
     _rigidBody = rigidBody;
 
     findAncestorAndBind();
-
-    _initialOffset = node->getTranslation();
 }
 
 PhysicsVehicleWheel* PhysicsVehicleWheel::create(Node* node, Properties* properties)
@@ -41,9 +37,9 @@ PhysicsVehicleWheel* PhysicsVehicleWheel::create(Node* node, Properties* propert
     const char* name;
     while ((name = properties->getNextProperty()) != NULL)
     {
-        if (strcmp(name, "isFront") == 0)
+        if (strcmp(name, "steerable") == 0)
         {
-            wheel->setFront(properties->getBool(name));
+            wheel->setSteerable(properties->getBool(name));
         }
         else if (strcmp(name, "wheelDirection") == 0 && properties->getVector3(name, &v))
         {
@@ -53,9 +49,9 @@ PhysicsVehicleWheel* PhysicsVehicleWheel::create(Node* node, Properties* propert
         {
             wheel->setWheelAxle(v);
         }
-        else if (strcmp(name, "strutConnectionPoint") == 0 && properties->getVector3(name, &v))
+        else if (strcmp(name, "strutConnectionOffset") == 0 && properties->getVector3(name, &v))
         {
-            wheel->setStrutConnectionPoint(v);
+            wheel->setStrutConnectionOffset(v);
         }
         else if (strcmp(name, "strutRestLength") == 0)
         {
@@ -119,6 +115,11 @@ PhysicsCollisionObject::Type PhysicsVehicleWheel::getType() const
     return PhysicsCollisionObject::VEHICLE_WHEEL;
 }
 
+void PhysicsVehicleWheel::setEnabled(bool enable)
+{
+    GP_ERROR("Operation not supported (PhysicsVehicleWheel::setEnabled(bool)). Use host vehicle instead.");
+}
+
 void PhysicsVehicleWheel::findAncestorAndBind()
 {
     GP_ASSERT(getNode());
@@ -152,6 +153,7 @@ void PhysicsVehicleWheel::findAncestorAndBind()
     if (host)
     {
         host->addWheel(this);
+        _initialOffset = _node->getTranslation() - host->_node->getTranslation();
     }
 }
 
@@ -181,18 +183,16 @@ void PhysicsVehicleWheel::addToVehicle(btRaycastVehicle* vehicle)
 void PhysicsVehicleWheel::transform(Node* node) const
 {
     GP_ASSERT(_host);
-    GP_ASSERT(_host->_vehicle);
     GP_ASSERT(_host->_node);
 
-    const btTransform& trans = _host->_vehicle->getWheelInfo(_indexInHost).m_worldTransform;
-    const btVector3& pos = trans.getOrigin();
     node->setRotation(_orientation);
 
     // Use only the component parallel to the defined strut line
     Vector3 strutLine;
     getWheelDirection(&strutLine);
-    Vector3 wheelPos = _initialOffset;
-    _host->_node->getMatrix().transformPoint(&wheelPos);
+    _host->_node->getMatrix().transformVector(&strutLine);
+    Vector3 wheelPos;
+    getWheelPos(&wheelPos);
     node->setTranslation(wheelPos + strutLine*(strutLine.dot(_positionDelta) / strutLine.lengthSquared()));
 }
 
@@ -200,7 +200,6 @@ void PhysicsVehicleWheel::update(float elapsedTime)
 {
     GP_ASSERT(_host);
     GP_ASSERT(_host->_vehicle);
-    GP_ASSERT(_host->_node);
 
     const btTransform& trans = _host->_vehicle->getWheelInfo(_indexInHost).m_worldTransform;
     const btQuaternion& rot = trans.getRotation();
@@ -208,8 +207,8 @@ void PhysicsVehicleWheel::update(float elapsedTime)
     _orientation.set(rot.x(), rot.y(), rot.z(), rot.w());
 
     Vector3 commandedPosition(pos.x(), pos.y(), pos.z());
-    Vector3 wheelPos = _initialOffset;
-    _host->_node->getMatrix().transformPoint(&wheelPos);
+    Vector3 wheelPos;
+    getWheelPos(&wheelPos);
     commandedPosition -= wheelPos;
 
     // Filter out noise from Bullet
@@ -219,7 +218,35 @@ void PhysicsVehicleWheel::update(float elapsedTime)
     _positionDelta.smooth(commandedPosition, elapsedTime, responseTime);
 }
 
-bool PhysicsVehicleWheel::isFront() const
+void PhysicsVehicleWheel::getConnectionDefault(Vector3* result) const
+{
+    // projected strut length
+    getWheelDirection(result);
+    result->normalize();
+    float length = 0.58f * getStrutRestLength();
+    *result *= -length;
+
+    // nudge wheel contact point to outer edge of tire for stability
+    Vector3 nudge;
+    getWheelAxle(&nudge);
+    nudge *= nudge.dot(_initialOffset);
+    nudge.normalize();
+    *result += nudge * 0.068f * getWheelRadius(); // rough-in for tire width
+
+    // offset at bind time
+    *result += _initialOffset;
+}
+
+void PhysicsVehicleWheel::getWheelPos(Vector3* result) const
+{
+    GP_ASSERT(_host);
+    GP_ASSERT(_host->_node);
+
+    *result = _initialOffset;
+    _host->_node->getMatrix().transformPoint(result);
+}
+
+bool PhysicsVehicleWheel::isSteerable() const
 {
     GP_ASSERT(_host);
     GP_ASSERT(_host->_vehicle);
@@ -227,12 +254,12 @@ bool PhysicsVehicleWheel::isFront() const
     return _host->_vehicle->getWheelInfo(_indexInHost).m_bIsFrontWheel;
 }
 
-void PhysicsVehicleWheel::setFront(bool front)
+void PhysicsVehicleWheel::setSteerable(bool steerable)
 {
     GP_ASSERT(_host);
     GP_ASSERT(_host->_vehicle);
 
-    _host->_vehicle->getWheelInfo(_indexInHost).m_bIsFrontWheel = front;
+    _host->_vehicle->getWheelInfo(_indexInHost).m_bIsFrontWheel = steerable;
 }
 
 void PhysicsVehicleWheel::getWheelDirection(Vector3* wheelDirection) const
@@ -269,19 +296,26 @@ void PhysicsVehicleWheel::setWheelAxle(const Vector3& wheelAxle)
     _host->_vehicle->getWheelInfo(_indexInHost).m_wheelAxleCS.setValue( wheelAxle.x, wheelAxle.y, wheelAxle.z);
 }
 
-void PhysicsVehicleWheel::getStrutConnectionPoint(Vector3* strutConnectionPoint) const
+void PhysicsVehicleWheel::getStrutConnectionOffset(Vector3* strutConnectionOffset) const
 {
     GP_ASSERT(_host);
     GP_ASSERT(_host->_vehicle);
 
     const btVector3& v = _host->_vehicle->getWheelInfo(_indexInHost).m_chassisConnectionPointCS;
-    strutConnectionPoint->set(v.x(), v.y(), v.z());
+    strutConnectionOffset->set(v.x(), v.y(), v.z());
+    Vector3 strutConnectionDefault;
+    getConnectionDefault(&strutConnectionDefault);
+    *strutConnectionOffset -= strutConnectionDefault;
 }
 
-void PhysicsVehicleWheel::setStrutConnectionPoint(const Vector3& strutConnectionPoint)
+void PhysicsVehicleWheel::setStrutConnectionOffset(const Vector3& strutConnectionOffset)
 {
     GP_ASSERT(_host);
     GP_ASSERT(_host->_vehicle);
+
+    Vector3 strutConnectionPoint;
+    getConnectionDefault(&strutConnectionPoint);
+    strutConnectionPoint += strutConnectionOffset;
     _host->_vehicle->getWheelInfo(_indexInHost).m_chassisConnectionPointCS.setValue(strutConnectionPoint.x,
                                                                                     strutConnectionPoint.y,
                                                                                     strutConnectionPoint.z);

+ 54 - 14
gameplay/src/PhysicsVehicleWheel.h

@@ -21,10 +21,10 @@ class PhysicsVehicle;
     {
         type                     = VEHICLE_WHEEL
 
-        isFront                  = <bool>                // indicates whether this is a front wheel
+        steerable                = <bool>                // indicates whether wheel is steerable
         wheelDirection           = <float, float, float> // direction strut extension, in chassis space
         wheelAxle                = <float, float, float> // direction of axle (spin axis), in chassis space
-        strutConnectionPoint     = <float, float, float> // strut connection point, in chassis space
+        strutConnectionOffset    = <float, float, float> // offset from default strut connection point
         strutRestLength          = <float>               // strut rest length
         strutTravelMax           = <float>               // maximum strut travel
         strutStiffness           = <float>               // strut stiffness, normalized to chassis mass
@@ -50,6 +50,11 @@ public:
      */
     PhysicsCollisionObject::Type getType() const;
 
+    /**
+     * Operation not supported. Use host vehicle's setEnabled() instead.
+     */
+    void setEnabled(bool enable);
+
     /**
      * Apply this wheel's world transform to the specified node.
      * Useful for updating the specified visual node with the current
@@ -61,18 +66,18 @@ public:
     void transform(Node* node) const;
 
     /**
-     * Returns true if this is a front wheel, false otherwise.
+     * Returns true if this wheel is steerable, false otherwise.
      *
-     * @return true if this is a front wheel, false otherwise.
+     * @return true if this wheel is steerable, false otherwise.
      */
-    bool isFront() const;
+    bool isSteerable() const;
 
     /**
-     * Sets whether this is a front wheel.
+     * Sets whether this wheel is steerable.
      *
-     * @param front true if this is a front wheel, false otherwise.
+     * @param steerable true if this wheel is steerable, false otherwise.
      */
-    void setFront(bool front);
+    void setSteerable(bool steerable);
 
     /**
      * Gets direction of strut extension, in chassis space.
@@ -103,18 +108,33 @@ public:
     void setWheelAxle(const Vector3& wheelAxle);
 
     /**
-     * Gets strut connection point, in chassis space.
+     * Gets offset from the default strut connection point.
+     * The default strut connection point is determined from the position
+     * of the wheel node relative to the chassis node, and uses the
+     * specified value for strut rest length to locate the connection
+     * point above it (i.e., in the specified direction of strut
+     * compression).
+     * Any non-zero strut connection offset acts as a delta from the
+     * computed default.
      *
-     * @param strutConnectionPoint address of where to store the result.
+     * @param strutConnectionOffset address of where to store the result.
      */
-    void getStrutConnectionPoint(Vector3* strutConnectionPoint) const;
+    void getStrutConnectionOffset(Vector3* strutConnectionOffset) const;
 
     /**
-     * Sets strut connection point, in chassis space.
+     * Sets offset from the default strut connection point.
+     * The default strut connection point is determined from the position
+     * of the wheel node relative to the chassis node, and uses the
+     * specified value for strut rest length to locate the connection
+     * point above it (i.e., in the specified direction of strut
+     * compression).
+     * Any non-zero strutConnectionOffset acts as a delta from the
+     * computed default.
      *
-     * @param strutConnectionPoint strut connection point.
+     * @param strutConnectionOffset offset from the default strut connection
+     *     point.
      */
-    void setStrutConnectionPoint(const Vector3& strutConnectionPoint);
+    void setStrutConnectionOffset(const Vector3& strutConnectionOffset);
 
     /**
      * Gets the strut rest length.
@@ -333,6 +353,26 @@ private:
      */
     void update(float elapsedTime);
 
+    /**
+     * Computes the default strut connection point for
+     * this wheel.
+     * The default strut connection point is determined from the position
+     * of the wheel node relative to the chassis node, and uses the
+     * specified value for maximum strut travel to locate the connection
+     * point above it (i.e., in the specified direction of strut
+     * compression).
+     *
+     * @param result where to store the result.
+     */
+    void getConnectionDefault(Vector3* result) const;
+
+    /**
+     * Get wheel position at bind time relative to chassis.
+     *
+     * @param result where to store the result.
+     */
+    void getWheelPos(Vector3* result) const;
+
     PhysicsRigidBody* _rigidBody;
     PhysicsVehicle* _host;
     unsigned int _indexInHost;

+ 67 - 26
gameplay/src/PlatformAndroid.cpp

@@ -108,14 +108,26 @@ static EGLenum checkErrorEGL(const char* msg)
 // Initialized EGL resources.
 static bool initEGL()
 {
+	int samples = 0;
+	Properties* config = Game::getInstance()->getConfig()->getNamespace("window", true);
+	if (config)
+	{
+		samples = std::max(config->getInt("samples"), 0);
+	}
+
     // Hard-coded to 32-bit/OpenGL ES 2.0.
+    // NOTE: EGL_SAMPLE_BUFFERS, EGL_SAMPLES and EGL_DEPTH_SIZE MUST remain at the beginning of the attribute list
+    // since they are expected to be at indices 0-5 in config fallback code later.
+	// EGL_DEPTH_SIZE is also expected to
     EGLint eglConfigAttrs[] =
     {
+		EGL_SAMPLE_BUFFERS,     samples > 0 ? 1 : 0,
+		EGL_SAMPLES,            samples,
+		EGL_DEPTH_SIZE,         24,
         EGL_RED_SIZE,           8,
         EGL_GREEN_SIZE,         8,
         EGL_BLUE_SIZE,          8,
         EGL_ALPHA_SIZE,         8,
-        EGL_DEPTH_SIZE,         24,
         EGL_STENCIL_SIZE,       8,
         EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
         EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
@@ -144,30 +156,59 @@ static bool initEGL()
             checkErrorEGL("eglGetDisplay");
             goto error;
         }
-    
+
         if (eglInitialize(__eglDisplay, NULL, NULL) != EGL_TRUE)
         {
             checkErrorEGL("eglInitialize");
             goto error;
         }
-    
-        if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) != EGL_TRUE)
-        {
-            checkErrorEGL("eglChooseConfig");
-            goto error;
-        }
-        
-        if (eglConfigCount == 0)
-        {
-            // try 16 bit depth buffer instead
-            eglConfigAttrs[9] = 16;
-            if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) != EGL_TRUE || eglConfigCount == 0)
-            {
-                checkErrorEGL("eglChooseConfig");
-                goto error;
-            }
-        }
-    
+
+		// Try both 24 and 16-bit depth sizes since some hardware (i.e. Tegra) does not support 24-bit depth
+		bool validConfig = false;
+		EGLint depthSizes[] = { 24, 16 };
+		for (unsigned int i = 0; i < 2; ++i)
+		{
+			eglConfigAttrs[1] = samples > 0 ? 1 : 0;
+			eglConfigAttrs[3] = samples;
+			eglConfigAttrs[5] = depthSizes[i];
+
+			if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) == EGL_TRUE && eglConfigCount > 0)
+			{
+				validConfig = true;
+				break;
+			}
+
+			if (samples)
+			{
+				// Try lowering the MSAA sample size until we find a supported config
+				int sampleCount = samples;
+				while (sampleCount)
+				{
+					GP_WARN("No EGL config found for depth_size=%d and samples=%d. Trying samples=%d instead.", depthSizes[i], sampleCount, sampleCount / 2);
+					sampleCount /= 2;
+					eglConfigAttrs[1] = sampleCount > 0 ? 1 : 0;
+					eglConfigAttrs[3] = sampleCount;
+					if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) == EGL_TRUE && eglConfigCount > 0)
+					{
+						validConfig = true;
+						break;
+					}
+				}
+				if (validConfig)
+					break;
+			}
+			else
+			{
+				GP_WARN("No EGL config found for depth_size=%d.", depthSizes[i]);
+			}
+		}
+
+		if (!validConfig)
+		{
+			checkErrorEGL("eglChooseConfig");
+			goto error;
+		}
+
         __eglContext = eglCreateContext(__eglDisplay, __eglConfig, EGL_NO_CONTEXT, eglContextAttrs);
         if (__eglContext == EGL_NO_CONTEXT)
         {
@@ -652,9 +693,9 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
                             else
                             {
                                 if (deltaY > 0)
-                                    direction = gameplay::Gesture::SWIPE_DIRECTION_UP;
-                                else if (deltaY < 0)
                                     direction = gameplay::Gesture::SWIPE_DIRECTION_DOWN;
+                                else if (deltaY < 0)
+                                    direction = gameplay::Gesture::SWIPE_DIRECTION_UP;
                             }
                             gameplay::Game::getInstance()->gestureSwipeEvent(x, y, direction);
                             __pointer0.pressed = false;
@@ -699,7 +740,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
                     {
                         pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
                         pointerId = AMotionEvent_getPointerId(event, pointerIndex);
-                        gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, x, y, pointerId);
+                        gameplay::Platform::touchEventInternal(Touch::TOUCH_PRESS, AMotionEvent_getX(event, pointerIndex), AMotionEvent_getY(event, pointerIndex), pointerId);
                     }
                 }
                 break;
@@ -707,7 +748,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
             case AMOTION_EVENT_ACTION_POINTER_UP:
                 {
                     pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-                    pointerId = AMotionEvent_getPointerId(event, 0);
+                    pointerId = AMotionEvent_getPointerId(event, pointerIndex);
                     x = AMotionEvent_getX(event, 0);
                     y = AMotionEvent_getY(event, 0);
 
@@ -729,9 +770,9 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
                                 direction |= gameplay::Gesture::SWIPE_DIRECTION_LEFT;
                             
                             if (deltaY > 0)
-                                direction |= gameplay::Gesture::SWIPE_DIRECTION_UP;
-                            else if (deltaY < 0)
                                 direction |= gameplay::Gesture::SWIPE_DIRECTION_DOWN;
+                            else if (deltaY < 0)
+                                direction |= gameplay::Gesture::SWIPE_DIRECTION_UP;
 
                             gameplay::Game::getInstance()->gestureSwipeEvent(x, y, direction);
                             __pointer1.pressed = false;

+ 9 - 0
gameplay/src/PlatformMacOSX.mm

@@ -7,6 +7,8 @@
 #include "Form.h"
 #include "ScriptController.h"
 #include <unistd.h>
+#include <IOKit/hid/IOHIDElement.h>
+#include <IOKit/hid/IOHIDDevice.h>
 #include <IOKit/hid/IOHIDLib.h>
 #import <Cocoa/Cocoa.h>
 #import <QuartzCore/CVDisplayLink.h>
@@ -1343,6 +1345,13 @@ int Platform::enterMessagePump()
 
             // Read fullscreen state.
             __fullscreen = config->getBool("fullscreen");
+            
+            // If fullscreen is specified, and width is not, interpret this
+            // as meaning, "use the current resolution".
+            if (__fullscreen && width == 0){
+			    __width = [[NSScreen mainScreen] frame].size.width;
+                __height = [[NSScreen mainScreen] frame].size.height;
+            }
         }
     }
 

+ 36 - 5
gameplay/src/PlatformQNX.cpp

@@ -421,7 +421,7 @@ EGLenum checkErrorEGL(const char* msg)
     GP_ASSERT(msg);
     static const char* errmsg[] =
     {
-        "EGL function succeeded",
+        "EGL function failed",
         "EGL is not initialized, or could not be initialized, for the specified display",
         "EGL cannot access a requested resource",
         "EGL failed to allocate resources for the requested operation",
@@ -544,6 +544,14 @@ Platform* Platform::create(Game* game, void* attachToWindow)
     FileSystem::setResourcePath("./app/native/");
     Platform* platform = new Platform(game);
 
+    // Query game config
+    int samples = 0;
+    Properties* config = Game::getInstance()->getConfig()->getNamespace("window", true);
+    if (config)
+    {
+        samples = std::max(config->getInt("samples"), 0);
+    }
+
     __gestureSet = gestures_set_alloc();
     swipe_gesture_alloc(NULL, gesture_callback, __gestureSet);
     pinch_gesture_alloc(NULL, gesture_callback, __gestureSet);
@@ -583,8 +591,12 @@ Platform* Platform::create(Game* game, void* attachToWindow)
     EGLint eglConfigCount;
 
     // Hard-coded to 32-bit/OpenGL ES 2.0.
-    const EGLint eglConfigAttrs[] =
+    // NOTE: EGL_SAMPLE_BUFFERS and EGL_SAMPLES MUST remain at the beginning of the attribute list
+    // since they are expected to be at indices 0-3 in config fallback code later.
+    EGLint eglConfigAttrs[] =
     {
+        EGL_SAMPLE_BUFFERS,     samples > 0 ? 1 : 0,
+        EGL_SAMPLES,            samples,
         EGL_RED_SIZE,           8,
         EGL_GREEN_SIZE,         8,
         EGL_BLUE_SIZE,          8,
@@ -766,8 +778,26 @@ Platform* Platform::create(Game* game, void* attachToWindow)
 
     if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) != EGL_TRUE || eglConfigCount == 0)
     {
-        checkErrorEGL("eglChooseConfig");
-        goto error;
+    	bool success = false;
+    	while (samples)
+    	{
+    		// Try lowering the MSAA sample count until we find a supported config
+    		GP_WARN("Failed to find a valid EGL configuration with EGL samples=%d. Trying samples=%d instead.", samples, samples/2);
+    		samples /= 2;
+    		eglConfigAttrs[1] = samples > 0 ? 1 : 0;
+    		eglConfigAttrs[3] = samples;
+    		if (eglChooseConfig(__eglDisplay, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) == EGL_TRUE && eglConfigCount > 0)
+    		{
+    			success = true;
+    			break;
+    		}
+    	}
+
+    	if (!success)
+    	{
+			checkErrorEGL("eglChooseConfig");
+			goto error;
+    	}
     }
 
     __eglContext = eglCreateContext(__eglDisplay, __eglConfig, EGL_NO_CONTEXT, eglContextAttrs);
@@ -1047,7 +1077,8 @@ int Platform::enterMessagePump()
                         break;
                     case NAVIGATOR_WINDOW_THUMBNAIL:
                     case NAVIGATOR_WINDOW_INVISIBLE:
-                        _game->pause();
+                        if (!suspended)
+                            _game->pause();
                         suspended = true;
                         break;
                     }

+ 7 - 0
gameplay/src/PlatformWin32.cpp

@@ -893,6 +893,13 @@ Platform* Platform::create(Game* game, void* attachToWindow)
         }
     }
 
+    // If fullscreen is specified, and width is not, interpret this
+    // as meaning, "use the current resolution".
+    if (params.fullscreen && params.rect.right == 0){
+        params.rect.right = params.rect.left + GetSystemMetrics(SM_CXSCREEN);
+        params.rect.bottom = params.rect.top + GetSystemMetrics(SM_CYSCREEN);
+    }
+    
     // If window size was not specified, set it to a default value
     if (params.rect.right == 0)
         params.rect.right = params.rect.left + DEFAULT_RESOLUTION_X;

+ 74 - 38
gameplay/src/PlatformiOS.mm

@@ -161,7 +161,7 @@ int getKey(unichar keyCode);
         multisampleDepthbuffer = 0;
         swapInterval = 1;        
         updating = FALSE;
-        game = Game::getInstance();
+        game = nil;
         
         // Set the resource path and initalize the game
         NSString* bundlePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/"];
@@ -172,7 +172,8 @@ int getKey(unichar keyCode);
 
 - (void) dealloc
 {
-    game->exit();
+    if (game)
+        game->exit();
     [self deleteFramebuffer];
     
     if ([EAGLContext currentContext] == context)
@@ -193,7 +194,10 @@ int getKey(unichar keyCode);
 {
     // Called on 'resize'.
     // Mark that framebuffer needs to be updated.
-    updateFramebuffer = YES;
+    // NOTE: Current disabled since we need to have a way to reset the default frame buffer handle
+    // in FrameBuffer.cpp (for FrameBuffer:bindDefault). This means that changing orientation at
+    // runtime is currently not supported until we fix this.
+    //updateFramebuffer = YES;
 }
 
 - (BOOL)createFramebuffer
@@ -209,7 +213,7 @@ int getKey(unichar keyCode);
     GL_ASSERT( glGenRenderbuffers(1, &colorRenderbuffer) );
     GL_ASSERT( glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer) );
     
-    // Associate our render buffer with CAEAGLLauyer so that the rendered content is display on our UI layer.
+    // Associate render buffer storage with CAEAGLLauyer so that the rendered content is display on our UI layer.
     [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
     
     // Attach the color buffer to our frame buffer
@@ -219,35 +223,52 @@ int getKey(unichar keyCode);
     GL_ASSERT( glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth) );
     GL_ASSERT( glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight) );
     
+    NSLog(@"width: %d, height: %d", framebufferWidth, framebufferHeight);
+    
     // If multisampling is enabled in config, create and setup a multisample buffer
-    Properties* config = game->getConfig()->getNamespace("window");
+    Properties* config = Game::getInstance()->getConfig()->getNamespace("window", true);
     int samples = config ? config->getInt("samples") : 0;
     if (samples < 0)
         samples = 0;
     if (samples)
     {
+        // Create multisample framebuffer
         GL_ASSERT( glGenFramebuffers(1, &multisampleFramebuffer) );
         GL_ASSERT( glBindFramebuffer(GL_FRAMEBUFFER, multisampleFramebuffer) );
         
+        // Create multisample render and depth buffers
         GL_ASSERT( glGenRenderbuffers(1, &multisampleRenderbuffer) );
-        GL_ASSERT( glBindRenderbuffer(1, multisampleRenderbuffer) );
-        GL_ASSERT( glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, samples, GL_RGBA8_OES, framebufferWidth, framebufferHeight) );
-        GL_ASSERT( glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, multisampleRenderbuffer) );
-        
         GL_ASSERT( glGenRenderbuffers(1, &multisampleDepthbuffer) );
-        GL_ASSERT( glBindRenderbuffer(GL_RENDERBUFFER, multisampleDepthbuffer) );
-        GL_ASSERT( glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT24_OES, framebufferWidth, framebufferHeight) );
-        GL_ASSERT( glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, multisampleDepthbuffer) );
-        
-        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+
+        // Try to find a supported multisample configuration starting with the defined sample count
+        while (samples)
         {
-            NSLog(@"Failed to make complete multisample buffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
-            [self deleteFramebuffer];
-            return NO;
+            GL_ASSERT( glBindRenderbuffer(GL_RENDERBUFFER, multisampleRenderbuffer) );
+            GL_ASSERT( glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, samples, GL_RGBA8_OES, framebufferWidth, framebufferHeight) );
+            GL_ASSERT( glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, multisampleRenderbuffer) );
+
+            GL_ASSERT( glBindRenderbuffer(GL_RENDERBUFFER, multisampleDepthbuffer) );
+            GL_ASSERT( glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, samples, GL_DEPTH_COMPONENT24_OES, framebufferWidth, framebufferHeight) );
+            GL_ASSERT( glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, multisampleDepthbuffer) );
+            
+            if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
+                break; // success!
+            
+            NSLog(@"Creation of multisample buffer with samples=%d failed. Attempting to use configuration with samples=%d instead: %x", samples, samples / 2, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+            samples /= 2;
         }
         
         // Re-bind the default framebuffer
         GL_ASSERT( glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer) );
+        
+        if (samples == 0)
+        {
+            // Unable to find a valid/supported multisample configuratoin - fallback to no multisampling
+            GL_ASSERT( glDeleteRenderbuffers(1, &multisampleRenderbuffer) );
+            GL_ASSERT( glDeleteRenderbuffers(1, &multisampleDepthbuffer) );
+            GL_ASSERT( glDeleteFramebuffers(1, &multisampleFramebuffer) );
+            multisampleFramebuffer = multisampleRenderbuffer = multisampleDepthbuffer = 0;
+        }
     }
     
     // Create default depth buffer and attach to the frame buffer.
@@ -269,6 +290,12 @@ int getKey(unichar keyCode);
         return NO;
     }
     
+    // If multisampling is enabled, set the currently bound framebuffer to the multisample buffer
+    // since that is the buffer code should be drawing into (and FrameBuffr::initialize will detect
+    // and set this bound buffer as the default one during initialization.
+    if (multisampleFramebuffer)
+        GL_ASSERT( glBindFramebuffer(GL_FRAMEBUFFER, multisampleFramebuffer) );
+    
     return YES;
 }
 
@@ -279,32 +306,32 @@ int getKey(unichar keyCode);
         [EAGLContext setCurrentContext:context];        
         if (defaultFramebuffer) 
         {
-            glDeleteFramebuffers(1, &defaultFramebuffer);
+            GL_ASSERT( glDeleteFramebuffers(1, &defaultFramebuffer) );
             defaultFramebuffer = 0;
         }        
         if (colorRenderbuffer) 
         {
-            glDeleteRenderbuffers(1, &colorRenderbuffer);
+            GL_ASSERT( glDeleteRenderbuffers(1, &colorRenderbuffer) );
             colorRenderbuffer = 0;
         }
         if (depthRenderbuffer) 
         {
-            glDeleteRenderbuffers(1, &depthRenderbuffer);
+            GL_ASSERT( glDeleteRenderbuffers(1, &depthRenderbuffer) );
             depthRenderbuffer = 0;
         }
         if (multisampleFramebuffer)
         {
-            glDeleteFramebuffers(1, &multisampleFramebuffer);
+            GL_ASSERT( glDeleteFramebuffers(1, &multisampleFramebuffer) );
             multisampleFramebuffer = 0;
         }
         if (multisampleRenderbuffer)
         {
-            glDeleteRenderbuffers(1, &multisampleRenderbuffer);
+            GL_ASSERT( glDeleteRenderbuffers(1, &multisampleRenderbuffer) );
             multisampleRenderbuffer = 0;
         }
         if (multisampleDepthbuffer)
         {
-            glDeleteRenderbuffers(1, &multisampleDepthbuffer);
+            GL_ASSERT( glDeleteRenderbuffers(1, &multisampleDepthbuffer) );
             multisampleDepthbuffer = 0;
         }
     }
@@ -335,16 +362,16 @@ int getKey(unichar keyCode);
         if (multisampleFramebuffer)
         {
             // Multisampling is enabled: resolve the multisample buffer into the default framebuffer
-            glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, defaultFramebuffer);
-            glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, multisampleFramebuffer);
-            glResolveMultisampleFramebufferAPPLE();
+            GL_ASSERT( glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, defaultFramebuffer) );
+            GL_ASSERT( glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, multisampleFramebuffer) );
+            GL_ASSERT( glResolveMultisampleFramebufferAPPLE() );
             
             if (oglDiscardSupported)
             {
                 // Performance hint that the GL driver can discard the contents of the multisample buffers
                 // since they have now been resolved into the default framebuffer
                 const GLenum discards[]  = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT };
-                glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, discards);
+                GL_ASSERT( glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, discards) );
             }
         }
         else
@@ -353,22 +380,25 @@ int getKey(unichar keyCode);
             {
                 // Performance hint to the GL driver that the depth buffer is no longer required.
                 const GLenum discards[]  = { GL_DEPTH_ATTACHMENT };
-                glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
-                glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards);
+                GL_ASSERT( glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer) );
+                GL_ASSERT( glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discards) );
             }
         }
         
         // Present the color buffer
-        glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
+        GL_ASSERT( glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer) );
         [context presentRenderbuffer:GL_RENDERBUFFER];
     }
 }
 
 - (void)startGame 
 {
-    game = Game::getInstance();
-    __timeStart = getMachTimeInMilliseconds();
-    game->run();
+    if (game == nil)
+    {
+        game = Game::getInstance();
+        __timeStart = getMachTimeInMilliseconds();
+        game->run();
+    }
 }
 
 - (void)startUpdating
@@ -378,7 +408,8 @@ int getKey(unichar keyCode);
         displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];
         [displayLink setFrameInterval:swapInterval];
         [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
-        game->resume();
+        if (game)
+            game->resume();
         updating = TRUE;
     }
 }
@@ -387,7 +418,8 @@ int getKey(unichar keyCode);
 {
     if (updating)
     {
-        game->pause();
+        if (game)
+            game->pause();
         [displayLink invalidate];
         displayLink = nil;
         updating = FALSE;
@@ -407,8 +439,14 @@ int getKey(unichar keyCode);
             updateFramebuffer = NO;
             [self deleteFramebuffer];
             [self createFramebuffer];
+            
+            // Start the game after our framebuffer is created for the first time.
+            if (game == nil)
+            {
+                [self startGame];
+            }
         }
-        
+
         // Bind our framebuffer for rendering.
         // If multisampling is enabled, bind the multisample buffer - otherwise bind the default buffer
         GL_ASSERT( glBindFramebuffer(GL_FRAMEBUFFER, multisampleFramebuffer ? multisampleFramebuffer : defaultFramebuffer) );
@@ -628,8 +666,6 @@ int getKey(unichar keyCode);
     {
         __view = (View*)self.view;
     }
-    // Start the game after assigning __view so Platform object knows about it on game start
-    [(View*)self.view startGame];
 }
 
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

+ 44 - 13
gameplay/src/TextBox.cpp

@@ -64,8 +64,8 @@ bool TextBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int conta
 
             if (_state == NORMAL)
                 Game::getInstance()->displayKeyboard(true);
-            else
-                setCaretLocation(x, y);
+
+            setCaretLocation(x, y);
 
             _state = ACTIVE;
             _dirty = true;
@@ -110,8 +110,6 @@ bool TextBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int conta
 
 bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
 {
-    bool consume = false;
-
     if (_state == FOCUS)
     {
         switch (evt)
@@ -149,7 +147,6 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex,
                             textAlignment, true, rightToLeft);
                         _dirty = true;
-                        consume = true;
                         notifyListeners(Listener::TEXT_CHANGED);
                         break;
                     }
@@ -166,7 +163,6 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex - 1,
                             textAlignment, true, rightToLeft);
                         _dirty = true;
-                        consume = true;
                         break;
                     }
                     case Keyboard::KEY_RIGHT_ARROW:
@@ -182,7 +178,6 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex + 1,
                             textAlignment, true, rightToLeft);
                         _dirty = true;
-                        consume = true;
                         break;
                     }
                     case Keyboard::KEY_UP_ARROW:
@@ -202,7 +197,6 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         }
 
                         _dirty = true;
-                        consume = true;
                         break;
                     }
                     case Keyboard::KEY_DOWN_ARROW:
@@ -222,7 +216,6 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         }
 
                         _dirty = true;
-                        consume = true;
                         break;
                     }
                 }
@@ -259,7 +252,6 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
 
                             _dirty = true;
                         }
-                        consume = true;
                         break;
                     }
                     case Keyboard::KEY_RETURN:
@@ -273,7 +265,6 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                     {
                         // Insert character into string.
                         _text.insert(textIndex, 1, (char)key);
-                        consume = true;
 
                         // Get new location of caret.
                         font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex + 1,
@@ -325,7 +316,7 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
 
     _lastKeypress = key;
 
-    return (consume & _consumeInputEvents);
+    return _consumeInputEvents;
 }
 
 void TextBox::update(const Control* container, const Vector2& offset)
@@ -374,7 +365,47 @@ void TextBox::setCaretLocation(int x, int y)
 
     if (index == -1)
     {
-        _caretLocation.set(_prevCaretLocation);
+        // Attempt to find the nearest valid caret location.
+        Rectangle textBounds;
+        font->measureText(_text.c_str(), _textBounds, fontSize, &textBounds, textAlignment, true, true);
+
+        if (_caretLocation.x > textBounds.x + textBounds.width &&
+            _caretLocation.y > textBounds.y + textBounds.height)
+        {
+            font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, _text.length(),
+                textAlignment, true, rightToLeft);
+            return;
+        }
+
+        if (_caretLocation.x < textBounds.x)
+        {
+            _caretLocation.x = textBounds.x;
+        }
+        else if (_caretLocation.x > textBounds.x + textBounds.width)
+        {
+            _caretLocation.x = textBounds.x + textBounds.width;
+        }
+
+        if (_caretLocation.y < textBounds.y)
+        {
+            _caretLocation.y = textBounds.y;
+        }
+        else if (_caretLocation.y > textBounds.y + textBounds.height)
+        {
+            Font* font = getFont(_state);
+            GP_ASSERT(font);
+            unsigned int fontSize = getFontSize(_state);
+            _caretLocation.y = textBounds.y + textBounds.height - fontSize;
+        }
+
+        index = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation,
+            textAlignment, true, rightToLeft);
+
+        if (index == -1)
+        {
+            // We failed to find a valid location; just put the caret back to where it was.
+            _caretLocation.set(_prevCaretLocation);
+        }
     }
 }
 

+ 1 - 0
gameplay/src/gameplay.h

@@ -10,6 +10,7 @@
 #include "FileSystem.h"
 #include "Bundle.h"
 #include "MathUtil.h"
+#include "Logger.h"
 
 // Math
 #include "Rectangle.h"

+ 11 - 0
gameplay/src/lua/lua_Global.cpp

@@ -565,6 +565,15 @@ void luaRegister_lua_Global()
         ScriptUtil::registerConstantString("SPOT", "SPOT", scopePath);
     }
 
+    // Register enumeration Logger::Level.
+    {
+        std::vector<std::string> scopePath;
+        scopePath.push_back("Logger");
+        ScriptUtil::registerConstantString("INFO", "INFO", scopePath);
+        ScriptUtil::registerConstantString("WARN", "WARN", scopePath);
+        ScriptUtil::registerConstantString("ERROR", "ERROR", scopePath);
+    }
+
     // Register enumeration Mesh::IndexFormat.
     {
         std::vector<std::string> scopePath;
@@ -824,6 +833,8 @@ const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value)
         return lua_stringFromEnum_LayoutType((Layout::Type)value);
     if (enumname == "Light::Type")
         return lua_stringFromEnum_LightType((Light::Type)value);
+    if (enumname == "Logger::Level")
+        return lua_stringFromEnum_LoggerLevel((Logger::Level)value);
     if (enumname == "Mesh::IndexFormat")
         return lua_stringFromEnum_MeshIndexFormat((Mesh::IndexFormat)value);
     if (enumname == "Mesh::PrimitiveType")

+ 1 - 0
gameplay/src/lua/lua_Global.h

@@ -23,6 +23,7 @@
 #include "lua_KeyboardKeyEvent.h"
 #include "lua_LayoutType.h"
 #include "lua_LightType.h"
+#include "lua_LoggerLevel.h"
 #include "lua_MeshIndexFormat.h"
 #include "lua_MeshPrimitiveType.h"
 #include "lua_MouseMouseEvent.h"

+ 195 - 0
gameplay/src/lua/lua_Logger.cpp

@@ -0,0 +1,195 @@
+#include "Base.h"
+#include "ScriptController.h"
+#include "lua_Logger.h"
+#include "Base.h"
+#include "Game.h"
+#include "Logger.h"
+#include "ScriptController.h"
+#include "lua_LoggerLevel.h"
+
+namespace gameplay
+{
+
+void luaRegister_Logger()
+{
+    const luaL_Reg* lua_members = NULL;
+    const luaL_Reg lua_statics[] = 
+    {
+        {"isEnabled", lua_Logger_static_isEnabled},
+        {"log", lua_Logger_static_log},
+        {"set", lua_Logger_static_set},
+        {"setEnabled", lua_Logger_static_setEnabled},
+        {NULL, NULL}
+    };
+    std::vector<std::string> scopePath;
+
+    ScriptUtil::registerClass("Logger", lua_members, NULL, NULL, lua_statics, scopePath);
+}
+
+static Logger* getInstance(lua_State* state)
+{
+    void* userdata = luaL_checkudata(state, 1, "Logger");
+    luaL_argcheck(state, userdata != NULL, 1, "'Logger' expected.");
+    return (Logger*)((ScriptUtil::LuaObject*)userdata)->instance;
+}
+
+int lua_Logger_static_isEnabled(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                Logger::Level param1 = (Logger::Level)lua_enumFromString_LoggerLevel(luaL_checkstring(state, 1));
+
+                bool result = Logger::isEnabled(param1);
+
+                // Push the return value onto the stack.
+                lua_pushboolean(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_Logger_static_isEnabled - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_Logger_static_log(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                Logger::Level param1 = (Logger::Level)lua_enumFromString_LoggerLevel(luaL_checkstring(state, 1));
+
+                // Get parameter 2 off the stack.
+                ScriptUtil::LuaArray<const char> param2 = ScriptUtil::getString(2, false);
+
+                Logger::log(param1, param2);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_Logger_static_log - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_Logger_static_set(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                Logger::Level param1 = (Logger::Level)lua_enumFromString_LoggerLevel(luaL_checkstring(state, 1));
+
+                // Get parameter 2 off the stack.
+                ScriptUtil::LuaArray<const char> param2 = ScriptUtil::getString(2, false);
+
+                Logger::set(param1, param2);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_Logger_static_set - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_Logger_static_setEnabled(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
+                lua_type(state, 2) == LUA_TBOOLEAN)
+            {
+                // Get parameter 1 off the stack.
+                Logger::Level param1 = (Logger::Level)lua_enumFromString_LoggerLevel(luaL_checkstring(state, 1));
+
+                // Get parameter 2 off the stack.
+                bool param2 = ScriptUtil::luaCheckBool(state, 2);
+
+                Logger::setEnabled(param1, param2);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_Logger_static_setEnabled - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+}

+ 17 - 0
gameplay/src/lua/lua_Logger.h

@@ -0,0 +1,17 @@
+#ifndef LUA_LOGGER_H_
+#define LUA_LOGGER_H_
+
+namespace gameplay
+{
+
+// Lua bindings for Logger.
+int lua_Logger_static_isEnabled(lua_State* state);
+int lua_Logger_static_log(lua_State* state);
+int lua_Logger_static_set(lua_State* state);
+int lua_Logger_static_setEnabled(lua_State* state);
+
+void luaRegister_Logger();
+
+}
+
+#endif

+ 38 - 0
gameplay/src/lua/lua_LoggerLevel.cpp

@@ -0,0 +1,38 @@
+#include "Base.h"
+#include "lua_LoggerLevel.h"
+
+namespace gameplay
+{
+
+static const char* enumStringEmpty = "";
+
+static const char* luaEnumString_LoggerLevel_LEVEL_INFO = "LEVEL_INFO";
+static const char* luaEnumString_LoggerLevel_LEVEL_WARN = "LEVEL_WARN";
+static const char* luaEnumString_LoggerLevel_LEVEL_ERROR = "LEVEL_ERROR";
+
+Logger::Level lua_enumFromString_LoggerLevel(const char* s)
+{
+    if (strcmp(s, luaEnumString_LoggerLevel_LEVEL_INFO) == 0)
+        return Logger::LEVEL_INFO;
+    if (strcmp(s, luaEnumString_LoggerLevel_LEVEL_WARN) == 0)
+        return Logger::LEVEL_WARN;
+    if (strcmp(s, luaEnumString_LoggerLevel_LEVEL_ERROR) == 0)
+        return Logger::LEVEL_ERROR;
+    GP_ERROR("Invalid enumeration value '%s' for enumeration Logger::Level.", s);
+    return Logger::LEVEL_INFO;
+}
+
+const char* lua_stringFromEnum_LoggerLevel(Logger::Level e)
+{
+    if (e == Logger::LEVEL_INFO)
+        return luaEnumString_LoggerLevel_LEVEL_INFO;
+    if (e == Logger::LEVEL_WARN)
+        return luaEnumString_LoggerLevel_LEVEL_WARN;
+    if (e == Logger::LEVEL_ERROR)
+        return luaEnumString_LoggerLevel_LEVEL_ERROR;
+    GP_ERROR("Invalid enumeration value '%d' for enumeration Logger::Level.", e);
+    return enumStringEmpty;
+}
+
+}
+

+ 15 - 0
gameplay/src/lua/lua_LoggerLevel.h

@@ -0,0 +1,15 @@
+#ifndef LUA_LOGGERLEVEL_H_
+#define LUA_LOGGERLEVEL_H_
+
+#include "Logger.h"
+
+namespace gameplay
+{
+
+// Lua bindings for enum conversion functions for Logger::Level.
+Logger::Level lua_enumFromString_LoggerLevel(const char* s);
+const char* lua_stringFromEnum_LoggerLevel(Logger::Level e);
+
+}
+
+#endif

+ 654 - 27
gameplay/src/lua/lua_PhysicsVehicle.cpp

@@ -3,6 +3,7 @@
 #include "lua_PhysicsVehicle.h"
 #include "Base.h"
 #include "Game.h"
+#include "MathUtil.h"
 #include "Node.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
@@ -23,14 +24,24 @@ void luaRegister_PhysicsVehicle()
         {"addCollisionListener", lua_PhysicsVehicle_addCollisionListener},
         {"addWheel", lua_PhysicsVehicle_addWheel},
         {"collidesWith", lua_PhysicsVehicle_collidesWith},
+        {"getBoostGain", lua_PhysicsVehicle_getBoostGain},
+        {"getBoostSpeed", lua_PhysicsVehicle_getBoostSpeed},
+        {"getBrakedownFull", lua_PhysicsVehicle_getBrakedownFull},
+        {"getBrakedownStart", lua_PhysicsVehicle_getBrakedownStart},
         {"getBrakingForce", lua_PhysicsVehicle_getBrakingForce},
         {"getCollisionShape", lua_PhysicsVehicle_getCollisionShape},
+        {"getDownforce", lua_PhysicsVehicle_getDownforce},
+        {"getDrivedownFull", lua_PhysicsVehicle_getDrivedownFull},
+        {"getDrivedownStart", lua_PhysicsVehicle_getDrivedownStart},
         {"getDrivingForce", lua_PhysicsVehicle_getDrivingForce},
         {"getNode", lua_PhysicsVehicle_getNode},
         {"getNumWheels", lua_PhysicsVehicle_getNumWheels},
         {"getRigidBody", lua_PhysicsVehicle_getRigidBody},
         {"getShapeType", lua_PhysicsVehicle_getShapeType},
         {"getSpeedKph", lua_PhysicsVehicle_getSpeedKph},
+        {"getSpeedSmoothKph", lua_PhysicsVehicle_getSpeedSmoothKph},
+        {"getSteerdownGain", lua_PhysicsVehicle_getSteerdownGain},
+        {"getSteerdownSpeed", lua_PhysicsVehicle_getSteerdownSpeed},
         {"getSteeringGain", lua_PhysicsVehicle_getSteeringGain},
         {"getType", lua_PhysicsVehicle_getType},
         {"getWheel", lua_PhysicsVehicle_getWheel},
@@ -38,9 +49,15 @@ void luaRegister_PhysicsVehicle()
         {"isEnabled", lua_PhysicsVehicle_isEnabled},
         {"isKinematic", lua_PhysicsVehicle_isKinematic},
         {"removeCollisionListener", lua_PhysicsVehicle_removeCollisionListener},
+        {"reset", lua_PhysicsVehicle_reset},
+        {"setBoost", lua_PhysicsVehicle_setBoost},
+        {"setBrakedown", lua_PhysicsVehicle_setBrakedown},
         {"setBrakingForce", lua_PhysicsVehicle_setBrakingForce},
+        {"setDownforce", lua_PhysicsVehicle_setDownforce},
+        {"setDrivedown", lua_PhysicsVehicle_setDrivedown},
         {"setDrivingForce", lua_PhysicsVehicle_setDrivingForce},
         {"setEnabled", lua_PhysicsVehicle_setEnabled},
+        {"setSteerdown", lua_PhysicsVehicle_setSteerdown},
         {"setSteeringGain", lua_PhysicsVehicle_setSteeringGain},
         {"update", lua_PhysicsVehicle_update},
         {NULL, NULL}
@@ -225,6 +242,154 @@ int lua_PhysicsVehicle_collidesWith(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsVehicle_getBoostGain(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                float result = instance->getBoostGain();
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getBoostGain - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_getBoostSpeed(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                float result = instance->getBoostSpeed();
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getBoostSpeed - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_getBrakedownFull(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                float result = instance->getBrakedownFull();
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getBrakedownFull - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_getBrakedownStart(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                float result = instance->getBrakedownStart();
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getBrakedownStart - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsVehicle_getBrakingForce(lua_State* state)
 {
     // Get the number of parameters.
@@ -308,6 +473,117 @@ int lua_PhysicsVehicle_getCollisionShape(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsVehicle_getDownforce(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                float result = instance->getDownforce();
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getDownforce - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_getDrivedownFull(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                float result = instance->getDrivedownFull();
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getDrivedownFull - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_getDrivedownStart(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                float result = instance->getDrivedownStart();
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getDrivedownStart - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsVehicle_getDrivingForce(lua_State* state)
 {
     // Get the number of parameters.
@@ -376,7 +652,127 @@ int lua_PhysicsVehicle_getNode(lua_State* state)
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicle_getNode - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicle_getNode - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_getNumWheels(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                unsigned int result = instance->getNumWheels();
+
+                // Push the return value onto the stack.
+                lua_pushunsigned(state, result);
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getNumWheels - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_getRigidBody(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                void* returnPtr = (void*)instance->getRigidBody();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsRigidBody");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getRigidBody - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_getShapeType(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                PhysicsCollisionShape::Type result = instance->getShapeType();
+
+                // Push the return value onto the stack.
+                lua_pushstring(state, lua_stringFromEnum_PhysicsCollisionShapeType(result));
+
+                return 1;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_getShapeType - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -391,7 +787,7 @@ int lua_PhysicsVehicle_getNode(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicle_getNumWheels(lua_State* state)
+int lua_PhysicsVehicle_getSpeedKph(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -404,16 +800,16 @@ int lua_PhysicsVehicle_getNumWheels(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 PhysicsVehicle* instance = getInstance(state);
-                unsigned int result = instance->getNumWheels();
+                float result = instance->getSpeedKph();
 
                 // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
+                lua_pushnumber(state, result);
 
                 return 1;
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicle_getNumWheels - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicle_getSpeedKph - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -428,7 +824,7 @@ int lua_PhysicsVehicle_getNumWheels(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicle_getRigidBody(lua_State* state)
+int lua_PhysicsVehicle_getSpeedSmoothKph(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -441,25 +837,16 @@ int lua_PhysicsVehicle_getRigidBody(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 PhysicsVehicle* instance = getInstance(state);
-                void* returnPtr = (void*)instance->getRigidBody();
-                if (returnPtr)
-                {
-                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                    object->instance = returnPtr;
-                    object->owns = false;
-                    luaL_getmetatable(state, "PhysicsRigidBody");
-                    lua_setmetatable(state, -2);
-                }
-                else
-                {
-                    lua_pushnil(state);
-                }
+                float result = instance->getSpeedSmoothKph();
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
 
                 return 1;
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicle_getRigidBody - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicle_getSpeedSmoothKph - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -474,7 +861,7 @@ int lua_PhysicsVehicle_getRigidBody(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicle_getShapeType(lua_State* state)
+int lua_PhysicsVehicle_getSteerdownGain(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -487,16 +874,16 @@ int lua_PhysicsVehicle_getShapeType(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 PhysicsVehicle* instance = getInstance(state);
-                PhysicsCollisionShape::Type result = instance->getShapeType();
+                float result = instance->getSteerdownGain();
 
                 // Push the return value onto the stack.
-                lua_pushstring(state, lua_stringFromEnum_PhysicsCollisionShapeType(result));
+                lua_pushnumber(state, result);
 
                 return 1;
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicle_getShapeType - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicle_getSteerdownGain - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -511,7 +898,7 @@ int lua_PhysicsVehicle_getShapeType(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicle_getSpeedKph(lua_State* state)
+int lua_PhysicsVehicle_getSteerdownSpeed(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -524,7 +911,7 @@ int lua_PhysicsVehicle_getSpeedKph(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 PhysicsVehicle* instance = getInstance(state);
-                float result = instance->getSpeedKph();
+                float result = instance->getSteerdownSpeed();
 
                 // Push the return value onto the stack.
                 lua_pushnumber(state, result);
@@ -533,7 +920,7 @@ int lua_PhysicsVehicle_getSpeedKph(lua_State* state)
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicle_getSpeedKph - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicle_getSteerdownSpeed - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -871,6 +1258,124 @@ int lua_PhysicsVehicle_removeCollisionListener(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsVehicle_reset(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                instance->reset();
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_reset - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_setBoost(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                float param1 = (float)luaL_checknumber(state, 2);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                PhysicsVehicle* instance = getInstance(state);
+                instance->setBoost(param1, param2);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_setBoost - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_setBrakedown(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                float param1 = (float)luaL_checknumber(state, 2);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                PhysicsVehicle* instance = getInstance(state);
+                instance->setBrakedown(param1, param2);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_setBrakedown - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsVehicle_setBrakingForce(lua_State* state)
 {
     // Get the number of parameters.
@@ -909,6 +1414,86 @@ int lua_PhysicsVehicle_setBrakingForce(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsVehicle_setDownforce(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                lua_type(state, 2) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                float param1 = (float)luaL_checknumber(state, 2);
+
+                PhysicsVehicle* instance = getInstance(state);
+                instance->setDownforce(param1);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_setDownforce - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_setDrivedown(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                float param1 = (float)luaL_checknumber(state, 2);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                PhysicsVehicle* instance = getInstance(state);
+                instance->setDrivedown(param1, param2);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_setDrivedown - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsVehicle_setDrivingForce(lua_State* state)
 {
     // Get the number of parameters.
@@ -985,6 +1570,48 @@ int lua_PhysicsVehicle_setEnabled(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsVehicle_setSteerdown(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                float param1 = (float)luaL_checknumber(state, 2);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                PhysicsVehicle* instance = getInstance(state);
+                instance->setSteerdown(param1, param2);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_PhysicsVehicle_setSteerdown - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsVehicle_setSteeringGain(lua_State* state)
 {
     // Get the number of parameters.

+ 16 - 0
gameplay/src/lua/lua_PhysicsVehicle.h

@@ -8,14 +8,24 @@ namespace gameplay
 int lua_PhysicsVehicle_addCollisionListener(lua_State* state);
 int lua_PhysicsVehicle_addWheel(lua_State* state);
 int lua_PhysicsVehicle_collidesWith(lua_State* state);
+int lua_PhysicsVehicle_getBoostGain(lua_State* state);
+int lua_PhysicsVehicle_getBoostSpeed(lua_State* state);
+int lua_PhysicsVehicle_getBrakedownFull(lua_State* state);
+int lua_PhysicsVehicle_getBrakedownStart(lua_State* state);
 int lua_PhysicsVehicle_getBrakingForce(lua_State* state);
 int lua_PhysicsVehicle_getCollisionShape(lua_State* state);
+int lua_PhysicsVehicle_getDownforce(lua_State* state);
+int lua_PhysicsVehicle_getDrivedownFull(lua_State* state);
+int lua_PhysicsVehicle_getDrivedownStart(lua_State* state);
 int lua_PhysicsVehicle_getDrivingForce(lua_State* state);
 int lua_PhysicsVehicle_getNode(lua_State* state);
 int lua_PhysicsVehicle_getNumWheels(lua_State* state);
 int lua_PhysicsVehicle_getRigidBody(lua_State* state);
 int lua_PhysicsVehicle_getShapeType(lua_State* state);
 int lua_PhysicsVehicle_getSpeedKph(lua_State* state);
+int lua_PhysicsVehicle_getSpeedSmoothKph(lua_State* state);
+int lua_PhysicsVehicle_getSteerdownGain(lua_State* state);
+int lua_PhysicsVehicle_getSteerdownSpeed(lua_State* state);
 int lua_PhysicsVehicle_getSteeringGain(lua_State* state);
 int lua_PhysicsVehicle_getType(lua_State* state);
 int lua_PhysicsVehicle_getWheel(lua_State* state);
@@ -23,9 +33,15 @@ int lua_PhysicsVehicle_isDynamic(lua_State* state);
 int lua_PhysicsVehicle_isEnabled(lua_State* state);
 int lua_PhysicsVehicle_isKinematic(lua_State* state);
 int lua_PhysicsVehicle_removeCollisionListener(lua_State* state);
+int lua_PhysicsVehicle_reset(lua_State* state);
+int lua_PhysicsVehicle_setBoost(lua_State* state);
+int lua_PhysicsVehicle_setBrakedown(lua_State* state);
 int lua_PhysicsVehicle_setBrakingForce(lua_State* state);
+int lua_PhysicsVehicle_setDownforce(lua_State* state);
+int lua_PhysicsVehicle_setDrivedown(lua_State* state);
 int lua_PhysicsVehicle_setDrivingForce(lua_State* state);
 int lua_PhysicsVehicle_setEnabled(lua_State* state);
+int lua_PhysicsVehicle_setSteerdown(lua_State* state);
 int lua_PhysicsVehicle_setSteeringGain(lua_State* state);
 int lua_PhysicsVehicle_update(lua_State* state);
 

+ 26 - 26
gameplay/src/lua/lua_PhysicsVehicleWheel.cpp

@@ -27,7 +27,7 @@ void luaRegister_PhysicsVehicleWheel()
         {"getNode", lua_PhysicsVehicleWheel_getNode},
         {"getRollInfluence", lua_PhysicsVehicleWheel_getRollInfluence},
         {"getShapeType", lua_PhysicsVehicleWheel_getShapeType},
-        {"getStrutConnectionPoint", lua_PhysicsVehicleWheel_getStrutConnectionPoint},
+        {"getStrutConnectionOffset", lua_PhysicsVehicleWheel_getStrutConnectionOffset},
         {"getStrutDampingCompression", lua_PhysicsVehicleWheel_getStrutDampingCompression},
         {"getStrutDampingRelaxation", lua_PhysicsVehicleWheel_getStrutDampingRelaxation},
         {"getStrutForceMax", lua_PhysicsVehicleWheel_getStrutForceMax},
@@ -40,14 +40,14 @@ void luaRegister_PhysicsVehicleWheel()
         {"getWheelRadius", lua_PhysicsVehicleWheel_getWheelRadius},
         {"isDynamic", lua_PhysicsVehicleWheel_isDynamic},
         {"isEnabled", lua_PhysicsVehicleWheel_isEnabled},
-        {"isFront", lua_PhysicsVehicleWheel_isFront},
         {"isKinematic", lua_PhysicsVehicleWheel_isKinematic},
+        {"isSteerable", lua_PhysicsVehicleWheel_isSteerable},
         {"removeCollisionListener", lua_PhysicsVehicleWheel_removeCollisionListener},
         {"setEnabled", lua_PhysicsVehicleWheel_setEnabled},
         {"setFrictionBreakout", lua_PhysicsVehicleWheel_setFrictionBreakout},
-        {"setFront", lua_PhysicsVehicleWheel_setFront},
         {"setRollInfluence", lua_PhysicsVehicleWheel_setRollInfluence},
-        {"setStrutConnectionPoint", lua_PhysicsVehicleWheel_setStrutConnectionPoint},
+        {"setSteerable", lua_PhysicsVehicleWheel_setSteerable},
+        {"setStrutConnectionOffset", lua_PhysicsVehicleWheel_setStrutConnectionOffset},
         {"setStrutDampingCompression", lua_PhysicsVehicleWheel_setStrutDampingCompression},
         {"setStrutDampingRelaxation", lua_PhysicsVehicleWheel_setStrutDampingRelaxation},
         {"setStrutForceMax", lua_PhysicsVehicleWheel_setStrutForceMax},
@@ -405,7 +405,7 @@ int lua_PhysicsVehicleWheel_getShapeType(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicleWheel_getStrutConnectionPoint(lua_State* state)
+int lua_PhysicsVehicleWheel_getStrutConnectionOffset(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -422,13 +422,13 @@ int lua_PhysicsVehicleWheel_getStrutConnectionPoint(lua_State* state)
                 ScriptUtil::LuaArray<Vector3> param1 = ScriptUtil::getObjectPointer<Vector3>(2, "Vector3", false);
 
                 PhysicsVehicleWheel* instance = getInstance(state);
-                instance->getStrutConnectionPoint(param1);
+                instance->getStrutConnectionOffset(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicleWheel_getStrutConnectionPoint - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicleWheel_getStrutConnectionOffset - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -889,7 +889,7 @@ int lua_PhysicsVehicleWheel_isEnabled(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicleWheel_isFront(lua_State* state)
+int lua_PhysicsVehicleWheel_isKinematic(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -902,7 +902,7 @@ int lua_PhysicsVehicleWheel_isFront(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 PhysicsVehicleWheel* instance = getInstance(state);
-                bool result = instance->isFront();
+                bool result = instance->isKinematic();
 
                 // Push the return value onto the stack.
                 lua_pushboolean(state, result);
@@ -911,7 +911,7 @@ int lua_PhysicsVehicleWheel_isFront(lua_State* state)
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicleWheel_isFront - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicleWheel_isKinematic - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -926,7 +926,7 @@ int lua_PhysicsVehicleWheel_isFront(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicleWheel_isKinematic(lua_State* state)
+int lua_PhysicsVehicleWheel_isSteerable(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -939,7 +939,7 @@ int lua_PhysicsVehicleWheel_isKinematic(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 PhysicsVehicleWheel* instance = getInstance(state);
-                bool result = instance->isKinematic();
+                bool result = instance->isSteerable();
 
                 // Push the return value onto the stack.
                 lua_pushboolean(state, result);
@@ -948,7 +948,7 @@ int lua_PhysicsVehicleWheel_isKinematic(lua_State* state)
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicleWheel_isKinematic - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicleWheel_isSteerable - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -1127,7 +1127,7 @@ int lua_PhysicsVehicleWheel_setFrictionBreakout(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicleWheel_setFront(lua_State* state)
+int lua_PhysicsVehicleWheel_setRollInfluence(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -1138,19 +1138,19 @@ int lua_PhysicsVehicleWheel_setFront(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TBOOLEAN)
+                lua_type(state, 2) == LUA_TNUMBER)
             {
                 // Get parameter 1 off the stack.
-                bool param1 = ScriptUtil::luaCheckBool(state, 2);
+                float param1 = (float)luaL_checknumber(state, 2);
 
                 PhysicsVehicleWheel* instance = getInstance(state);
-                instance->setFront(param1);
+                instance->setRollInfluence(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicleWheel_setFront - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicleWheel_setRollInfluence - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -1165,7 +1165,7 @@ int lua_PhysicsVehicleWheel_setFront(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicleWheel_setRollInfluence(lua_State* state)
+int lua_PhysicsVehicleWheel_setSteerable(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -1176,19 +1176,19 @@ int lua_PhysicsVehicleWheel_setRollInfluence(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER)
+                lua_type(state, 2) == LUA_TBOOLEAN)
             {
                 // Get parameter 1 off the stack.
-                float param1 = (float)luaL_checknumber(state, 2);
+                bool param1 = ScriptUtil::luaCheckBool(state, 2);
 
                 PhysicsVehicleWheel* instance = getInstance(state);
-                instance->setRollInfluence(param1);
+                instance->setSteerable(param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicleWheel_setRollInfluence - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicleWheel_setSteerable - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;
@@ -1203,7 +1203,7 @@ int lua_PhysicsVehicleWheel_setRollInfluence(lua_State* state)
     return 0;
 }
 
-int lua_PhysicsVehicleWheel_setStrutConnectionPoint(lua_State* state)
+int lua_PhysicsVehicleWheel_setStrutConnectionOffset(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -1220,13 +1220,13 @@ int lua_PhysicsVehicleWheel_setStrutConnectionPoint(lua_State* state)
                 ScriptUtil::LuaArray<Vector3> param1 = ScriptUtil::getObjectPointer<Vector3>(2, "Vector3", true);
 
                 PhysicsVehicleWheel* instance = getInstance(state);
-                instance->setStrutConnectionPoint(*param1);
+                instance->setStrutConnectionOffset(*param1);
                 
                 return 0;
             }
             else
             {
-                lua_pushstring(state, "lua_PhysicsVehicleWheel_setStrutConnectionPoint - Failed to match the given parameters to a valid function signature.");
+                lua_pushstring(state, "lua_PhysicsVehicleWheel_setStrutConnectionOffset - Failed to match the given parameters to a valid function signature.");
                 lua_error(state);
             }
             break;

+ 4 - 4
gameplay/src/lua/lua_PhysicsVehicleWheel.h

@@ -12,7 +12,7 @@ int lua_PhysicsVehicleWheel_getFrictionBreakout(lua_State* state);
 int lua_PhysicsVehicleWheel_getNode(lua_State* state);
 int lua_PhysicsVehicleWheel_getRollInfluence(lua_State* state);
 int lua_PhysicsVehicleWheel_getShapeType(lua_State* state);
-int lua_PhysicsVehicleWheel_getStrutConnectionPoint(lua_State* state);
+int lua_PhysicsVehicleWheel_getStrutConnectionOffset(lua_State* state);
 int lua_PhysicsVehicleWheel_getStrutDampingCompression(lua_State* state);
 int lua_PhysicsVehicleWheel_getStrutDampingRelaxation(lua_State* state);
 int lua_PhysicsVehicleWheel_getStrutForceMax(lua_State* state);
@@ -25,14 +25,14 @@ int lua_PhysicsVehicleWheel_getWheelDirection(lua_State* state);
 int lua_PhysicsVehicleWheel_getWheelRadius(lua_State* state);
 int lua_PhysicsVehicleWheel_isDynamic(lua_State* state);
 int lua_PhysicsVehicleWheel_isEnabled(lua_State* state);
-int lua_PhysicsVehicleWheel_isFront(lua_State* state);
 int lua_PhysicsVehicleWheel_isKinematic(lua_State* state);
+int lua_PhysicsVehicleWheel_isSteerable(lua_State* state);
 int lua_PhysicsVehicleWheel_removeCollisionListener(lua_State* state);
 int lua_PhysicsVehicleWheel_setEnabled(lua_State* state);
 int lua_PhysicsVehicleWheel_setFrictionBreakout(lua_State* state);
-int lua_PhysicsVehicleWheel_setFront(lua_State* state);
 int lua_PhysicsVehicleWheel_setRollInfluence(lua_State* state);
-int lua_PhysicsVehicleWheel_setStrutConnectionPoint(lua_State* state);
+int lua_PhysicsVehicleWheel_setSteerable(lua_State* state);
+int lua_PhysicsVehicleWheel_setStrutConnectionOffset(lua_State* state);
 int lua_PhysicsVehicleWheel_setStrutDampingCompression(lua_State* state);
 int lua_PhysicsVehicleWheel_setStrutDampingRelaxation(lua_State* state);
 int lua_PhysicsVehicleWheel_setStrutForceMax(lua_State* state);

+ 1 - 0
gameplay/src/lua/lua_all_bindings.cpp

@@ -53,6 +53,7 @@ void lua_RegisterAllBindings()
     luaRegister_Label();
     luaRegister_Layout();
     luaRegister_Light();
+    luaRegister_Logger();
     luaRegister_Material();
     luaRegister_MaterialParameter();
     luaRegister_MathUtil();

+ 1 - 0
gameplay/src/lua/lua_all_bindings.h

@@ -48,6 +48,7 @@
 #include "lua_Label.h"
 #include "lua_Layout.h"
 #include "lua_Light.h"
+#include "lua_Logger.h"
 #include "lua_Material.h"
 #include "lua_MaterialParameter.h"
 #include "lua_MathUtil.h"