Parcourir la source

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

Steve Grenier il y a 13 ans
Parent
commit
e4bfc49def
39 fichiers modifiés avec 349 ajouts et 100 suppressions
  1. 2 1
      .gitignore
  2. 1 1
      gameplay/android/jni/Android.mk
  3. 2 0
      gameplay/gameplay.vcxproj
  4. 6 0
      gameplay/gameplay.vcxproj.filters
  5. 12 0
      gameplay/gameplay.xcodeproj/project.pbxproj
  6. 0 0
      gameplay/res/icon.psd
  7. 0 0
      gameplay/res/icon_128.ico
  8. 0 0
      gameplay/res/icon_16.ico
  9. 0 0
      gameplay/res/icon_32.ico
  10. 0 0
      gameplay/res/icon_64.ico
  11. BIN
      gameplay/res/icon_black.psd
  12. BIN
      gameplay/res/icon_black128.ico
  13. BIN
      gameplay/res/icon_black16.ico
  14. BIN
      gameplay/res/icon_black32.ico
  15. BIN
      gameplay/res/icon_black64.ico
  16. BIN
      gameplay/res/icon_white_transparent.psd
  17. BIN
      gameplay/res/icon_white_transparent128.ico
  18. BIN
      gameplay/res/icon_white_transparent16.ico
  19. BIN
      gameplay/res/icon_white_transparent32.ico
  20. BIN
      gameplay/res/icon_white_transparent64.ico
  21. 2 2
      gameplay/src/AnimationClip.h
  22. 7 10
      gameplay/src/Base.h
  23. 2 0
      gameplay/src/Container.cpp
  24. 92 0
      gameplay/src/FlowLayout.cpp
  25. 60 0
      gameplay/src/FlowLayout.h
  26. 6 6
      gameplay/src/Matrix.cpp
  27. 1 11
      gameplay/src/Model.cpp
  28. 1 1
      gameplay/src/Node.cpp
  29. 67 17
      gameplay/src/PhysicsCharacter.cpp
  30. 7 0
      gameplay/src/PhysicsCharacter.h
  31. 2 2
      gameplay/src/PhysicsCollisionShape.cpp
  32. 17 4
      gameplay/src/PhysicsController.cpp
  33. 1 1
      gameplay/src/PhysicsRigidBody.h
  34. 10 1
      gameplay/src/PlatformAndroid.cpp
  35. 9 0
      gameplay/src/PlatformMacOSX.mm
  36. 1 2
      gameplay/src/PlatformQNX.cpp
  37. 31 31
      gameplay/src/Texture.cpp
  38. 3 3
      gameplay/src/Texture.h
  39. 7 7
      gameplay/src/VertexAttributeBinding.cpp

+ 2 - 1
.gitignore

@@ -155,4 +155,5 @@ Thumbs.db
 
 /gameplay-samples/sample04-particles/Device-Debug
 /gameplay-samples/sample04-particles/Debug
-/gameplay-samples/sample04-particles/DebugMem
+/gameplay-samples/sample04-particles/DebugMem
+/gameplay-samples/sample03-character/res/gamepad.xcf

+ 1 - 1
gameplay/android/jni/Android.mk

@@ -16,7 +16,7 @@ LOCAL_PATH := $(call my-dir)/../../src
 
 include $(CLEAR_VARS)
 LOCAL_MODULE    := libgameplay
-LOCAL_SRC_FILES := AbsoluteLayout.cpp Animation.cpp AnimationClip.cpp AnimationController.cpp AnimationTarget.cpp AnimationValue.cpp AudioBuffer.cpp AudioController.cpp AudioListener.cpp AudioSource.cpp BoundingBox.cpp BoundingSphere.cpp Bundle.cpp Button.cpp Camera.cpp CheckBox.cpp Container.cpp Control.cpp Curve.cpp DebugNew.cpp DepthStencilTarget.cpp Effect.cpp FileSystem.cpp Font.cpp Form.cpp FrameBuffer.cpp Frustum.cpp Game.cpp gameplay-main-android.cpp Image.cpp Joint.cpp Label.cpp Layout.cpp Light.cpp Material.cpp MaterialParameter.cpp Matrix.cpp Mesh.cpp MeshBatch.cpp MeshPart.cpp MeshSkin.cpp Model.cpp Node.cpp ParticleEmitter.cpp Pass.cpp PhysicsCharacter.cpp PhysicsCollisionObject.cpp PhysicsCollisionShape.cpp PhysicsConstraint.cpp PhysicsController.cpp PhysicsFixedConstraint.cpp PhysicsGenericConstraint.cpp PhysicsGhostObject.cpp PhysicsHingeConstraint.cpp PhysicsMotionState.cpp PhysicsRigidBody.cpp PhysicsSocketConstraint.cpp PhysicsSpringConstraint.cpp Plane.cpp PlatformAndroid.cpp Properties.cpp Quaternion.cpp RadioButton.cpp Ray.cpp Rectangle.cpp Ref.cpp RenderState.cpp RenderTarget.cpp Scene.cpp SceneLoader.cpp Slider.cpp SpriteBatch.cpp Technique.cpp TextBox.cpp Texture.cpp Theme.cpp ThemeStyle.cpp Transform.cpp Vector2.cpp Vector3.cpp Vector4.cpp VertexAttributeBinding.cpp VertexFormat.cpp VerticalLayout.cpp
+LOCAL_SRC_FILES := AbsoluteLayout.cpp Animation.cpp AnimationClip.cpp AnimationController.cpp AnimationTarget.cpp AnimationValue.cpp AudioBuffer.cpp AudioController.cpp AudioListener.cpp AudioSource.cpp BoundingBox.cpp BoundingSphere.cpp Bundle.cpp Button.cpp Camera.cpp CheckBox.cpp Container.cpp Control.cpp Curve.cpp DebugNew.cpp DepthStencilTarget.cpp Effect.cpp FileSystem.cpp FlowLayout.cpp Font.cpp Form.cpp FrameBuffer.cpp Frustum.cpp Game.cpp gameplay-main-android.cpp Image.cpp Joint.cpp Label.cpp Layout.cpp Light.cpp Material.cpp MaterialParameter.cpp Matrix.cpp Mesh.cpp MeshBatch.cpp MeshPart.cpp MeshSkin.cpp Model.cpp Node.cpp ParticleEmitter.cpp Pass.cpp PhysicsCharacter.cpp PhysicsCollisionObject.cpp PhysicsCollisionShape.cpp PhysicsConstraint.cpp PhysicsController.cpp PhysicsFixedConstraint.cpp PhysicsGenericConstraint.cpp PhysicsGhostObject.cpp PhysicsHingeConstraint.cpp PhysicsMotionState.cpp PhysicsRigidBody.cpp PhysicsSocketConstraint.cpp PhysicsSpringConstraint.cpp Plane.cpp PlatformAndroid.cpp Properties.cpp Quaternion.cpp RadioButton.cpp Ray.cpp Rectangle.cpp Ref.cpp RenderState.cpp RenderTarget.cpp Scene.cpp SceneLoader.cpp Slider.cpp SpriteBatch.cpp Technique.cpp TextBox.cpp Texture.cpp Theme.cpp ThemeStyle.cpp Transform.cpp Vector2.cpp Vector3.cpp Vector4.cpp VertexAttributeBinding.cpp VertexFormat.cpp VerticalLayout.cpp
 LOCAL_CFLAGS := -D__ANDROID__ -I"../../external-deps/bullet/include" -I"../../external-deps/libpng/include"
 LOCAL_STATIC_LIBRARIES := android_native_app_glue
 

