Преглед изворни кода

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

Conflicts:
	gameplay-samples/CMakeLists.txt
	gameplay-tests/CMakeLists.txt
Karim Ahmed пре 13 година
родитељ
комит
1740b801f4
40 измењених фајлова са 631 додато и 131 уклоњено
  1. 15 1
      gameplay-api/header.html
  2. 4 0
      gameplay-encoder/CMakeLists.txt
  3. 17 36
      gameplay.doxyfile
  4. 6 0
      gameplay/src/Animation.cpp
  5. 0 1
      gameplay/src/AnimationClip.cpp
  6. 18 1
      gameplay/src/AnimationTarget.cpp
  7. 1 0
      gameplay/src/Base.h
  8. 1 1
      gameplay/src/Button.h
  9. 1 1
      gameplay/src/CheckBox.h
  10. 2 2
      gameplay/src/Container.h
  11. 1 1
      gameplay/src/Control.h
  12. 15 1
      gameplay/src/Game.h
  13. 10 0
      gameplay/src/Game.inl
  14. 1 1
      gameplay/src/Joystick.h
  15. 1 1
      gameplay/src/Layout.h
  16. 3 0
      gameplay/src/MaterialParameter.cpp
  17. 66 0
      gameplay/src/MeshBatch.cpp
  18. 25 1
      gameplay/src/MeshBatch.h
  19. 1 56
      gameplay/src/MeshBatch.inl
  20. 12 0
      gameplay/src/Platform.h
  21. 47 12
      gameplay/src/PlatformAndroid.cpp
  22. 21 0
      gameplay/src/PlatformBlackBerry.cpp
  23. 25 1
      gameplay/src/PlatformLinux.cpp
  24. 22 0
      gameplay/src/PlatformMacOSX.mm
  25. 29 0
      gameplay/src/PlatformWindows.cpp
  26. 92 3
      gameplay/src/PlatformiOS.mm
  27. 1 1
      gameplay/src/RadioButton.h
  28. 8 0
      gameplay/src/RenderState.cpp
  29. 1 1
      gameplay/src/RenderState.h
  30. 1 1
      gameplay/src/ScriptController.h
  31. 1 1
      gameplay/src/Slider.h
  32. 1 1
      gameplay/src/TextBox.h
  33. 73 0
      gameplay/src/lua/lua_Game.cpp
  34. 2 0
      gameplay/src/lua/lua_Game.h
  35. 1 0
      gameplay/src/lua/lua_Gamepad.cpp
  36. 1 1
      gameplay/src/lua/lua_Global.cpp
  37. 98 0
      gameplay/src/lua/lua_MeshBatch.cpp
  38. 1 0
      gameplay/src/lua/lua_MeshBatch.h
  39. 5 5
      gameplay/src/lua/lua_RenderStateBlend.cpp
  40. 1 0
      gameplay/src/lua/lua_Terrain.cpp

+ 15 - 1
gameplay-api/header.html

@@ -7,6 +7,7 @@
 
 <link href="tabs.css" rel="stylesheet" type="text/css"/>
 <link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="custom.css" rel="stylesheet" type="text/css" />
 
 <link href="search/search.css" rel="stylesheet" type="text/css"/>
 <script type="text/javascript" src="jquery.js"></script>
@@ -17,4 +18,17 @@
 
 </head>
 <body>
-<div id="top"><!-- do not remove this div! -->
+<div id="top"><!-- do not remove this div! -->
+<table class="header" border="0">
+<tbody>
+<tr>
+<td id="logo"><a href="http://gameplay3d.org/"><img src="images/logo.png" alt="gameplay" border="0" height="64px"/></a></td>
+<td width="100%"/>
+<td><a href="http://gameplay3d.org/"><span class="button">overview</span></a></td><td width="12px"/>
+<td><a href="https://github.com/blackberry/GamePlay/wiki"><span class="button">wiki</span></a></td><td width="12px"/>
+<td><a href="http://blackberry.github.com/GamePlay/api/index.html"><span class="button">api&nbsp;reference</span></a></td><td width="12px"/>
+<td><a href="http://www.gameplay3d.org/forums"><span class="button">forums</span></a></td>
+<td><a href="https://github.com/blackberry/GamePlay"><span class="button">download</span></a></td>
+</tr>
+</tbody>
+</table>

+ 4 - 0
gameplay-encoder/CMakeLists.txt

