ソースを参照

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

Adam Blake 13 年 前
コミット
32db40e6f1
42 ファイル変更1760 行追加232 行削除
  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. 6 0
      gameplay/CMakeLists.txt
  17. 9 6
      gameplay/android/jni/Android.mk
  18. 6 0
      gameplay/gameplay.vcxproj
  19. 18 0
      gameplay/gameplay.vcxproj.filters
  20. 36 0
      gameplay/gameplay.xcodeproj/project.pbxproj
  21. 1 1
      gameplay/src/AudioSource.cpp
  22. 7 7
      gameplay/src/Base.h
  23. 99 0
      gameplay/src/Logger.cpp
  24. 124 0
      gameplay/src/Logger.h
  25. 6 1
      gameplay/src/PhysicsVehicle.cpp
  26. 13 5
      gameplay/src/PhysicsVehicle.h
  27. 56 22
      gameplay/src/PhysicsVehicleWheel.cpp
  28. 54 14
      gameplay/src/PhysicsVehicleWheel.h
  29. 67 26
      gameplay/src/PlatformAndroid.cpp
  30. 1 0
      gameplay/src/gameplay.h
  31. 11 0
      gameplay/src/lua/lua_Global.cpp
  32. 1 0
      gameplay/src/lua/lua_Global.h
  33. 195 0
      gameplay/src/lua/lua_Logger.cpp
  34. 17 0
      gameplay/src/lua/lua_Logger.h
  35. 38 0
      gameplay/src/lua/lua_LoggerLevel.cpp
  36. 15 0
      gameplay/src/lua/lua_LoggerLevel.h
  37. 654 27
      gameplay/src/lua/lua_PhysicsVehicle.cpp
  38. 16 0
      gameplay/src/lua/lua_PhysicsVehicle.h
  39. 26 26
      gameplay/src/lua/lua_PhysicsVehicleWheel.cpp
  40. 4 4
      gameplay/src/lua/lua_PhysicsVehicleWheel.h
  41. 1 0
      gameplay/src/lua/lua_all_bindings.cpp
  42. 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/FBX SDK/2013.3/include
 - Add the FBX lib directory to the Additional Library Directories (Linker/General)
-  * Example: C:/Program Files/Autodesk/FBX/FbxSdk/2013.2/lib/vs2010/x86
-- Add "fbxsdk-2013.2-mdd.lib"(Release) to the Additional Dependencies (Linker/Input)
-  * Example: fbxsdk-2013.2-mdd.lib
+  * Example: C:/Program Files/Autodesk/FBX/FBX SDK/2013.3/lib/vs2010/x86
+- Add "fbxsdk-2013.3-mdd.lib"(Release) to the Additional Dependencies (Linker/Input)
+  * Example: fbxsdk-2013.3-mdd.lib
 - Build gameplay-encoder
 
 ### Building with FBX Support on Mac OS X using XCode 4.3.2+
@@ -43,12 +44,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

+ 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 \

+ 6 - 0
gameplay/gameplay.vcxproj

@@ -82,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" />
@@ -153,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" />
@@ -348,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" />
@@ -419,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" />

+ 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

+ 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

+ 6 - 1
gameplay/src/PhysicsVehicle.cpp

@@ -226,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();
@@ -276,7 +281,7 @@ void PhysicsVehicle::update(float elapsedTime, float steering, float braking, fl
     {
         wheel = getWheel(i);
 
-        if (wheel->isFront())
+        if (wheel->isSteerable())
         {
             _vehicle->setSteeringValue(steering * _steeringGain, i);
         }

+ 13 - 5
gameplay/src/PhysicsVehicle.h

@@ -72,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.
      *
@@ -361,6 +369,11 @@ private:
      */
     void initialize();
 
+    /**
+     * Destructor.
+     */
+    ~PhysicsVehicle();
+
     /**
      * Returns adjusted steering value.
      *
@@ -391,11 +404,6 @@ private:
      */
     void applyDownforce();
 
-    /**
-     * Destructor.
-     */
-    ~PhysicsVehicle();
-
     float _steeringGain;
     float _brakingForce;
     float _drivingForce;

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

+ 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"