+ 2 - 0
gameplay/gameplay.vcxproj

@@ -37,6 +37,7 @@
     <ClCompile Include="src\DepthStencilTarget.cpp" />
     <ClCompile Include="src\Effect.cpp" />
     <ClCompile Include="src\FileSystem.cpp" />
+    <ClCompile Include="src\FlowLayout.cpp" />
     <ClCompile Include="src\Font.cpp" />
     <ClCompile Include="src\Form.cpp" />
     <ClCompile Include="src\FrameBuffer.cpp" />
@@ -128,6 +129,7 @@
     <ClInclude Include="src\DepthStencilTarget.h" />
     <ClInclude Include="src\Effect.h" />
     <ClInclude Include="src\FileSystem.h" />
+    <ClInclude Include="src\FlowLayout.h" />
     <ClInclude Include="src\Font.h" />
     <ClInclude Include="src\Form.h" />
     <ClInclude Include="src\FrameBuffer.h" />

+ 6 - 0
gameplay/gameplay.vcxproj.filters

@@ -276,6 +276,9 @@
     <ClCompile Include="src\Bundle.cpp">
       <Filter>src</Filter>
     </ClCompile>
+    <ClCompile Include="src\FlowLayout.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -548,6 +551,9 @@
     <ClInclude Include="src\Bundle.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="src\FlowLayout.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="res\shaders\bumped-specular.vsh">

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

@@ -28,6 +28,10 @@
 		42554EA2152BC35C000ED910 /* PhysicsCollisionShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42554E9F152BC35C000ED910 /* PhysicsCollisionShape.cpp */; };
 		42554EA3152BC35C000ED910 /* PhysicsCollisionShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 42554EA0152BC35C000ED910 /* PhysicsCollisionShape.h */; };
 		42554EA4152BC35C000ED910 /* PhysicsCollisionShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 42554EA0152BC35C000ED910 /* PhysicsCollisionShape.h */; };
+		426878AC153F4BB300844500 /* FlowLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 426878AA153F4BB300844500 /* FlowLayout.cpp */; };
+		426878AD153F4BB300844500 /* FlowLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 426878AA153F4BB300844500 /* FlowLayout.cpp */; };
+		426878AE153F4BB300844500 /* FlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 426878AB153F4BB300844500 /* FlowLayout.h */; };
+		426878AF153F4BB300844500 /* FlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 426878AB153F4BB300844500 /* FlowLayout.h */; };
 		4271C08E15337C8200B89DA7 /* Layout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4271C08D15337C8200B89DA7 /* Layout.cpp */; };
 		4271C08F15337C8200B89DA7 /* Layout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4271C08D15337C8200B89DA7 /* Layout.cpp */; };
 		428390991489D6E800E2B2F5 /* SceneLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 428390971489D6E800E2B2F5 /* SceneLoader.cpp */; };