@@ -77,6 +77,8 @@ set(APP_SRC
 	src/GPBFile.h
 	src/Heightmap.cpp
 	src/Heightmap.h
+	src/Image.cpp
+	src/Image.h
 	src/Light.cpp
 	src/Light.h
 	src/main.cpp
@@ -98,6 +100,8 @@ set(APP_SRC
 	src/Model.h
 	src/Node.cpp
 	src/Node.h
+	src/NormalMapGenerator.cpp
+	src/NormalMapGenerator.h
 	src/Object.cpp
 	src/Object.h
 	src/Quaternion.cpp

+ 17 - 36
gameplay.doxyfile

@@ -1,4 +1,4 @@
-# Doxyfile 1.8.0
+# Doxyfile 1.7.6.1
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project
@@ -250,15 +250,6 @@ OPTIMIZE_OUTPUT_VHDL   = NO
 
 EXTENSION_MAPPING      = 
 
-# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all 
-# comments according to the Markdown format, which allows for more readable 
-# documentation. See http://daringfireball.net/projects/markdown/ for details. 
-# The output of markdown processing is further processed by doxygen, so you 
-# can mix doxygen, HTML, and XML commands with Markdown formatting. 
-# Disable only in case of backward compatibilities issues.
-
-MARKDOWN_SUPPORT       = YES
-
 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
 # to include (a tag file for) the STL sources as input, then you should 
 # set this tag to YES in order to let doxygen match functions declarations and 
@@ -372,11 +363,6 @@ EXTRACT_ALL            = NO
 
 EXTRACT_PRIVATE        = NO
 
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
-# scope will be included in the documentation.
-
-EXTRACT_PACKAGE        = NO
-
 # If the EXTRACT_STATIC tag is set to YES all static members of a file 
 # will be included in the documentation.
 
@@ -1182,7 +1168,7 @@ FORMULA_TRANSPARENT    = YES
 # (see http://www.mathjax.org) which uses client side Javascript for the 
 # rendering instead of using prerendered bitmaps. Use this if you do not 
 # have LaTeX installed or if you want to formulas look prettier in the HTML 
-# output. When enabled you may also need to install MathJax separately and 
+# output. When enabled you also need to install MathJax separately and 
 # configure the path to it using the MATHJAX_RELPATH option.
 
 USE_MATHJAX            = NO
@@ -1191,10 +1177,10 @@ USE_MATHJAX            = NO
 # HTML output directory using the MATHJAX_RELPATH option. The destination 
 # directory should contain the MathJax.js script. For instance, if the mathjax 
 # directory is located at the same level as the HTML output directory, then 
-# MATHJAX_RELPATH should be ../mathjax. The default value points to 
-# the MathJax Content Delivery Network so you can quickly see the result without 
-# installing MathJax.  However, it is strongly recommended to install a local 
-# copy of MathJax from http://www.mathjax.org before deployment.
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the 
+# mathjax.org site, so you can quickly see the result without installing 
+# MathJax, but it is strongly recommended to install a local copy of MathJax 
+# before deployment.
 
 MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
 
@@ -1542,16 +1528,20 @@ SKIP_FUNCTION_MACROS   = YES
 # Configuration::additions related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles. For each 
-# tag file the location of the external documentation should be added. The 
-# format of a tag file without this location is as follows: 
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
 #   TAGFILES = file1 file2 ... 
 # Adding location for the tag files is done as follows: 
 #   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths 
-# or URLs. Note that each tag file must have a unique name (where the name does 
-# NOT include the path). If a tag file is not located in the directory in which 
-# doxygen is run, you must also specify the path to the tagfile here.
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links. 
+# Note that each tag file must have a unique name 
+# (where the name does NOT include the path) 
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
 
 TAGFILES               = 
 
@@ -1664,15 +1654,6 @@ GROUP_GRAPHS           = YES
 
 UML_LOOK               = NO
 
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside 
-# the class node. If there are many fields or methods and many nodes the 
-# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS 
-# threshold limits the number of items for each type to make the size more 
-# managable. Set this to 0 for no limit. Note that the threshold may be 
-# exceeded by 50% before the limit is enforced.
-
-UML_LIMIT_NUM_FIELDS   = 10
-
 # If set to YES, the inheritance and collaboration graphs will show the 
 # relations between templates and their instances.
 

+ 6 - 0
gameplay/src/Animation.cpp

@@ -453,6 +453,12 @@ Animation* Animation::clone(Channel* channel, AnimationTarget* target)
     GP_ASSERT(animation->getRefCount() == 1);
 
     // Clone the clips
+    
+    if (_defaultClip)
+    {
+        animation->_defaultClip = _defaultClip->clone(animation);
+    }
+    
     if (_clips)
     {
         for (std::vector<AnimationClip*>::iterator it = _clips->begin(); it != _clips->end(); ++it)

+ 0 - 1
gameplay/src/AnimationClip.cpp

@@ -598,7 +598,6 @@ AnimationClip* AnimationClip::clone(Animation* animation) const
 {
     // Don't clone the elapsed time, listeners or crossfade information.
     AnimationClip* newClip = new AnimationClip(getId(), animation, getStartTime(), getEndTime());
-    newClip->setRepeatCount(getRepeatCount());
     newClip->setSpeed(getSpeed());
     newClip->setRepeatCount(getRepeatCount());
     newClip->setBlendWeight(getBlendWeight());

+ 18 - 1
gameplay/src/AnimationTarget.cpp

@@ -4,6 +4,8 @@
 #include "Game.h"
 #include "Node.h"
 
+#define ANIMATION_TARGET_INDEFINITE_STR "INDEFINITE"
+
 namespace gameplay
 {
 
@@ -261,6 +263,21 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
         animation = createAnimation(id, propertyId, keyCount, keyTimes, keyValues, (Curve::InterpolationType) curve);
     }
 
+    const char* repeat = animationProperties->getString("repeatCount");
+    if (repeat)
+    {
+        if (strcmp(repeat, ANIMATION_TARGET_INDEFINITE_STR) == 0)
+        {
+            animation->getClip()->setRepeatCount(AnimationClip::REPEAT_INDEFINITE);
+        }
+        else
+        {
+            float value;
+            sscanf(repeat, "%f", &value);
+            animation->getClip()->setRepeatCount(value);
+        }
+    }
+    
     SAFE_DELETE_ARRAY(keyOut);
     SAFE_DELETE_ARRAY(keyIn);
     SAFE_DELETE_ARRAY(keyValues);
@@ -277,7 +294,7 @@ Animation* AnimationTarget::createAnimation(const char* id, Properties* animatio
         }
         animation->createClips(animationProperties, (unsigned int) frameCount);
     }
-
+    
     return animation;
 }
 

+ 1 - 0
gameplay/src/Base.h

@@ -27,6 +27,7 @@
 #include <limits>
 #include <functional>
 #include <bitset>
+#include <typeinfo>
 #include "Logger.h"
 
 // Bring common functions from C into global namespace

+ 1 - 1
gameplay/src/Button.h

@@ -77,7 +77,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by the control.
      *

+ 1 - 1
gameplay/src/CheckBox.h

@@ -123,7 +123,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by the control.
      *

+ 2 - 2
gameplay/src/Container.h

@@ -259,7 +259,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by a control within this container.
      *
@@ -340,7 +340,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by scrolling within this container.
      *

+ 1 - 1
gameplay/src/Control.h

@@ -805,7 +805,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by this control.
      *

+ 15 - 1
gameplay/src/Game.h

@@ -295,7 +295,7 @@ public:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @see Touch::TouchEvent
      */
@@ -464,6 +464,20 @@ public:
      */
     inline Gamepad* getGamepad(unsigned int index, bool preferPhysical = true) const;
 
+    /**
+	 * Sets whether multi-sampling is to be enabled/disabled. Default is disabled.
+	 *
+	 * @param enabled true sets multi-sampling to be enabled, false to be disabled.
+	 */
+	inline void setMultiSampling(bool enabled);
+
+	/*
+	 * Is multi-sampling enabled.
+	 *
+	 * @return true if multi-sampling is enabled.
+	 */
+	inline bool isMultiSampling() const;
+
     /**
      * Sets multi-touch is to be enabled/disabled. Default is disabled.
      *

+ 10 - 0
gameplay/src/Game.inl

@@ -96,6 +96,16 @@ inline bool Game::isCursorVisible()
     return Platform::isCursorVisible();
 }
 
+inline void Game::setMultiSampling(bool enabled)
+{
+    Platform::setMultiSampling(enabled);
+}
+
+inline bool Game::isMultiSampling() const
+{
+    return Platform::isMultiSampling();
+}
+
 inline void Game::setMultiTouch(bool enabled)
 {
     Platform::setMultiTouch(enabled);

+ 1 - 1
gameplay/src/Joystick.h

@@ -153,7 +153,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by the control.
      *

+ 1 - 1
gameplay/src/Layout.h

@@ -80,7 +80,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @see Touch::TouchEvent
      */

+ 3 - 0
gameplay/src/MaterialParameter.cpp

@@ -663,6 +663,9 @@ void MaterialParameter::cloneInto(MaterialParameter* materialParameter) const
         GP_ERROR("Unsupported material parameter type(%d).", _type);
         break;
     }
+    
+    NodeCloneContext context;
+    this->AnimationTarget::cloneInto(materialParameter, context);
 }
 
 }

