Browse Source

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

Steve Grenier 13 years ago
parent
commit
678c2895be

+ 3 - 2
CHANGES.md

@@ -1,10 +1,10 @@
 ## v1.5.0
 
-- Linux support.
+- Linux x64 support tested on Ubuntu 12+.
 - CMake support for Linux makefile generation.
 - Gamepad controllers support for desktops.
 - Touch gesture support for tap, swipe and pinch.
-- Vehicle phyics support via new PhysicsVehicle adn PhysicsVehicleWheels classes.
+- Vehicle phyics support via new PhysicsVehicle and PhysicsVehicleWheel classes.
 - Adds gameplay-tests project as a test app for various engine features with initial basic tests.
 - Adds support for Scene files for wildcard identifiers.
 - Web community forums at http://www.gameplay3d.org/forums
@@ -15,6 +15,7 @@
 - Fixes Lua print logging.
 - Fixes Lua errors to be treated as runtime warnings.
 - Fixes setVertexData to pointers instead of constant data.
+- Fixed AudioSource so that it doesn't loop by default.
 
 ## v1.4.0
 

+ 7 - 0
CMakeLists.txt

@@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.6)
 project(GamePlay)
 
 set(GAMEPLAY_VERSION 1.5.0)
+set(CMAKE_C_COMPILER_INIT g++)
 
 # debug
 message( "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}" )
@@ -16,4 +17,10 @@ add_subdirectory(gameplay)
 # gameplay samples
 add_subdirectory(gameplay-samples)
 
+# gameplay samples
+add_subdirectory(gameplay-tests)
+
+# gameplay encoder (See gameplay/bin)
+#add_subdirectory(gameplay-encoder)
+
 

+ 145 - 0
gameplay-encoder/CMakeLists.txt

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

+ 37 - 22
gameplay-encoder/README.md

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

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

@@ -10,6 +10,7 @@
 #include <cmath>
 #include <cfloat>
 #include <ctime>
+#include <cstring>
 #include <iostream>
 #include <fstream>
 #include <string>
@@ -24,6 +25,7 @@
 
 // Collada includes
 #include <dae.h>
+#include <dom.h>
 #include <dae/daeSIDResolver.h>
 #include <dae/domAny.h>
 #include <dom/domCOLLADA.h>

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

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

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

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

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

@@ -264,7 +264,7 @@ void DAESceneEncoder::write(const std::string& filepath, const EncoderArguments&
     // Load the collada document
     _collada = new DAE();
     begin();
-    _dom = _collada->open(filepath);
+    _dom = (domCOLLADA*)_collada->open(filepath);
     end("Open file");
     if (!_dom)
     {
@@ -889,7 +889,7 @@ void DAESceneEncoder::calcTransform(domNode* domNode, Matrix& dstTransform)
     for (size_t i = 0; i < childCount; ++i)
     {
         daeElementRef childElement = children[i];
-        switch (childElement->getElementType())
+        switch (childElement->typeID())
         {
             case COLLADA_TYPE::TRANSLATE:
             {
@@ -1286,7 +1286,7 @@ void DAESceneEncoder::loadSkeleton(domNode* rootNode, MeshSkin* skin)
         domNode* topLevelParent = rootNode;
         while (
             topLevelParent->getParent() &&
-            topLevelParent->getParent()->getElementType() == COLLADA_TYPE::NODE &&
+            topLevelParent->getParent()->typeID() == COLLADA_TYPE::NODE &&
             _gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID()) == NULL)
         {
             topLevelParent = (domNode*)topLevelParent->getParent();
@@ -1295,7 +1295,7 @@ void DAESceneEncoder::loadSkeleton(domNode* rootNode, MeshSkin* skin)
         // Is the parent of this node loaded yet?
         Node* parentNode = NULL;
         if (topLevelParent->getParent() &&
-            topLevelParent->getParent()->getElementType() == COLLADA_TYPE::NODE &&
+            topLevelParent->getParent()->typeID() == COLLADA_TYPE::NODE &&
             _gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID()) != NULL)
         {
             parentNode = (Node*)_gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID());
@@ -1372,7 +1372,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
             {
                 daeSIDResolver resolver(source->getDocument()->getDomRoot(), i->c_str());
                 daeElement* element = resolver.getElement();
-                if (element && element->getElementType() == COLLADA_TYPE::NODE)
+                if (element && element->typeID() == COLLADA_TYPE::NODE)
                 {
                     domNodeRef node = daeSafeCast<domNode>(element);
                     const char* nodeId = node->getId();

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

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

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

@@ -310,10 +310,6 @@ void FBXSceneEncoder::loadAnimationChannels(FbxAnimLayer* animLayer, FbxNode* fb
 {
     const char* name = fbxNode->GetName();
     Node* node = _gamePlayFile.getNode(name);
-    if (node)
-    {
-        targetId = &node->getId();
-    }
     
     // Determine which properties are animated on this node
     // Find the transform at each key frame
@@ -1713,4 +1709,4 @@ bool isGroupAnimationPossible(FbxMesh* fbxMesh)
     return false;
 }
 
-#endif
+#endif

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

@@ -216,4 +216,4 @@ private:
 };
 
 #endif
-#endif
+#endif

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

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

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

@@ -67,7 +67,7 @@ bool GPBFile::saveBinary(const std::string& filepath)
     size_t n = 0;
 
     // identifier
-    char identifier[] = { '«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n' };
+    char identifier[] = { '�', 'G', 'P', 'B', '�', '\r', '\n', '\x1A', '\n' };
     n = fwrite(identifier, 1, sizeof(identifier), _file);
     if (n != sizeof(identifier))
     {
@@ -310,7 +310,6 @@ void GPBFile::adjust()
         }
     }
 
-    LOG(1, "Computing bounding volumes.\n");
     for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
     {
         computeBounds(*i);

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

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

+ 54 - 36
gameplay-newproject.sh

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

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

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

+ 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

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

+ 1 - 1
gameplay/src/Container.cpp

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

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

+ 6 - 6
gameplay/src/PlatformAndroid.cpp

@@ -693,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;
@@ -740,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;
@@ -748,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);
 
@@ -770,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;

+ 22 - 4
gameplay/src/PlatformMacOSX.mm

@@ -7,6 +7,8 @@
 #include "Form.h"
 #include "ScriptController.h"
 #include <unistd.h>
+#include <IOKit/hid/IOHIDElement.h>
+#include <IOKit/hid/IOHIDDevice.h>
 #include <IOKit/hid/IOHIDLib.h>
 #import <Cocoa/Cocoa.h>
 #import <QuartzCore/CVDisplayLink.h>
@@ -360,7 +362,8 @@ double getMachTimeInMilliseconds()
 }
 - (NSNumber*)locationID
 {
-    return (NSNumber*)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDLocationIDKey));
+    NSNumber *n = (NSNumber*)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDLocationIDKey));
+    return [NSNumber numberWithUnsignedInt:[n unsignedIntValue]];
 }
 
 - (void)initializeGamepadElements