@@ -400,6 +404,8 @@
 		4251B130152D049B002F6199 /* ThemeStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThemeStyle.h; path = src/ThemeStyle.h; sourceTree = SOURCE_ROOT; };
 		42554E9F152BC35C000ED910 /* PhysicsCollisionShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PhysicsCollisionShape.cpp; path = src/PhysicsCollisionShape.cpp; sourceTree = SOURCE_ROOT; };
 		42554EA0152BC35C000ED910 /* PhysicsCollisionShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PhysicsCollisionShape.h; path = src/PhysicsCollisionShape.h; sourceTree = SOURCE_ROOT; };
+		426878AA153F4BB300844500 /* FlowLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FlowLayout.cpp; path = src/FlowLayout.cpp; sourceTree = SOURCE_ROOT; };
+		426878AB153F4BB300844500 /* FlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlowLayout.h; path = src/FlowLayout.h; sourceTree = SOURCE_ROOT; };
 		4271C08D15337C8200B89DA7 /* Layout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Layout.cpp; path = src/Layout.cpp; sourceTree = SOURCE_ROOT; };
 		428390971489D6E800E2B2F5 /* SceneLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SceneLoader.cpp; path = src/SceneLoader.cpp; sourceTree = SOURCE_ROOT; };
 		428390981489D6E800E2B2F5 /* SceneLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SceneLoader.h; path = src/SceneLoader.h; sourceTree = SOURCE_ROOT; };
@@ -730,6 +736,8 @@
 				42CD0DD3147D8FF50000361E /* Effect.h */,
 				42CD0DD4147D8FF50000361E /* FileSystem.cpp */,
 				42CD0DD5147D8FF50000361E /* FileSystem.h */,
+				426878AA153F4BB300844500 /* FlowLayout.cpp */,
+				426878AB153F4BB300844500 /* FlowLayout.h */,
 				42CD0DD6147D8FF50000361E /* Font.cpp */,
 				42CD0DD7147D8FF50000361E /* Font.h */,
 				5BD5263F150F822A004C9099 /* Form.cpp */,
@@ -1055,6 +1063,7 @@
 				4251B131152D049B002F6199 /* ScreenDisplayer.h in Headers */,
 				4251B135152D049B002F6199 /* ThemeStyle.h in Headers */,
 				422260D81537790F0011E3AB /* Bundle.h in Headers */,
+				426878AE153F4BB300844500 /* FlowLayout.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1151,6 +1160,7 @@
 				4251B132152D049B002F6199 /* ScreenDisplayer.h in Headers */,
 				4251B136152D049B002F6199 /* ThemeStyle.h in Headers */,
 				422260D91537790F0011E3AB /* Bundle.h in Headers */,
+				426878AF153F4BB300844500 /* FlowLayout.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1306,6 +1316,7 @@
 				4251B133152D049B002F6199 /* ThemeStyle.cpp in Sources */,
 				4271C08E15337C8200B89DA7 /* Layout.cpp in Sources */,
 				422260D61537790F0011E3AB /* Bundle.cpp in Sources */,
+				426878AC153F4BB300844500 /* FlowLayout.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1397,6 +1408,7 @@
 				4251B134152D049B002F6199 /* ThemeStyle.cpp in Sources */,
 				4271C08F15337C8200B89DA7 /* Layout.cpp in Sources */,
 				422260D71537790F0011E3AB /* Bundle.cpp in Sources */,
+				426878AD153F4BB300844500 /* FlowLayout.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 0 - 0
gameplay/res/icon_black_transparent.psd → gameplay/res/icon.psd


+ 0 - 0
gameplay/res/icon_black_transparent128.ico → gameplay/res/icon_128.ico


+ 0 - 0
gameplay/res/icon_black_transparent16.ico → gameplay/res/icon_16.ico


+ 0 - 0
gameplay/res/icon_black_transparent32.ico → gameplay/res/icon_32.ico


+ 0 - 0
gameplay/res/icon_black_transparent64.ico → gameplay/res/icon_64.ico


BIN
gameplay/res/icon_black.psd


BIN
gameplay/res/icon_black128.ico


BIN
gameplay/res/icon_black16.ico


BIN
gameplay/res/icon_black32.ico


BIN
gameplay/res/icon_black64.ico


BIN
gameplay/res/icon_white_transparent.psd


BIN
gameplay/res/icon_white_transparent128.ico


BIN
gameplay/res/icon_white_transparent16.ico


BIN
gameplay/res/icon_white_transparent32.ico


BIN
gameplay/res/icon_white_transparent64.ico


+ 2 - 2
gameplay/src/AnimationClip.h

@@ -108,7 +108,7 @@ public:
     /**
      * Sets the AnimationClip's repeat count. Overrides repeat duration.
      *
-     * Use ANIMATION_REPEAT_INDEFINITE to play the AnimationClip indefinitely.
+     * Use REPEAT_INDEFINITE to play the AnimationClip indefinitely.
      * 
      * @param repeatCount The repeat count to set on the AnimationClip.
      */
@@ -124,7 +124,7 @@ public:
     /**
      * Sets the AnimationClip's active duration. Overrides repeat count.
      *
-     * Use ANIMATION_REPEAT_INDEFINITE to play the AnimationClip indefinitely.
+     * Use REPEAT_INDEFINITE to play the AnimationClip indefinitely.
      *
      * @param duration The active duration that is set on the AnimationClip.
      */

+ 7 - 10
gameplay/src/Base.h

@@ -198,14 +198,11 @@ extern void printError(const char* format, ...);
     extern PFNGLISVERTEXARRAYOESPROC glIsVertexArray;
     #define glClearDepth glClearDepthf
     #define OPENGL_ES
-    #define OPENGL_ES_PVR    
+    #define USE_PVRTC
 #elif WIN32
     #define WIN32_LEAN_AND_MEAN
-    #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG                      0x8C00
-    #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG                      0x8C01
-    #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG                     0x8C02
-    #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG                     0x8C03
     #include <GL/glew.h>
+    #define USE_VAO
 #elif __APPLE__
     #include "TargetConditionals.h"
     #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