+ 66 - 0
gameplay/src/MeshBatch.cpp

@@ -1,5 +1,6 @@
 #include "Base.h"
 #include "MeshBatch.h"
+#include "Material.h"
 
 namespace gameplay
 {
@@ -42,6 +43,66 @@ MeshBatch* MeshBatch::create(const VertexFormat& vertexFormat, Mesh::PrimitiveTy
     return batch;
 }
 
+void MeshBatch::add(void* vertices, size_t size, unsigned int vertexCount, unsigned short* indices, unsigned int indexCount)
+{
+    GP_ASSERT(vertices);
+    
+    unsigned int newVertexCount = _vertexCount + vertexCount;
+    unsigned int newIndexCount = _indexCount + indexCount;
+    if (_primitiveType == Mesh::TRIANGLE_STRIP && _vertexCount > 0)
+        newIndexCount += 2; // need an extra 2 indices for connecting strips with degenerate triangles
+    
+    // Do we need to grow the batch?
+    while (newVertexCount > _vertexCapacity || (_indexed && newIndexCount > _indexCapacity))
+    {
+        if (_growSize == 0)
+            return; // growing disabled, just clip batch
+        if (!resize(_capacity + _growSize))
+            return; // failed to grow
+    }
+    
+    // Copy vertex data.
+    GP_ASSERT(_verticesPtr);
+    unsigned int vBytes = vertexCount * _vertexFormat.getVertexSize();
+    memcpy(_verticesPtr, vertices, vBytes);
+    
+    // Copy index data.
+    if (_indexed)
+    {
+        GP_ASSERT(indices);
+        GP_ASSERT(_indicesPtr);
+
+        if (_vertexCount == 0)
+        {
+            // Simply copy values directly into the start of the index array.
+            memcpy(_indicesPtr, indices, indexCount * sizeof(unsigned short));
+        }
+        else
+        {
+            if (_primitiveType == Mesh::TRIANGLE_STRIP)
+            {
+                // Create a degenerate triangle to connect separate triangle strips
+                // by duplicating the previous and next vertices.
+                _indicesPtr[0] = *(_indicesPtr-1);
+                _indicesPtr[1] = _vertexCount;
+                _indicesPtr += 2;
+            }
+            
+            // Loop through all indices and insert them, with their values offset by
+            // 'vertexCount' so that they are relative to the first newly inserted vertex.
+            for (unsigned int i = 0; i < indexCount; ++i)
+            {
+                _indicesPtr[i] = indices[i] + _vertexCount;
+            }
+        }
+        _indicesPtr += indexCount;
+        _indexCount = newIndexCount;
+    }
+    
+    _verticesPtr += vBytes;
+    _vertexCount = newVertexCount;
+}
+
 void MeshBatch::updateVertexAttributeBinding()
 {
     GP_ASSERT(_material);
@@ -155,6 +216,11 @@ bool MeshBatch::resize(unsigned int capacity)
 
     return true;
 }
+
+void MeshBatch::add(float* vertices, unsigned int vertexCount, unsigned short* indices, unsigned int indexCount)
+{
+    add(vertices, sizeof(float), vertexCount, indices, indexCount);
+}
     
 void MeshBatch::start()
 {

+ 25 - 1
gameplay/src/MeshBatch.h

@@ -2,11 +2,12 @@
 #define MESHBATCH_H_
 
 #include "Mesh.h"
-#include "Material.h"
 
 namespace gameplay
 {
 
+class Material;
+
 /**
  * Defines a class for rendering multiple mesh into a single draw call on the graphics device.
  */
@@ -92,6 +93,27 @@ public:
     template <class T>
     void add(T* vertices, unsigned int vertexCount, unsigned short* indices = NULL, unsigned int indexCount = 0);
 
+    /**
+     * Adds a group of primitives to the batch.
+     *
+     * The vertex list passed in should be a pointer of floats where every X floats represent a
+     * single vertex (e.g. {x,y,z,u,v}).
+     *
+     * If the batch was created with 'indexed' set to true, then valid index data should be
+     * passed in this method. However, if 'indexed' was set to false, the indices and indexCount
+     * parameters can be omitted since only vertex data will be used.
+     *
+     * If the batch created to draw triangle strips, this method assumes that separate calls to
+     * add specify separate triangle strips. In this case, this method will automatically stitch
+     * separate triangle strips together using degenerate (zero-area) triangles.
+     *
+     * @param vertices Array of vertices.
+     * @param vertexCount Number of vertices.
+     * @param indices Array of indices into the vertex array (should be NULL for non-indexed batches).
+     * @param indexCount Number of indices (should be zero for non-indexed batches).
+     */
+    void add(float* vertices, unsigned int vertexCount, unsigned short* indices = NULL, unsigned int indexCount = 0);
+
     /**
      * Starts batching.
      *
@@ -131,6 +153,8 @@ private:
      */
     MeshBatch& operator=(const MeshBatch&);
 
+    void add(void* vertices, size_t size, unsigned int vertexCount, unsigned short* indices, unsigned int indexCount);
+
     void updateVertexAttributeBinding();
 
     bool resize(unsigned int capacity);

+ 1 - 56
gameplay/src/MeshBatch.inl

@@ -11,63 +11,8 @@ Material* MeshBatch::getMaterial() const
 template <class T>
 void MeshBatch::add(T* vertices, unsigned int vertexCount, unsigned short* indices, unsigned int indexCount)
 {
-    GP_ASSERT(vertices);
     GP_ASSERT(sizeof(T) == _vertexFormat.getVertexSize());
-    
-    unsigned int newVertexCount = _vertexCount + vertexCount;
-    unsigned int newIndexCount = _indexCount + indexCount;
-    if (_primitiveType == Mesh::TRIANGLE_STRIP && _vertexCount > 0)
-        newIndexCount += 2; // need an extra 2 indices for connecting strips with degenerate triangles
-    
-    // Do we need to grow the batch?
-    while (newVertexCount > _vertexCapacity || (_indexed && newIndexCount > _indexCapacity))
-    {
-        if (_growSize == 0)
-            return; // growing disabled, just clip batch
-        if (!resize(_capacity + _growSize))
-            return; // failed to grow
-    }
-    
-    // Copy vertex data.
-    GP_ASSERT(_verticesPtr);
-    unsigned int vBytes = vertexCount * _vertexFormat.getVertexSize();
-    memcpy(_verticesPtr, vertices, vBytes);
-    
-    // Copy index data.
-    if (_indexed)
-    {
-        GP_ASSERT(indices);
-        GP_ASSERT(_indicesPtr);
-
-        if (_vertexCount == 0)
-        {
-            // Simply copy values directly into the start of the index array.
-            memcpy(_indicesPtr, indices, indexCount * sizeof(unsigned short));
-        }
-        else
-        {
-            if (_primitiveType == Mesh::TRIANGLE_STRIP)
-            {
-                // Create a degenerate triangle to connect separate triangle strips
-                // by duplicating the previous and next vertices.
-                _indicesPtr[0] = *(_indicesPtr-1);
-                _indicesPtr[1] = _vertexCount;
-                _indicesPtr += 2;
-            }
-            
-            // Loop through all indices and insert them, with their values offset by
-            // 'vertexCount' so that they are relative to the first newly inserted vertex.
-            for (unsigned int i = 0; i < indexCount; ++i)
-            {
-                _indicesPtr[i] = indices[i] + _vertexCount;
-            }
-        }
-        _indicesPtr += indexCount;
-        _indexCount = newIndexCount;
-    }
-    
-    _verticesPtr += vBytes;
-    _vertexCount = newVertexCount;
+    add(vertices, sizeof(T), vertexCount, indices, indexCount);
 }
 
 }

+ 12 - 0
gameplay/src/Platform.h

@@ -127,6 +127,18 @@ private:
      */
     static void sleep(long ms);
 
+    /**
+     * Set if multi-sampling is enabled on the platform.
+     *
+     * @param enabled true sets multi-sampling to be enabled, false to be disabled.
+     */
+    static void setMultiSampling(bool enabled);
+
+   /**
+    * Is multi-sampling mode enabled.
+    */
+    static bool isMultiSampling();
+
     /**
      * Set if multi-touch is enabled on the platform.
      *

+ 47 - 12
gameplay/src/PlatformAndroid.cpp

@@ -32,6 +32,7 @@ static ASensorEventQueue* __sensorEventQueue;
 static ASensorEvent __sensorEvent;
 static const ASensor* __accelerometerSensor;
 static int __orientationAngle = 90;
+static bool __multiSampling = false;
 static bool __multiTouch = false;
 static int __primaryTouchId = -1;
 static bool __displayKeyboard = false;
@@ -176,6 +177,7 @@ static bool initEGL()
         EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
         EGL_NONE
     };
+    __multiSampling = samples > 0;
     
     EGLint eglConfigCount;
     const EGLint eglContextAttrs[] =
@@ -237,6 +239,9 @@ static bool initEGL()
                         break;
                     }
                 }
+
+                __multiSampling = sampleCount > 0;
+
                 if (validConfig)
                     break;
             }
@@ -974,22 +979,35 @@ int Platform::enterMessagePump()
     }
     GP_ASSERT(env);
 
-    // Get the package name for this app from Java.
-    jclass clazz = env->GetObjectClass(activity->clazz);
-    jmethodID methodID = env->GetMethodID(clazz, "getPackageName", "()Ljava/lang/String;");
-    jobject result = env->CallObjectMethod(activity->clazz, methodID);
-    
-    const char* packageName;
+    /* Get external files directory on Android; this will result in a directory where all app files
+     * should be stored, like /mnt/sdcard/android/<package-name>/files/
+     */
     jboolean isCopy;
-    packageName = env->GetStringUTFChars((jstring)result, &isCopy);
-    jvm->DetachCurrentThread();
+
+    jclass clazz = env->GetObjectClass(activity->clazz);
+    jmethodID methodGetExternalStorage = env->GetMethodID(clazz, "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
+
+    jclass clazzFile = env->FindClass("java/io/File");
+    jmethodID methodGetPath = env->GetMethodID(clazzFile, "getPath", "()Ljava/lang/String;");
+
+    // Now has java.io.File object pointing to directory
+    jobject objectFile  = env->CallObjectMethod(activity->clazz, methodGetExternalStorage, NULL);
     
+    // Now has String object containing path to directory
+    jstring stringExternalPath = static_cast<jstring>(env->CallObjectMethod(objectFile, methodGetPath));
+    const char* externalPath = env->GetStringUTFChars(stringExternalPath, &isCopy);
+
     // Set the default path to store the resources.
-    std::string assetsPath = "/mnt/sdcard/android/data/";
-    assetsPath += packageName;
-    assetsPath += "/";
+    std::string assetsPath(externalPath);
+    if (externalPath[strlen(externalPath)-1] != '/')
+        assetsPath += "/";
+
     FileSystem::setResourcePath(assetsPath.c_str());    
-        
+
+    // Release string data
+    env->ReleaseStringUTFChars(stringExternalPath, externalPath);
+    jvm->DetachCurrentThread();
+    
     // Get the asset manager to get the resources from the .apk file.
     __assetManager = activity->assetManager; 
     
@@ -1132,6 +1150,23 @@ void Platform::sleep(long ms)
     usleep(ms * 1000);
 }
 
+void Platform::setMultiSampling(bool enabled)
+{
+    if (enabled == __multiSampling)
+    {
+        return;
+    }
+
+    //todo
+
+    __multiSampling = enabled;
+}
+
+bool Platform::isMultiSampling()
+{
+    return __multiSampling;
+}
+
 void Platform::setMultiTouch(bool enabled)
 {
     __multiTouch = enabled;

+ 21 - 0
gameplay/src/PlatformBlackBerry.cpp

@@ -41,6 +41,7 @@ static EGLSurface __eglSurface = EGL_NO_SURFACE;
 static EGLConfig __eglConfig = 0;
 static int __orientationAngle;
 static bool __multiTouch = false;
+static bool __multiSampling = false;
 static float __pitch;
 static float __roll;
 static const char* __glExtensions;
@@ -745,6 +746,7 @@ Platform* Platform::create(Game* game, void* attachToWindow)
         EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
         EGL_NONE
     };
+    __multiSampling = samples > 0;
 
     const EGLint eglContextAttrs[] =
     {
@@ -929,6 +931,8 @@ Platform* Platform::create(Game* game, void* attachToWindow)
             }
         }
 
+        __multiSampling = samples > 0;
+
         if (!success)
         {
             checkErrorEGL("eglChooseConfig");
@@ -1400,6 +1404,23 @@ void Platform::sleep(long ms)
     usleep(ms * 1000);
 }
 
+void Platform::setMultiSampling(bool enabled)
+{
+    if (enabled == __multiSampling)
+    {
+        return;
+    }
+
+    //todo
+
+    __multiSampling = enabled;
+}
+
+bool Platform::isMultiSampling()
+{
+    return __multiSampling;
+}
+
 void Platform::setMultiTouch(bool enabled)
 {
     __multiTouch = enabled;

+ 25 - 1
gameplay/src/PlatformLinux.cpp

@@ -27,6 +27,7 @@ static float __roll;
 static bool __mouseCaptured = false;
 static float __mouseCapturePointX = 0;
 static float __mouseCapturePointY = 0;
+static bool __multiSampling = false;
 static bool __cursorVisible = true;
 static Display* __display;
 static Window   __window;
@@ -513,7 +514,7 @@ Platform* Platform::create(Game* game, void* attachToWindow)
      
     // Get the window configuration values
     const char *title = NULL;
-    int __x = 0, __y = 0, __width = 1280, __height = 800;
+    int __x = 0, __y = 0, __width = 1280, __height = 800, __samples = 0;
     bool fullscreen = false;
     if (game->getConfig())
     {
@@ -528,6 +529,7 @@ Platform* Platform::create(Game* game, void* attachToWindow)
             int y = config->getInt("y");
             int width = config->getInt("width");
             int height = config->getInt("height");
+            int samples = config->getInt("samples");
             fullscreen = config->getBool("fullscreen");
 
             if (fullscreen && width == 0 && height == 0)
@@ -541,6 +543,7 @@ Platform* Platform::create(Game* game, void* attachToWindow)
             if (y != 0) __y = y;
             if (width != 0) __width = width;
             if (height != 0) __height = height;
+            if (samples != 0) __samples = samples;
         }
     }
 
@@ -578,8 +581,12 @@ Platform* Platform::create(Game* game, void* attachToWindow)
         GLX_GREEN_SIZE,     8,
         GLX_BLUE_SIZE,      8,
         GLX_DOUBLEBUFFER,   True,
+        GLX_SAMPLE_BUFFERS, __samples > 0 ? 1 : 0,
+        GLX_SAMPLES,        __samples,
         0
     };