@@ -1278,9 +1281,17 @@ Platform::Platform(Game* game)
     IOHIDManagerRegisterDeviceMatchingCallback(__hidManagerRef, hidDeviceDiscoveredCallback, NULL);
     IOHIDManagerRegisterDeviceRemovalCallback(__hidManagerRef, hidDeviceRemovalCallback, NULL);
     
-    CFDictionaryRef matchingCFDictRef = IOHIDCreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
-    if (matchingCFDictRef) IOHIDManagerSetDeviceMatching(__hidManagerRef, matchingCFDictRef);
-    CFRelease(matchingCFDictRef);
+    CFDictionaryRef matchingJoystickCFDictRef = IOHIDCreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
+    CFDictionaryRef matchingGamepadCFDictRef = IOHIDCreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
+    CFMutableArrayRef matchingDicts = CFArrayCreateMutable(kCFAllocatorDefault, 2, NULL);
+    CFArrayAppendValue(matchingDicts, matchingJoystickCFDictRef);
+    CFArrayAppendValue(matchingDicts, matchingGamepadCFDictRef);
+
+    if (matchingDicts) IOHIDManagerSetDeviceMatchingMultiple(__hidManagerRef, matchingDicts);
+    
+    CFRelease(matchingJoystickCFDictRef);
+    CFRelease(matchingGamepadCFDictRef);
+    CFRelease(matchingDicts);
     
     IOHIDManagerScheduleWithRunLoop(__hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
     IOReturn kr = IOHIDManagerOpen(__hidManagerRef, kIOHIDOptionsTypeNone);
@@ -1335,6 +1346,13 @@ int Platform::enterMessagePump()
 
             // Read fullscreen state.
             __fullscreen = config->getBool("fullscreen");
+            
+            // If fullscreen is specified, and width is not, interpret this
+            // as meaning, "use the current resolution".
+            if (__fullscreen && width == 0){
+			    __width = [[NSScreen mainScreen] frame].size.width;
+                __height = [[NSScreen mainScreen] frame].size.height;
+            }
         }
     }
 

+ 2 - 1
gameplay/src/PlatformQNX.cpp

@@ -1077,7 +1077,8 @@ int Platform::enterMessagePump()
                         break;
                     case NAVIGATOR_WINDOW_THUMBNAIL:
                     case NAVIGATOR_WINDOW_INVISIBLE:
-                        _game->pause();
+                        if (!suspended)
+                            _game->pause();
                         suspended = true;
                         break;
                     }

+ 7 - 0
gameplay/src/PlatformWin32.cpp

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

+ 44 - 13
gameplay/src/TextBox.cpp

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

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