@@ -217,7 +214,8 @@ extern void printError(const char* format, ...);
         #define glIsVertexArray glIsVertexArrayOES
         #define glClearDepth glClearDepthf
         #define OPENGL_ES
-        #define OPENGL_ES_PVR    
+        #define USE_PVRTC
+        #define USE_VAO
     #elif TARGET_OS_MAC
         #include <OpenGL/gl.h>
         #include <OpenGL/glext.h>
@@ -225,13 +223,12 @@ extern void printError(const char* format, ...);
         #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
         #define glGenVertexArrays glGenVertexArraysAPPLE
         #define glIsVertexArray glIsVertexArrayAPPLE
+        #define USE_VAO
     #else
         #error "Unsupported Apple Device"
     #endif
 #endif
 
-
-
 // Graphics (GLSL)
 #define VERTEX_ATTRIBUTE_POSITION_NAME              "a_position"
 #define VERTEX_ATTRIBUTE_NORMAL_NAME                "a_normal"
@@ -240,9 +237,9 @@ extern void printError(const char* format, ...);
 #define VERTEX_ATTRIBUTE_BINORMAL_NAME              "a_binormal"
 #define VERTEX_ATTRIBUTE_BLENDWEIGHTS_NAME          "a_blendWeights"
 #define VERTEX_ATTRIBUTE_BLENDINDICES_NAME          "a_blendIndices"
-#define VERTEX_ATTRIBUTE_TEXCOORD_PREFIX            "a_texCoord"
+#define VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME       "a_texCoord"
 