+    __multiSampling = __samples > 0;
+
     GLXFBConfig* configs;
     int configCount = 0;
     configs = glXChooseFBConfig(__display, DefaultScreen(__display), configAttribs, &configCount);
@@ -995,6 +1002,23 @@ void Platform::sleep(long ms)
     usleep(ms * 1000);
 }
 
+void Platform::setMultiSampling(bool enabled)
+{
+    if (enabled == __multiSampling)
+    {
+        return;
+    }
+
+    //todo
+
+    __multiSampling = enabled;
+}
+
+bool Platform::isMultiSampling()
+{
+    return __multiSampling;
+}
+
 void Platform::setMultiTouch(bool enabled)
 {
     // not supported

+ 22 - 0
gameplay/src/PlatformMacOSX.mm

@@ -50,6 +50,7 @@ static void* __attachToWindow = NULL;
 static bool __mouseCaptured = false;
 static bool __mouseCapturedFirstPass = false;
 static CGPoint __mouseCapturePoint;
+static bool __multiSampling = false;
 static bool __cursorVisible = true;
 static View* __view = NULL;
 
@@ -770,6 +771,8 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
     };
     NSOpenGLPixelFormatAttribute* attrs = __fullscreen ? fullscreenAttrs : windowedAttrs;
     
+    __multiSampling = samples > 0;
+
     // Try to choose a supported pixel format
     NSOpenGLPixelFormat* pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
     if (!pf)