-// Hardware Resources
+// Hardware buffer
 namespace gameplay
 {
 typedef GLint VertexAttribute;

+ 2 - 0
gameplay/src/Container.cpp

@@ -2,6 +2,7 @@
 #include "Container.h"
 #include "Layout.h"
 #include "AbsoluteLayout.h"
+#include "FlowLayout.h"
 #include "VerticalLayout.h"
 #include "Label.h"
 #include "Button.h"
@@ -40,6 +41,7 @@ namespace gameplay
             layout = AbsoluteLayout::create();
             break;
         case Layout::LAYOUT_FLOW:
+            layout = FlowLayout::create();
             break;
         case Layout::LAYOUT_VERTICAL:
             layout = VerticalLayout::create();

+ 92 - 0
gameplay/src/FlowLayout.cpp

@@ -0,0 +1,92 @@
+#include "Base.h"
+#include "Control.h"
+#include "FlowLayout.h"
+#include "Container.h"
+
+namespace gameplay
+{
+
+static FlowLayout* __instance;
+
+FlowLayout::FlowLayout()
+{
+}
+
+FlowLayout::FlowLayout(const FlowLayout& copy)
+{
+}
+
+FlowLayout::~FlowLayout()
+{
+}
+
+FlowLayout* FlowLayout::create()
+{
+    if (!__instance)
+    {
+        __instance = new FlowLayout();
+    }
+    else
+    {
+        __instance->addRef();
+    }
+
+    return __instance;
+}
+
+Layout::Type FlowLayout::getType()
+{
+    return Layout::LAYOUT_FLOW;
+}
+
+void FlowLayout::update(const Container* container)
+{
+    const Rectangle& containerBounds = container->getClipBounds();
+    const Theme::Border& containerBorder = container->getBorder(container->getState());
+    const Theme::Padding& containerPadding = container->getPadding();
+
+    float clipWidth = containerBounds.width - containerBorder.left - containerBorder.right - containerPadding.left - containerPadding.right;
+    float clipHeight = containerBounds.height - containerBorder.top - containerBorder.bottom - containerPadding.top - containerPadding.bottom;
+
+    float xPosition = 0;
+    float yPosition = 0;
+    float rowY = 0;
+    float tallestHeight = 0;
+
+    std::vector<Control*> controls = container->getControls();
+    unsigned int controlsCount = controls.size();
+    for (unsigned int i = 0; i < controlsCount; i++)
+    {
+        Control* control = controls.at(i);
+
+        const Rectangle& bounds = control->getBounds();
+        const Theme::Margin& margin = control->getMargin();
+
+        xPosition += margin.left;
+
+        // Wrap to next row if we've gone past the edge of the container.
+        if (xPosition + bounds.width >= clipWidth)
+        {
+            xPosition = margin.left;
+            rowY += tallestHeight;
+        }
+
+        yPosition = rowY + margin.top;
+
+        control->setPosition(xPosition, yPosition);
+        if (control->isDirty() || control->isContainer())
+        {
+            control->update(container->getClip());
+        }
+
+        xPosition += bounds.width + margin.right;
+
+        float height = bounds.height + margin.top + margin.bottom;
+        if (height > tallestHeight)
+        {
+            tallestHeight = height;
+        }
+    }
+}
+
+}

+ 60 - 0
gameplay/src/FlowLayout.h

@@ -0,0 +1,60 @@
+#ifndef FLOWLAYOUT_H_
+#define FLOWLAYOUT_H_
+
+#include "Layout.h"
+
+namespace gameplay
+{
+
+class FlowLayout : public Layout
+{
+    friend class Form;
+    friend class Container;
+
+public:
+
+    /**
+     * Get the type of this Layout.
+     *
+     * @return Layout::LAYOUT_FLOW
+     */
+    Layout::Type getType();
+
+protected:
+
+    /**
+     * Create a FlowLayout.
+     *
+     * @return A FlowLayout object.
+     */
+    static FlowLayout* create();
+
+    /**
+     * Update the controls contained by the specified container.
+     *
+     * @param container The container to update.
+     */
+    void update(const Container* container);
+
+private:
+
+    /**
+     * Constructor.
+     */
+    FlowLayout();
+
+    /**
+     * Constructor.
+     */
+    FlowLayout(const FlowLayout& copy);
+
+    /**
+     * Destructor.
+     */
+    virtual ~FlowLayout();
+
+};
+
+}
+
+#endif

+ 6 - 6
gameplay/src/Matrix.cpp

@@ -554,18 +554,18 @@ void Matrix::getLeftVector(Vector3* dst) const
 {
     assert(dst);
 
-    dst->x = m[0];
-    dst->y = m[1];
-    dst->z = m[2];
+    dst->x = -m[0];
+    dst->y = -m[1];
+    dst->z = -m[2];
 }
 
 void Matrix::getRightVector(Vector3* dst) const
 {
     assert(dst);
 
-    dst->x = -m[0];
-    dst->y = -m[1];
-    dst->z = -m[2];
+    dst->x = m[0];
+    dst->y = m[1];
+    dst->z = m[2];
 }
 
 void Matrix::getForwardVector(Vector3* dst) const

+ 1 - 11
gameplay/src/Model.cpp

@@ -252,14 +252,13 @@ void Model::draw(bool wireframe)
         // No mesh parts (index buffers).
         if (_material)
         {
-            GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
-
             Technique* technique = _material->getTechnique();
             unsigned int passCount = technique->getPassCount();
             for (unsigned int i = 0; i < passCount; ++i)
             {
                 Pass* pass = technique->getPass(i);
                 pass->bind();
+                GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
                 if (wireframe && (_mesh->getPrimitiveType() == Mesh::TRIANGLES || _mesh->getPrimitiveType() == Mesh::TRIANGLE_STRIP))
                 {
                     unsigned int vertexCount = _mesh->getVertexCount();
@@ -284,15 +283,6 @@ void Model::draw(bool wireframe)
 
             // Get the material for this mesh part.
             Material* material = getMaterial(i);
-            /*if (_partMaterials && i < _partCount && _partMaterials[i])
-            {
-                material = _partMaterials[i]; // Use part material
-            }
-            else
-            {
-                material = _material; // Use shared material
-            }*/
-
             if (material)
             {
                 Technique* technique = material->getTechnique();

+ 1 - 1
gameplay/src/Node.cpp

@@ -1021,7 +1021,7 @@ PhysicsCollisionObject* Node::setCollisionObject(Properties* properties)
         strcmp(properties->getNamespace(), "ghostObject") == 0 || 
         strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
-        WARN("Failed to load collision object from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
+        WARN("Failed to load collision object from properties object: must be non-null object and have namespace equal to \'character\', \'ghostObject\', or \'rigidBody\'.");
         return NULL;
     }
 

+ 67 - 17
gameplay/src/PhysicsCharacter.cpp

@@ -209,6 +209,15 @@ void PhysicsCharacter::setRightVelocity(float velocity)
     _rightVelocity = velocity;
 }
 
+Vector3 PhysicsCharacter::getCurrentVelocity() const
+{
+    Vector3 v(_currentVelocity.x(), _currentVelocity.y(), _currentVelocity.z());
+    v.x += _verticalVelocity.x();
+    v.y += _verticalVelocity.y();
+    v.z += _verticalVelocity.z();
+    return v;
+}
+
 void PhysicsCharacter::jump(float height)
 {
     // TODO: Add support for different jump modes (i.e. double jump, changing direction in air, holding down jump button for extra height, etc)
@@ -440,28 +449,69 @@ void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
     btTransform end;
     start.setIdentity();
     end.setIdentity();
-    start.setOrigin(_currentPosition);
-    end.setOrigin(targetPosition);
 
-    ClosestNotMeConvexResultCallback callback(this, btVector3(0, 1, 0), _cosSlopeAngle);
-    callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
-    callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
+    btScalar fraction = 1.0;
+    int maxIter = 10;
+    while (fraction > btScalar(0.01) && maxIter-- > 0)
+    {
+        start.setOrigin(_currentPosition);
+        end.setOrigin(targetPosition);
 
-    _ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+        btVector3 sweepDirNegative(_currentPosition - targetPosition);
 
-    if (callback.hasHit())
-    {
-        // Collision detected, fix it
-        _currentPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
+        ClosestNotMeConvexResultCallback callback(this, sweepDirNegative, 0.0);
+        callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
+        callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
 
-        // Zero out fall velocity when we hit an object
-        _verticalVelocity.setZero();
-    }
-    else
-    {
-        // We can move here
-        _currentPosition = targetPosition;
+        _ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+
+        fraction -= callback.m_closestHitFraction;
+
+        if (callback.hasHit())
+        {
+            // Collision detected, fix it.
+            Vector3 normal(callback.m_hitNormalWorld.x(), callback.m_hitNormalWorld.y(), callback.m_hitNormalWorld.z());
+            normal.normalize();
+
+            float dot = normal.dot(Vector3::unitY());
+            if (dot > 1.0f - MATH_EPSILON)
+            {
+                targetPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
+
+                // Zero out fall velocity when we hit an object going straight down.
+                _verticalVelocity.setZero();
+                break;
+            }
+            else
+            {
+                PhysicsCollisionObject* o = Game::getInstance()->getPhysicsController()->getCollisionObject(callback.m_hitCollisionObject);
+                if (o->getType() == PhysicsCollisionObject::RIGID_BODY && o->isDynamic())
+                {
+                    PhysicsRigidBody* rb = static_cast<PhysicsRigidBody*>(o);
+                    normal.normalize();
+                    rb->applyImpulse(_mass * -normal * sqrt(BV(normal).dot(_verticalVelocity)));
+                }
+
+                updateTargetPositionFromCollision(targetPosition, BV(normal));
+            }
+        }
+        else
+        {
+            // Nothing is in the way.
+            break;
+        }
     }
+
+    // Calculate what the vertical velocity actually is.
+    // In cases where the character might not actually be able to move down,
+    // but isn't intersecting with an object straight down either, we don't
+    // want to keep increasing the vertical velocity until the character 
+    // randomly drops through the floor when it can finally move due to its
+    // vertical velocity having such a great magnitude.
+    if (!_verticalVelocity.isZero())
+        _verticalVelocity = ((targetPosition + btVector3(0.0, _stepHeight, 0.0)) - _currentPosition) / time;
+
+    _currentPosition = targetPosition;
 }
 
 /*

+ 7 - 0
gameplay/src/PhysicsCharacter.h

@@ -151,6 +151,13 @@ public:
      */
     void setRightVelocity(float velocity = 1.0f);
 
+    /**
+     * Returns the current velocity of the character.
+     *
+     * @return The current velocity.
+     */
+    Vector3 getCurrentVelocity() const;
+
     /**
      * Causes the character to jump to the specified height.
      *

+ 2 - 2
gameplay/src/PhysicsCollisionShape.cpp

@@ -124,7 +124,7 @@ PhysicsCollisionShape::Definition* PhysicsCollisionShape::Definition::create(Nod
         strcmp(properties->getNamespace(), "ghostObject") == 0 || 
         strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
-        WARN("Failed to load physics collision shape from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
+        WARN("Failed to load physics collision shape from properties object: must be non-null object and have namespace equal to \'character\', \'ghostObject\', or \'rigidBody\'.");
         return NULL;
     }
 
@@ -186,7 +186,7 @@ PhysicsCollisionShape::Definition* PhysicsCollisionShape::Definition::create(Nod
             center = new Vector3();
             properties->getVector3("center", center);
         }
-        else if (strcmp(name, "center-absolute") == 0)
+        else if (strcmp(name, "centerAbsolute") == 0)
         {
             centerIsAbsolute = properties->getBool();
         }

+ 17 - 4
gameplay/src/PhysicsController.cpp

@@ -185,20 +185,33 @@ bool PhysicsController::sweepTest(PhysicsCollisionObject* object, const Vector3&
 
     // Define the start transform
     btTransform start;
+    start.setIdentity();
     if (object->getNode())
-        start.setFromOpenGLMatrix(object->getNode()->getWorldMatrix().m);
-    else
+    {
+        Vector3 translation;
+        Quaternion rotation;
+        const Matrix& m = object->getNode()->getWorldMatrix();
+        m.getTranslation(&translation);
+        m.getRotation(&rotation);
+
         start.setIdentity();
+        start.setOrigin(BV(translation));
+        start.setRotation(BQ(rotation));
+    }
 
     // Define the end transform
     btTransform end(start);
     end.setOrigin(BV(endPosition));
 
+    float d1 = object->getNode()->getTranslationWorld().distance(endPosition);
+    float d2 = start.getOrigin().distance(end.getOrigin());
+
     // Perform bullet convex sweep test
     SweepTestCallback callback(object);
 
     // If the object is represented by a ghost object, use the ghost object's convex sweep test
     // since it is much faster than the world's version.
+    // NOTE: Unfortunately the ghost object sweep test does not seem reliable here currently, so using world's version instead.
     /*switch (object->getType())
     {
     case PhysicsCollisionObject::GHOST_OBJECT:
@@ -209,8 +222,8 @@ bool PhysicsController::sweepTest(PhysicsCollisionObject* object, const Vector3&
     default:
         _world->convexSweepTest(static_cast<btConvexShape*>(shape->getShape()), start, end, callback, _world->getDispatchInfo().m_allowedCcdPenetration);
         break;
-    }
-    */
+    }*/
+
     _world->convexSweepTest(static_cast<btConvexShape*>(shape->getShape()), start, end, callback, _world->getDispatchInfo().m_allowedCcdPenetration);
 
     // Check for hits and store results

+ 1 - 1
gameplay/src/PhysicsRigidBody.h

@@ -294,7 +294,7 @@ private:
      * 
      * @param node The node to create a rigid body for; note that the node must have
      *      a model attached to it prior to creating a rigid body for it.
-     * @param properties The properties object defining the rigid body (must have namespace equal to 'rigidbody').
+     * @param properties The properties object defining the rigid body (must have namespace equal to 'rigidBody').
      * @return The newly created rigid body, or <code>NULL</code> if the rigid body failed to load.
      */
     static PhysicsRigidBody* create(Node* node, Properties* properties);

+ 10 - 1
gameplay/src/PlatformAndroid.cpp

@@ -4,6 +4,7 @@
 #include "Platform.h"
 #include "FileSystem.h"
 #include "Game.h"
+#include "Form.h"
 #include <unistd.h>
 
 #include <android/sensor.h>
@@ -549,7 +550,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
                     break;
             }
             size_t pointerId = AMotionEvent_getPointerId(event, i);
-            Game::getInstance()->touchEvent(touchEvent, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), pointerId);
+            gameplay::Platform::touchEventInternal(touchEvent, AMotionEvent_getX(event, i), AMotionEvent_getY(event, i), pointerId);
         }
         return 1;
     } 
@@ -853,6 +854,14 @@ void Platform::displayKeyboard(bool display)
         __displayKeyboard = false;
 }
 
+void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
+{
+    if (!Form::touchEventInternal(evt, x, y, contactIndex))
+    {
+        Game::getInstance()->touchEvent(evt, x, y, contactIndex);
+    }
+}
+
 void Platform::sleep(long ms)
 {
     usleep(ms * 1000);

+ 9 - 0
gameplay/src/PlatformMacOSX.mm

@@ -667,6 +667,15 @@ int Platform::getOrientationAngle()
     return 0;
 }
 
+void Platform::setMultiTouch(bool enabled)
+{
+}
+    
+bool Platform::isMultiTouch()
+{
+    return false;
+}
+    
 void Platform::getAccelerometerValues(float* pitch, float* roll)
 {
     *pitch = __pitch;

+ 1 - 2
gameplay/src/PlatformQNX.cpp

@@ -721,9 +721,8 @@ Platform* Platform::create(Game* game)
 
     if (strstr(__glExtensions, "GL_OES_vertex_array_object") || strstr(__glExtensions, "GL_ARB_vertex_array_object"))
     {
-        // Disable VAO extension for now.
         glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
-        glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArrays");
+        glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
         glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
         glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");
     }

+ 31 - 31
gameplay/src/Texture.cpp

@@ -75,11 +75,11 @@ Texture* Texture::create(const char* path, bool generateMipmaps)
             }
             else if (tolower(ext[1]) == 'p' && tolower(ext[2]) == 'v' && tolower(ext[3]) == 'r')
             {
-#ifdef OPENGL_ES_PVR
-                // PowerVR Compressed RGBA
-                texture = createCompressedPVR(path);
+#ifdef USE_PVRTC
+                // PowerVR Compressed Texture RGBA
+                texture = createCompressedPVRTC(path);
 #else
-                texture = NULL; // Cannot handle PVR if not supported on platform
+                texture = NULL; // Cannot handle PVRTC if not supported on platform
 #endif
             }
             break;