@@ -787,6 +790,8 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
                 break;
             }
         }
+
+        __multiSampling = samples > 0;
         
         if (!valid)
         {
@@ -1647,6 +1652,23 @@ void Platform::sleep(long ms)
     usleep(ms * 1000);
 }
 
+void Platform::setMultiSampling(bool enabled)
+{
+    if (enabled == __multiSampling)
+    {
+        return;
+    }
+
+    //todo
+
+    __multiSampling = enabled;
+}
+
+bool Platform::isMultiSampling()
+{
+    return __multiSampling;
+}
+
 void Platform::setMultiTouch(bool enabled)
 {
 }

+ 29 - 0
gameplay/src/PlatformWindows.cpp

@@ -36,6 +36,7 @@ static HDC __hdc = 0;
 static HGLRC __hrc = 0;
 static bool __mouseCaptured = false;
 static POINT __mouseCapturePoint = { 0, 0 };
+static bool __multiSampling = false;
 static bool __cursorVisible = true;
 static unsigned int __gamepadsConnected = 0;
 
@@ -663,6 +664,8 @@ bool initializeGL(WindowCreationParams* params)
         WGL_STENCIL_BITS_ARB, DEFAULT_STENCIL_BUFFER_SIZE,
         0
     };
+    __multiSampling = params->samples > 0;
+
     UINT numFormats;
     if (!wglChoosePixelFormatARB(hdc, attribList, NULL, 1, &pixelFormat, &numFormats) || numFormats == 0)
     {
@@ -682,6 +685,8 @@ bool initializeGL(WindowCreationParams* params)
                     break;
                 }
             }
+
+            __multiSampling = params->samples > 0;
         }
 
         if (!valid)
@@ -1064,6 +1069,30 @@ void Platform::sleep(long ms)
     Sleep(ms);
 }
 