@@ -147,32 +147,32 @@ Texture* Texture::create(Format format, unsigned int width, unsigned int height,
     return texture;
 }
 
-#ifdef OPENGL_ES_PVR
-Texture* Texture::createCompressedPVR(const char* path)
+#ifdef USE_PVRTC
+Texture* Texture::createCompressedPVRTC(const char* path)
 {
-    char PVRTexIdentifier[] = "PVR!";
+    char PVRTCIdentifier[] = "PVR!";
 
     enum
     {
-        PVRTextureFlagTypePVRTC_2 = 24,
-        PVRTextureFlagTypePVRTC_4
+        PVRTC_2 = 24,
+        PVRTC_4
     };
 
-    struct pvr_file_header
+    struct pvrtc_file_header
     {
         unsigned int size;                  // size of the structure
-        unsigned int height;                  // height of surface to be created
-        unsigned int width;                   // width of input surface
-        unsigned int mipmapCount;             // number of mip-map levels requested
+        unsigned int height;                // height of surface to be created
+        unsigned int width;                 // width of input surface
+        unsigned int mipmapCount;           // number of mip-map levels requested
         unsigned int formatflags;           // pixel format flags
-        unsigned int dataSize;                 // total size in bytes
-        unsigned int bpp;                    // number of bits per pixel
+        unsigned int dataSize;              // total size in bytes
+        unsigned int bpp;                   // number of bits per pixel
         unsigned int redBitMask;            // mask for red bit
         unsigned int greenBitMask;          // mask for green bits
         unsigned int blueBitMask;           // mask for blue bits
-        unsigned int alphaBitMask;            // mask for alpha channel
-        unsigned int pvrTag;                // magic number identifying pvr file
-        unsigned int surfaceCount;          // number of surfaces present in the pvr
+        unsigned int alphaBitMask;          // mask for alpha channel
+        unsigned int pvrtcTag;              // magic number identifying pvrtc file
+        unsigned int surfaceCount;          // number of surfaces present in the pvrtc
     } ;
 
     FILE* file = FileSystem::openFile(path, "rb");
@@ -183,24 +183,24 @@ Texture* Texture::createCompressedPVR(const char* path)
     }
 
     // Read the file header
-    unsigned int size = sizeof(pvr_file_header);
-    pvr_file_header header;
+    unsigned int size = sizeof(pvrtc_file_header);
+    pvrtc_file_header header;
     unsigned int read = (int)fread(&header, 1, size, file);
     assert(read == size);
     if (read != size)
     {
-        LOG_ERROR_VARG("Read file header error for pvr file: %s (%d < %d)", path, (int)read, (int)size);
+        LOG_ERROR_VARG("Read file header error for pvrtc file: %s (%d < %d)", path, (int)read, (int)size);
         fclose(file);
         return NULL;
     }
 
     // Proper file header identifier
-    if (PVRTexIdentifier[0] != (char)((header.pvrTag >>  0) & 0xff) ||
-        PVRTexIdentifier[1] != (char)((header.pvrTag >>  8) & 0xff) ||
-        PVRTexIdentifier[2] != (char)((header.pvrTag >> 16) & 0xff) ||
-        PVRTexIdentifier[3] != (char)((header.pvrTag >> 24) & 0xff))
+    if (PVRTCIdentifier[0] != (char)((header.pvrtcTag >>  0) & 0xff) ||
+        PVRTCIdentifier[1] != (char)((header.pvrtcTag >>  8) & 0xff) ||
+        PVRTCIdentifier[2] != (char)((header.pvrtcTag >> 16) & 0xff) ||
+        PVRTCIdentifier[3] != (char)((header.pvrtcTag >> 24) & 0xff))
      {
-        LOG_ERROR_VARG("Invalid PVR texture file: %s", path);
+        LOG_ERROR_VARG("Invalid PVRTC compressed texture file: %s", path);
         fclose(file);
         return NULL;
     }
@@ -208,17 +208,17 @@ Texture* Texture::createCompressedPVR(const char* path)
     // Format flags for GLenum format
     GLenum format;
     unsigned int formatFlags = header.formatflags & 0xff;
-    if (formatFlags == PVRTextureFlagTypePVRTC_4)
+    if (formatFlags == PVRTC_4)
     {
         format = header.alphaBitMask ? COMPRESSED_RGBA_PVRTC_4BPP : COMPRESSED_RGB_PVRTC_4BPP;
     }
-    else if (formatFlags == PVRTextureFlagTypePVRTC_2)
+    else if (formatFlags == PVRTC_2)
     {
         format = header.alphaBitMask ? COMPRESSED_RGBA_PVRTC_2BPP : COMPRESSED_RGB_PVRTC_2BPP;
     }
     else
     {
-        LOG_ERROR_VARG("Invalid PVR texture format flags for file: %s", path);
+        LOG_ERROR_VARG("Invalid PVRTC compressed texture format flags for file: %s", path);
         fclose(file);
         return NULL;
     }
@@ -228,7 +228,7 @@ Texture* Texture::createCompressedPVR(const char* path)
     assert(read == header.dataSize);
     if (read != header.dataSize)
     {
-        LOG_ERROR_VARG("Read file data error for pvr file: %s (%d < %d)", path, (int)read, (int)header.dataSize);
+        LOG_ERROR_VARG("Read file data error for pvrtc file: %s (%d < %d)", path, (int)read, (int)header.dataSize);
         SAFE_DELETE_ARRAY(data);
         fclose(file);
         return NULL;
@@ -259,7 +259,7 @@ Texture* Texture::createCompressedPVR(const char* path)
 
     for (unsigned int level = 0; level <= header.mipmapCount; level++)
     {
-        if (formatFlags == PVRTextureFlagTypePVRTC_4)
+        if (formatFlags == PVRTC_4)
         {
             dataSize = ( max((int)width, 8) * max((int)height, 8) * 4 + 7) / 8;
         }

+ 3 - 3
gameplay/src/Texture.h

@@ -30,7 +30,7 @@ public:
         RGBA    = GL_RGBA,
         ALPHA   = GL_ALPHA,
         DEPTH   = GL_DEPTH_COMPONENT,
-#ifdef OPENGL_ES_PVR
+#ifdef USE_PVRTC
         COMPRESSED_RGB_PVRTC_4BPP = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
         COMPRESSED_RGBA_PVRTC_4BPP = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
         COMPRESSED_RGB_PVRTC_2BPP = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,
@@ -213,8 +213,8 @@ private:
      */
     virtual ~Texture();
 
-#ifdef OPENGL_ES_PVR
-    static Texture* createCompressedPVR(const char* path);
+#ifdef USE_PVRTC
+    static Texture* createCompressedPVRTC(const char* path);
 #endif
     
     std::string _path;

+ 7 - 7
gameplay/src/VertexAttributeBinding.cpp

@@ -86,11 +86,11 @@ VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexF
     // Create a new VertexAttributeBinding.
     VertexAttributeBinding* b = new VertexAttributeBinding();
 
-#ifdef USE_GL_VAOS
+#ifdef USE_VAO
     if (mesh && glGenVertexArrays)
     {
         GL_ASSERT( glBindBuffer(GL_ARRAY_BUFFER, 0) );
-        GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) );
+        GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
 
         // Use hardware VAOs.
         GL_ASSERT( glGenVertexArrays(1, &b->_handle) );
@@ -168,11 +168,11 @@ VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexF
             attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDINDICES_NAME);
             break;
         case VertexFormat::TEXCOORD0:
-            attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX);
+            attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME);
             // Try adding a "0" after the texcoord attrib name (flexible name for this case).
             if (attrib == -1)
             {
-                name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX;
+                name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME;
                 name += "0";
                 attrib = effect->getVertexAttribute(name.c_str());
             }
@@ -184,7 +184,7 @@ VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexF
         case VertexFormat::TEXCOORD5:
         case VertexFormat::TEXCOORD6:
         case VertexFormat::TEXCOORD7:
-            name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX;
+            name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME;
             name += (e.usage - VertexFormat::TEXCOORD0);
             attrib = effect->getVertexAttribute(name.c_str());
             break;
@@ -221,8 +221,8 @@ void VertexAttributeBinding::setVertexAttribPointer(GLuint indx, GLint size, GLe
     if (_handle)
     {
         // Hardware mode
-        GL_ASSERT( glEnableVertexAttribArray(indx) );
         GL_ASSERT( glVertexAttribPointer(indx, size, type, normalize, stride, pointer) );
+        GL_ASSERT( glEnableVertexAttribArray(indx) );
     }
     else
     {
@@ -260,8 +260,8 @@ void VertexAttributeBinding::bind()
             VertexAttribute& a = _attributes[i];
             if (a.enabled)
             {
-                GL_ASSERT( glEnableVertexAttribArray(i) );
                 GL_ASSERT( glVertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, a.pointer) );
+                GL_ASSERT( glEnableVertexAttribArray(i) );
             }
         }
     }