+void Platform::setMultiSampling(bool enabled)
+{
+    if (enabled == __multiSampling)
+    {
+        return;
+    }
+
+    if (enabled)
+    {
+        glEnable(GL_MULTISAMPLE);
+    }
+    else
+    {
+        glDisable(GL_MULTISAMPLE);
+    }
+
+    __multiSampling = enabled;
+}
+
+bool Platform::isMultiSampling()
+{
+    return __multiSampling;
+}
+
 void Platform::setMultiTouch(bool enabled)
 {
     // not supported

+ 92 - 3
gameplay/src/PlatformiOS.mm

@@ -38,6 +38,27 @@ extern const int WINDOW_SCALE = [[UIScreen mainScreen] scale];
 static AppDelegate *__appDelegate = NULL;
 static View* __view = NULL;
 
+class TouchPoint
+{
+public:
+    unsigned int hashId;
+    int x;
+    int y;
+    bool down;
+    
+    TouchPoint()
+    {
+        hashId = 0;
+        x = 0;
+        y = 0;
+        down = false;
+    }
+};
+
+// more than we'd ever need, to be safe
+#define TOUCH_POINTS_MAX (10)
+static TouchPoint __touchPoints[TOUCH_POINTS_MAX];
+
 static double __timeStart;
 static double __timeAbsolute;
 static bool __vsync = WINDOW_VSYNC;
@@ -259,6 +280,8 @@ int getUnicode(int key);
             samples /= 2;
         }
         
+        //todo: __multiSampling = samples > 0;
+
         // Re-bind the default framebuffer
         GL_ASSERT( glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer) );
         
@@ -516,7 +539,27 @@ int getUnicode(int key);
         {
             touchID = [touch hash];
         }
-        Platform::touchEventInternal(Touch::TOUCH_PRESS, touchPoint.x * WINDOW_SCALE, touchPoint.y * WINDOW_SCALE, touchID);
+
+        // Nested loop efficiency shouldn't be a concern since both loop sizes are small (<= 10)
+        int i = 0;
+        while (i < TOUCH_POINTS_MAX && __touchPoints[i].down)
+        {
+            i++;
+        }
+
+        if (i < TOUCH_POINTS_MAX)
+        {
+            __touchPoints[i].hashId = touchID;
+            __touchPoints[i].x = touchPoint.x * WINDOW_SCALE;
+            __touchPoints[i].y = touchPoint.y * WINDOW_SCALE;
+            __touchPoints[i].down = true;
+
+            Platform::touchEventInternal(Touch::TOUCH_PRESS, __touchPoints[i].x, __touchPoints[i].y, i);
+        }
+        else
+        {
+            print("touchesBegan: unable to find free element in __touchPoints");
+        }
     }
 }
 
@@ -528,7 +571,32 @@ int getUnicode(int key);
         CGPoint touchPoint = [touch locationInView:self];
         if(self.multipleTouchEnabled == YES) 
             touchID = [touch hash];
-        Platform::touchEventInternal(Touch::TOUCH_RELEASE, touchPoint.x * WINDOW_SCALE, touchPoint.y * WINDOW_SCALE, touchID);
+
+        // Nested loop efficiency shouldn't be a concern since both loop sizes are small (<= 10)
+        bool found = false;
+        for (int i = 0; !found && i < TOUCH_POINTS_MAX; i++)
+        {
+            if (__touchPoints[i].down && __touchPoints[i].hashId == touchID)
+            {
+                __touchPoints[i].down = false;
+                Platform::touchEventInternal(Touch::TOUCH_RELEASE, touchPoint.x * WINDOW_SCALE, touchPoint.y * WINDOW_SCALE, i);
+                found = true;
+            }
+        }
+        
+        if (!found)
+        {
+            // It seems possible to receive an ID not in the array.
+            // The best we can do is clear the whole array.
+            for (int i = 0; i < TOUCH_POINTS_MAX; i++)
+            {
+                if (__touchPoints[i].down)
+                {
+                    __touchPoints[i].down = false;
+                    Platform::touchEventInternal(Touch::TOUCH_RELEASE, __touchPoints[i].x, __touchPoints[i].y, i);
+                }
+            }
+        }
     }
 }
 
@@ -546,7 +614,18 @@ int getUnicode(int key);
         CGPoint touchPoint = [touch locationInView:self];
         if(self.multipleTouchEnabled == YES) 
             touchID = [touch hash];
-        Platform::touchEventInternal(Touch::TOUCH_MOVE, touchPoint.x * WINDOW_SCALE, touchPoint.y * WINDOW_SCALE, touchID);
+
+        // Nested loop efficiency shouldn't be a concern since both loop sizes are small (<= 10)
+        for (int i = 0; i < TOUCH_POINTS_MAX; i++)
+        {
+            if (__touchPoints[i].down && __touchPoints[i].hashId == touchID)
+            {
+                __touchPoints[i].x = touchPoint.x * WINDOW_SCALE;
+                __touchPoints[i].y = touchPoint.y * WINDOW_SCALE;
+                Platform::touchEventInternal(Touch::TOUCH_MOVE, __touchPoints[i].x, __touchPoints[i].y, i);
+                break;
+            }
+        }
     }
 }
 
@@ -1331,6 +1410,16 @@ bool Platform::isCursorVisible()
     return false;
 }
 
+void Platform::setMultiSampling(bool enabled)
+{
+    //todo
+}
+
+bool Platform::isMultiSampling()
+{
+    return false; //todo
+}
+
 void Platform::setMultiTouch(bool enabled) 
 {
     __view.multipleTouchEnabled = enabled;

+ 1 - 1
gameplay/src/RadioButton.h

@@ -136,7 +136,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by the control.
      *

+ 8 - 0
gameplay/src/RenderState.cpp

@@ -556,6 +556,14 @@ static RenderState::Blend parseBlend(const char* value)
         return RenderState::BLEND_ZERO;
     else if (upper == "ONE")
         return RenderState::BLEND_ONE;
+    else if (upper == "SRC_COLOR")
+        return RenderState::BLEND_SRC_COLOR;
+    else if (upper == "ONE_MINUS_SRC_COLOR")
+        return RenderState::BLEND_ONE_MINUS_SRC_COLOR;
+    else if (upper == "DST_COLOR")
+        return RenderState::BLEND_DST_COLOR;
+    else if (upper == "ONE_MINUS_DST_COLOR")
+        return RenderState::BLEND_ONE_MINUS_DST_COLOR;
     else if (upper == "SRC_ALPHA")
         return RenderState::BLEND_SRC_ALPHA;
     else if (upper == "ONE_MINUS_SRC_ALPHA")

+ 1 - 1
gameplay/src/RenderState.h

@@ -134,7 +134,7 @@ public:
         BLEND_ZERO = GL_ZERO,
         BLEND_ONE = GL_ONE,
         BLEND_SRC_COLOR = GL_SRC_COLOR,
-        BLEN_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR,
+        BLEND_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR,
         BLEND_DST_COLOR = GL_DST_COLOR,
         BLEND_ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_COLOR,
         BLEND_SRC_ALPHA = GL_SRC_ALPHA,

+ 1 - 1
gameplay/src/ScriptController.h

@@ -811,7 +811,7 @@ private:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @see Touch::TouchEvent
      */

+ 1 - 1
gameplay/src/Slider.h

@@ -192,7 +192,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by the control.
      *

+ 1 - 1
gameplay/src/TextBox.h

@@ -102,7 +102,7 @@ protected:
      * @param evt The touch event that occurred.
      * @param x The x position of the touch in pixels. Left edge is zero.
      * @param y The y position of the touch in pixels. Top edge is zero.
-     * @param contactIndex An integer to identify this contact point within the currently active touch set.
+     * @param contactIndex The order of occurrence for multiple touch contacts starting at zero.
      *
      * @return Whether the touch event was consumed by the control.
      *

+ 73 - 0
gameplay/src/lua/lua_Game.cpp

@@ -54,6 +54,7 @@ void luaRegister_Game()
         {"isGestureSupported", lua_Game_isGestureSupported},
         {"isInitialized", lua_Game_isInitialized},
         {"isMouseCaptured", lua_Game_isMouseCaptured},
+        {"isMultiSampling", lua_Game_isMultiSampling},
         {"isMultiTouch", lua_Game_isMultiTouch},
         {"keyEvent", lua_Game_keyEvent},
         {"launchURL", lua_Game_launchURL},
@@ -66,6 +67,7 @@ void luaRegister_Game()
         {"schedule", lua_Game_schedule},
         {"setCursorVisible", lua_Game_setCursorVisible},
         {"setMouseCaptured", lua_Game_setMouseCaptured},
+        {"setMultiSampling", lua_Game_setMultiSampling},
         {"setMultiTouch", lua_Game_setMultiTouch},
         {"setViewport", lua_Game_setViewport},
         {"touchEvent", lua_Game_touchEvent},
@@ -1441,6 +1443,41 @@ int lua_Game_isMouseCaptured(lua_State* state)
     return 0;
 }
 
+int lua_Game_isMultiSampling(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))
+            {
+                Game* instance = getInstance(state);
+                bool result = instance->isMultiSampling();
+
+                // Push the return value onto the stack.
+                lua_pushboolean(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Game_isMultiSampling - 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_Game_isMultiTouch(lua_State* state)
 {
     // Get the number of parameters.
@@ -1885,6 +1922,42 @@ int lua_Game_setMouseCaptured(lua_State* state)
     return 0;
 }
 
+int lua_Game_setMultiSampling(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_TBOOLEAN)
+            {
+                // Get parameter 1 off the stack.
+                bool param1 = ScriptUtil::luaCheckBool(state, 2);
+
+                Game* instance = getInstance(state);
+                instance->setMultiSampling(param1);
+
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_Game_setMultiSampling - 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_Game_setMultiTouch(lua_State* state)
 {
     // Get the number of parameters.

+ 2 - 0
gameplay/src/lua/lua_Game.h

@@ -37,6 +37,7 @@ int lua_Game_isGestureRegistered(lua_State* state);
 int lua_Game_isGestureSupported(lua_State* state);
 int lua_Game_isInitialized(lua_State* state);
 int lua_Game_isMouseCaptured(lua_State* state);
+int lua_Game_isMultiSampling(lua_State* state);
 int lua_Game_isMultiTouch(lua_State* state);
 int lua_Game_keyEvent(lua_State* state);
 int lua_Game_launchURL(lua_State* state);
@@ -49,6 +50,7 @@ int lua_Game_run(lua_State* state);
 int lua_Game_schedule(lua_State* state);
 int lua_Game_setCursorVisible(lua_State* state);
 int lua_Game_setMouseCaptured(lua_State* state);
+int lua_Game_setMultiSampling(lua_State* state);
 int lua_Game_setMultiTouch(lua_State* state);
 int lua_Game_setViewport(lua_State* state);
 int lua_Game_static_getAbsoluteTime(lua_State* state);

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

@@ -5,6 +5,7 @@
 #include "Button.h"
 #include "Game.h"
 #include "Gamepad.h"
+#include "Platform.h"
 #include "lua_GamepadButtonMapping.h"
 
 namespace gameplay

+ 1 - 1
gameplay/src/lua/lua_Global.cpp

@@ -730,7 +730,7 @@ void luaRegister_lua_Global()
         ScriptUtil::registerConstantString("BLEND_ZERO", "BLEND_ZERO", scopePath);
         ScriptUtil::registerConstantString("BLEND_ONE", "BLEND_ONE", scopePath);
         ScriptUtil::registerConstantString("BLEND_SRC_COLOR", "BLEND_SRC_COLOR", scopePath);
-        ScriptUtil::registerConstantString("BLEN_ONE_MINUS_SRC_COLOR", "BLEN_ONE_MINUS_SRC_COLOR", scopePath);
+        ScriptUtil::registerConstantString("BLEND_ONE_MINUS_SRC_COLOR", "BLEND_ONE_MINUS_SRC_COLOR", scopePath);
         ScriptUtil::registerConstantString("BLEND_DST_COLOR", "BLEND_DST_COLOR", scopePath);
         ScriptUtil::registerConstantString("BLEND_ONE_MINUS_DST_COLOR", "BLEND_ONE_MINUS_DST_COLOR", scopePath);
         ScriptUtil::registerConstantString("BLEND_SRC_ALPHA", "BLEND_SRC_ALPHA", scopePath);

+ 98 - 0
gameplay/src/lua/lua_MeshBatch.cpp

@@ -2,6 +2,7 @@
 #include "ScriptController.h"
 #include "lua_MeshBatch.h"
 #include "Base.h"
+#include "Material.h"
 #include "MeshBatch.h"
 #include "lua_MeshPrimitiveType.h"
 
@@ -12,6 +13,7 @@ void luaRegister_MeshBatch()
 {
     const luaL_Reg lua_members[] = 
     {
+        {"add", lua_MeshBatch_add},
         {"draw", lua_MeshBatch_draw},
         {"finish", lua_MeshBatch_finish},
         {"getCapacity", lua_MeshBatch_getCapacity},
@@ -75,6 +77,102 @@ int lua_MeshBatch__gc(lua_State* state)
     return 0;
 }
 
+int lua_MeshBatch_add(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_TTABLE || lua_type(state, 2) == LUA_TLIGHTUSERDATA) &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                ScriptUtil::LuaArray<float> param1 = ScriptUtil::getFloatPointer(2);
+
+                // Get parameter 2 off the stack.
+                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 3);
+
+                MeshBatch* instance = getInstance(state);
+                instance->add(param1, param2);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_MeshBatch_add - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        case 4:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TTABLE || lua_type(state, 2) == LUA_TLIGHTUSERDATA) &&
+                lua_type(state, 3) == LUA_TNUMBER &&
+                (lua_type(state, 4) == LUA_TTABLE || lua_type(state, 4) == LUA_TLIGHTUSERDATA))
+            {
+                // Get parameter 1 off the stack.
+                ScriptUtil::LuaArray<float> param1 = ScriptUtil::getFloatPointer(2);
+
+                // Get parameter 2 off the stack.
+                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 3);
+
+                // Get parameter 3 off the stack.
+                ScriptUtil::LuaArray<unsigned short> param3 = ScriptUtil::getUnsignedShortPointer(4);
+
+                MeshBatch* instance = getInstance(state);
+                instance->add(param1, param2, param3);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_MeshBatch_add - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        case 5:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TTABLE || lua_type(state, 2) == LUA_TLIGHTUSERDATA) &&
+                lua_type(state, 3) == LUA_TNUMBER &&
+                (lua_type(state, 4) == LUA_TTABLE || lua_type(state, 4) == LUA_TLIGHTUSERDATA) &&
+                lua_type(state, 5) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                ScriptUtil::LuaArray<float> param1 = ScriptUtil::getFloatPointer(2);
+
+                // Get parameter 2 off the stack.
+                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 3);
+
+                // Get parameter 3 off the stack.
+                ScriptUtil::LuaArray<unsigned short> param3 = ScriptUtil::getUnsignedShortPointer(4);
+
+                // Get parameter 4 off the stack.
+                unsigned int param4 = (unsigned int)luaL_checkunsigned(state, 5);
+
+                MeshBatch* instance = getInstance(state);
+                instance->add(param1, param2, param3, param4);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_MeshBatch_add - 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, 4 or 5).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_MeshBatch_draw(lua_State* state)
 {
     // Get the number of parameters.

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

@@ -6,6 +6,7 @@ namespace gameplay
 
 // Lua bindings for MeshBatch.
 int lua_MeshBatch__gc(lua_State* state);
+int lua_MeshBatch_add(lua_State* state);
 int lua_MeshBatch_draw(lua_State* state);
 int lua_MeshBatch_finish(lua_State* state);
 int lua_MeshBatch_getCapacity(lua_State* state);

+ 5 - 5
gameplay/src/lua/lua_RenderStateBlend.cpp

@@ -9,7 +9,7 @@ static const char* enumStringEmpty = "";
 static const char* luaEnumString_RenderStateBlend_BLEND_ZERO = "BLEND_ZERO";
 static const char* luaEnumString_RenderStateBlend_BLEND_ONE = "BLEND_ONE";
 static const char* luaEnumString_RenderStateBlend_BLEND_SRC_COLOR = "BLEND_SRC_COLOR";
-static const char* luaEnumString_RenderStateBlend_BLEN_ONE_MINUS_SRC_COLOR = "BLEN_ONE_MINUS_SRC_COLOR";
+static const char* luaEnumString_RenderStateBlend_BLEND_ONE_MINUS_SRC_COLOR = "BLEND_ONE_MINUS_SRC_COLOR";
 static const char* luaEnumString_RenderStateBlend_BLEND_DST_COLOR = "BLEND_DST_COLOR";
 static const char* luaEnumString_RenderStateBlend_BLEND_ONE_MINUS_DST_COLOR = "BLEND_ONE_MINUS_DST_COLOR";
 static const char* luaEnumString_RenderStateBlend_BLEND_SRC_ALPHA = "BLEND_SRC_ALPHA";
@@ -28,8 +28,8 @@ RenderState::Blend lua_enumFromString_RenderStateBlend(const char* s)
         return RenderState::BLEND_ONE;
     if (strcmp(s, luaEnumString_RenderStateBlend_BLEND_SRC_COLOR) == 0)
         return RenderState::BLEND_SRC_COLOR;
-    if (strcmp(s, luaEnumString_RenderStateBlend_BLEN_ONE_MINUS_SRC_COLOR) == 0)
-        return RenderState::BLEN_ONE_MINUS_SRC_COLOR;
+    if (strcmp(s, luaEnumString_RenderStateBlend_BLEND_ONE_MINUS_SRC_COLOR) == 0)
+        return RenderState::BLEND_ONE_MINUS_SRC_COLOR;
     if (strcmp(s, luaEnumString_RenderStateBlend_BLEND_DST_COLOR) == 0)
         return RenderState::BLEND_DST_COLOR;
     if (strcmp(s, luaEnumString_RenderStateBlend_BLEND_ONE_MINUS_DST_COLOR) == 0)
@@ -60,8 +60,8 @@ const char* lua_stringFromEnum_RenderStateBlend(RenderState::Blend e)
         return luaEnumString_RenderStateBlend_BLEND_ONE;
     if (e == RenderState::BLEND_SRC_COLOR)
         return luaEnumString_RenderStateBlend_BLEND_SRC_COLOR;
-    if (e == RenderState::BLEN_ONE_MINUS_SRC_COLOR)
-        return luaEnumString_RenderStateBlend_BLEN_ONE_MINUS_SRC_COLOR;
+    if (e == RenderState::BLEND_ONE_MINUS_SRC_COLOR)
+        return luaEnumString_RenderStateBlend_BLEND_ONE_MINUS_SRC_COLOR;
     if (e == RenderState::BLEND_DST_COLOR)
         return luaEnumString_RenderStateBlend_BLEND_DST_COLOR;
     if (e == RenderState::BLEND_ONE_MINUS_DST_COLOR)

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

@@ -11,6 +11,7 @@
 #include "ScriptController.h"
 #include "ScriptTarget.h"
 #include "Terrain.h"
+#include "TerrainPatch.h"
 #include "Transform.h"
 #include "lua_CurveInterpolationType.h"
 #include "lua_TerrainFlags.h"