Преглед на файлове

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

Conflicts:
	gameplay/src/FrameBuffer.cpp
	gameplay/src/RenderState.cpp
Steve Grenier преди 13 години
родител
ревизия
8c3e5ca808
променени са 95 файла, в които са добавени 2692 реда и са изтрити 3315 реда
  1. 7 0
      CHANGES.md
  2. 3 6
      README.md
  3. 12 0
      gameplay-encoder/src/Base.cpp
  4. 10 0
      gameplay-encoder/src/Base.h
  5. 4 7
      gameplay-encoder/src/EncoderArguments.cpp
  6. 8 14
      gameplay-encoder/src/TTFFontEncoder.cpp
  7. 12 2
      gameplay-encoder/src/TTFFontEncoder.h
  8. 28 12
      gameplay-encoder/src/main.cpp
  9. 2 2
      gameplay-template/res/box.material
  10. 16 92
      gameplay-template/res/colored.fsh
  11. 4 164
      gameplay-template/res/colored.vsh
  12. 17 2
      gameplay-template/src/TemplateGame.cpp
  13. 7 2
      gameplay-template/src/TemplateGame.h
  14. 21 20
      gameplay/gameplay.vcxproj
  15. 66 60
      gameplay/gameplay.vcxproj.filters
  16. 0 124
      gameplay/res/shaders/bumped-specular.fsh
  17. 0 248
      gameplay/res/shaders/bumped-specular.vsh
  18. 69 0
      gameplay/res/shaders/bumped.frag
  19. 0 113
      gameplay/res/shaders/bumped.fsh
  20. 94 0
      gameplay/res/shaders/bumped.vert
  21. 0 236
      gameplay/res/shaders/bumped.vsh
  22. 0 132
      gameplay/res/shaders/colored-specular.fsh
  23. 0 203
      gameplay/res/shaders/colored-specular.vsh
  24. 37 0
      gameplay/res/shaders/colored-unlit.frag
  25. 39 0
      gameplay/res/shaders/colored-unlit.vert
  26. 70 0
      gameplay/res/shaders/colored.frag
  27. 0 111
      gameplay/res/shaders/colored.fsh
  28. 81 0
      gameplay/res/shaders/colored.vert
  29. 0 183
      gameplay/res/shaders/colored.vsh
  30. 0 124
      gameplay/res/shaders/diffuse-specular.fsh
  31. 0 194
      gameplay/res/shaders/diffuse-specular.vsh
  32. 0 111
      gameplay/res/shaders/diffuse.fsh
  33. 0 191
      gameplay/res/shaders/diffuse.vsh
  34. 93 0
      gameplay/res/shaders/lib/attributes-skinning.vert
  35. 27 0
      gameplay/res/shaders/lib/attributes.vert
  36. 41 0
      gameplay/res/shaders/lib/lighting-directional.frag
  37. 31 0
      gameplay/res/shaders/lib/lighting-directional.vert
  38. 46 0
      gameplay/res/shaders/lib/lighting-point.frag
  39. 53 0
      gameplay/res/shaders/lib/lighting-point.vert
  40. 63 0
      gameplay/res/shaders/lib/lighting-spot.frag
  41. 54 0
      gameplay/res/shaders/lib/lighting-spot.vert
  42. 46 0
      gameplay/res/shaders/lib/lighting.frag
  43. 0 175
      gameplay/res/shaders/parallax-specular.fsh
  44. 0 118
      gameplay/res/shaders/parallax-specular.vsh
  45. 0 167
      gameplay/res/shaders/parallax.fsh
  46. 0 118
      gameplay/res/shaders/parallax.vsh
  47. 0 18
      gameplay/res/shaders/solid.fsh
  48. 0 10
      gameplay/res/shaders/solid.vsh
  49. 36 0
      gameplay/res/shaders/textured-unlit.frag
  50. 48 0
      gameplay/res/shaders/textured-unlit.vert
  51. 66 0
      gameplay/res/shaders/textured.frag
  52. 0 22
      gameplay/res/shaders/textured.fsh
  53. 87 0
      gameplay/res/shaders/textured.vert
  54. 0 78
      gameplay/res/shaders/textured.vsh
  55. 54 6
      gameplay/src/Button.cpp
  56. 21 1
      gameplay/src/Button.h
  57. 17 0
      gameplay/src/CheckBox.cpp
  58. 19 4
      gameplay/src/CheckBox.h
  59. 82 17
      gameplay/src/Container.cpp
  60. 20 3
      gameplay/src/Container.h
  61. 61 14
      gameplay/src/Control.cpp
  62. 56 6
      gameplay/src/Control.h
  63. 139 10
      gameplay/src/Effect.cpp
  64. 8 5
      gameplay/src/FileSystem.cpp
  65. 4 4
      gameplay/src/FileSystem.h
  66. 57 9
      gameplay/src/Form.cpp
  67. 20 2
      gameplay/src/Form.h
  68. 1 1
      gameplay/src/FrameBuffer.cpp
  69. 76 2
      gameplay/src/Game.cpp
  70. 33 0
      gameplay/src/Game.h
  71. 11 1
      gameplay/src/Game.inl
  72. 181 0
      gameplay/src/Gamepad.cpp
  73. 113 0
      gameplay/src/Gamepad.h
  74. 77 47
      gameplay/src/Joystick.cpp
  75. 17 1
      gameplay/src/Joystick.h
  76. 21 1
      gameplay/src/Label.cpp
  77. 16 1
      gameplay/src/Label.h
  78. 1 13
      gameplay/src/Material.cpp
  79. 0 1
      gameplay/src/MaterialParameter.cpp
  80. 1 1
      gameplay/src/PlatformWin32.cpp
  81. 18 1
      gameplay/src/RadioButton.cpp
  82. 17 1
      gameplay/src/RadioButton.h
  83. 17 20
      gameplay/src/RenderState.cpp
  84. 3 4
      gameplay/src/RenderState.h
  85. 74 2
      gameplay/src/Slider.cpp
  86. 29 0
      gameplay/src/Slider.h
  87. 0 25
      gameplay/src/SpriteBatch.cpp
  88. 60 25
      gameplay/src/TextBox.cpp
  89. 16 1
      gameplay/src/TextBox.h
  90. 3 1
      gameplay/src/Texture.h
  91. 29 17
      gameplay/src/Theme.h
  92. 5 0
      gameplay/src/ThemeStyle.cpp
  93. 9 0
      gameplay/src/ThemeStyle.h
  94. 7 9
      gameplay/src/VerticalLayout.h
  95. 1 0
      gameplay/src/gameplay.h

+ 7 - 0
CHANGES.md

@@ -1,3 +1,10 @@
+## v1.4.0
+
+- Pre-built versions gameplay-encoder added to bin folder with TTF, DAE and FBX support built-in.
+- Improved modular shader library with support for #include in shaders.
+- Fixes to FrameBuffer, RenderTarget and DepthStencilTarget.
+- TODO
+
 ## v1.3.0
 
 - Portrait mode games on mobile platforms.

+ 3 - 6
README.md

@@ -1,4 +1,4 @@
-## gameplay v1.3.0
+## gameplay v1.4.0
 An open-source, cross-platform 3D native C++ game framework making it easy to learn and write mobile and desktop games. 
 
 ## Supported Mobile Platforms
@@ -11,12 +11,9 @@ An open-source, cross-platform 3D native C++ game framework making it easy to le
 - Apple MacOS X (using Apple XCode 4.3.2)
 
 ## Roadmap for 'next' branch
-- Lua script bindings
-- Gamepad support
-- Vehicle physics
+- PhysicsVehicle
 - Terrain
-- Lightmaps
-- Shadows
+- ShadowMap
 
 ## Licence
 The project is open sourced under the Apache 2.0 license.

+ 12 - 0
gameplay-encoder/src/Base.cpp

@@ -11,4 +11,16 @@ void fillArray(float values[], float value, size_t length)
     }
 }
 
+std::string getBaseName(const std::string& filepath)
+{
+    size_t index1 = filepath.find_last_of('\\');
+    size_t index2 = filepath.find_last_of('/');
+    size_t index = (index1 != -1 && index1 > index2 ? index1 : index2);
+    size_t length = filepath.length();
+    std::string filename = filepath.substr(index + 1, length);
+    length = filename.length();
+    std::string output = filename.substr(0, (length-4));
+    return output;
+}
+
 }

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

@@ -76,6 +76,16 @@ enum VertexUsage
 
 void fillArray(float values[], float value, size_t length);
 
+/**
+ * Returns the base name of the given path.
+ * Example: "c:/foo/bar/model.dae" returns "model.dae"
+ * 
+ * @param filepath File path.
+ * 
+ * @return Base file name.
+ */
+std::string getBaseName(const std::string& filepath);
+
 #define ISZERO(x) (fabs(x) < 0.000001f)
 
 // Object deletion macro

+ 4 - 7
gameplay-encoder/src/EncoderArguments.cpp

@@ -179,16 +179,13 @@ void EncoderArguments::printUsage() const
     fprintf(stderr,"COLLADA and FBX file options:\n");
     fprintf(stderr,"  -i <id>\t\tFilter by node ID.\n");
     fprintf(stderr,"  -t\t\t\tWrite text/xml.\n");
-    fprintf(stderr,"  -groupAnimations <node id> <animation id>\n" \
+    fprintf(stderr,"  -g <node id> <animation id>\n" \
         "\t\t\tGroup all animation channels targetting the nodes into a new animation.\n");
     fprintf(stderr,"  -heightmaps \"<node ids>\"\n" \
         "\t\t\tList of nodes to generate heightmaps for.\n" \
         "\t\t\tNode id list should be in quotes with a space between each id.\n" \
         "\t\t\tHeightmaps will be saved in files named <nodeid>.png.\n");
     fprintf(stderr,"\n");
-    fprintf(stderr,"COLLADA file options:\n");
-    fprintf(stderr,"  -dae <filepath>\tOutput optimized DAE.\n");
-    fprintf(stderr,"\n");
     fprintf(stderr,"TTF file options:\n");
     fprintf(stderr,"  -s <size of font>\tSize of the font.\n");
     fprintf(stderr,"  -p\t\t\tOutput font preview.\n");
@@ -284,12 +281,12 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
         }
         break;
     case 'g':
-        if (str.compare("-groupAnimations") == 0)
+        if (str.compare("-groupAnimations") == 0 || str.compare("-g") == 0)
         {
             // read two strings, make sure not to go out of bounds
             if ((*index + 2) >= options.size())
             {
-                fprintf(stderr, "Error: -groupAnimations requires 2 arguments.\n");
+                fprintf(stderr, "Error: -g requires 2 arguments.\n");
                 _parseError = true;
                 return;
             }
@@ -450,7 +447,7 @@ void unittestsEncoderArguments()
     exePath.append("/gameplay-encoder.exe");
     const char* exe = exePath.c_str();
     {
-        const char* argv[] = {exe, "-groupAnimations", "root", "movements", "C:\\Git\\gaming\\GamePlay\\gameplay-encoder\\res\\seymour.dae"};
+        const char* argv[] = {exe, "-g", "root", "movements", "C:\\Git\\gaming\\GamePlay\\gameplay-encoder\\res\\seymour.dae"};
         EncoderArguments args(sizeof(argv) / sizeof(char*), (const char**)argv);
         assert(equals(args.getAnimationId("root"), ("movements")));
         assert(equals(args.getGroupAnimationNodeId()[0], ("root")));

+ 8 - 14
gameplay-encoder/src/TTFFontEncoder.cpp

@@ -1,6 +1,7 @@
 #include "Base.h"
 #include "TTFFontEncoder.h"
 #include "GPBFile.h"
+#include "StringUtil.h"
 
 namespace gameplay
 {
@@ -33,7 +34,7 @@ static void writeString(FILE* fp, const char* str)
     }
 }
 
-int writeFont(const char* filename, unsigned int fontSize, const char* id, bool fontpreview = false)
+int writeFont(const char* inFilePath, const char* outFilePath, unsigned int fontSize, const char* id, bool fontpreview = false)
 {
     Glyph glyphArray[END_INDEX - START_INDEX];
     
@@ -48,7 +49,7 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
     
     // Initialize font face.
     FT_Face face;
-    error = FT_New_Face(library, filename, 0, &face);
+    error = FT_New_Face(library, inFilePath, 0, &face);
     if (error)
     {
         fprintf(stderr, "FT_New_Face error: %d \n", error);
@@ -249,15 +250,9 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
         penX += advance; // Move X to next glyph position
         i++;
     }
-    
-    unsigned int idlen = strlen(id);
 
-    // Write it to the id.gpb file.
-    char* fileName = (char*)malloc(idlen + 4);
-    strcpy(fileName, id);
-    strcat(fileName, ".gpb");
 
-    FILE *gpbFp = fopen(fileName, "wb");
+    FILE *gpbFp = fopen(outFilePath, "wb");
     
     // File header and version.
     char fileHeader[9]     = {'«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n'};
@@ -303,15 +298,14 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
     // Close file.
     fclose(gpbFp);
 
-    printf("%s.gpb created successfully! \n", id);
+    printf("%s.gpb created successfully. \n", getBaseName(outFilePath).c_str());
 
     if (fontpreview)
     {
         // Write out font map to an image.
-        strcpy(fileName, id);
-        strcat(fileName, ".pgm");
-
-        FILE *imageFp = fopen(fileName, "wb");
+        std::string pgmFilePath = getFilenameNoExt(outFilePath);
+        pgmFilePath.append(".pgm");
+        FILE *imageFp = fopen(pgmFilePath.c_str(), "wb");
         fprintf(imageFp, "P5 %d %d 255\n", imageWidth, imageHeight);
         fwrite((const char *)imageBuffer, sizeof(unsigned char), imageWidth * imageHeight, imageFp);
         fclose(imageFp);

+ 12 - 2
gameplay-encoder/src/TTFFontEncoder.h

@@ -3,7 +3,6 @@
 
 #define START_INDEX     32
 #define END_INDEX       127
-
 #define GLYPH_PADDING   4
 
 namespace gameplay
@@ -18,6 +17,17 @@ public:
     float uvCoords[4];
 };
 
-int writeFont(const char* filename, unsigned int fontSize, const char* id, bool fontpreview);
+/**
+ * Writes the font gpb file.
+ * 
+ * @param inFilePath Input file path to the tiff file.
+ * @param outFilePath Output file path to write the gpb to.
+ * @param fontSize Size of the font.
+ * @param id ID string of the font in the ref table.
+ * @param fontpreview True if the pgm font preview file should be written. (For debugging)
+ * 
+ * @return 0 if successful, -1 if error.
+ */
+int writeFont(const char* inFilePath, const char* outFilePath, unsigned int fontSize, const char* id, bool fontpreview);
 
 }

+ 28 - 12
gameplay-encoder/src/main.cpp

@@ -7,16 +7,28 @@
 
 using namespace gameplay;
 
-static std::string getFileName(const std::string& filepath)
+/**
+ * Prompts the user for a font size until a valid font size is entered.
+ * 
+ * @return A valid font size.
+ */
+static unsigned int promptUserFontSize()
 {
-    size_t index1 = filepath.find_last_of('\\');
-    size_t index2 = filepath.find_last_of('/');
-    size_t index = (index1 != -1 && index1 > index2 ? index1 : index2);
-    size_t length = filepath.length();
-    std::string filename = filepath.substr(index + 1, length);
-    length = filename.length();
-    std::string output = filename.substr(0, (length-4));
-    return output;
+    static const int lowerBound = 8;
+    static const int upperBound = 500;
+    unsigned int fontSize = 0;
+    char buffer[80];
+    do
+    {
+        printf("Enter font size (between %d and %d):\n", lowerBound, upperBound);
+        std::cin.getline(buffer, 80);
+        int i = atoi(buffer);
+        if (i >= lowerBound && i <= upperBound)
+        {
+            fontSize = (unsigned int)i;
+        }
+    } while (fontSize == 0);
+    return fontSize;
 }
 
 /**
@@ -74,9 +86,13 @@ int main(int argc, const char** argv)
         }
     case EncoderArguments::FILEFORMAT_TTF:
         {
-            std::string realpath(arguments.getFilePath());
-            std::string id = getFileName(realpath);
-            writeFont(realpath.c_str(), arguments.getFontSize(), id.c_str(), arguments.fontPreviewEnabled());
+            unsigned int fontSize = arguments.getFontSize();
+            if (fontSize == 0)
+            {
+                fontSize = promptUserFontSize();
+            }
+            std::string id = getBaseName(arguments.getFilePath());
+            writeFont(arguments.getFilePath().c_str(), arguments.getOutputFilePath().c_str(), fontSize, id.c_str(), arguments.fontPreviewEnabled());
             break;
         }
     case EncoderArguments::FILEFORMAT_GPB:

+ 2 - 2
gameplay-template/res/box.material

@@ -2,7 +2,7 @@ material box
 {
     technique
     {
-        pass
+        pass 0
         {
             // shaders
             vertexShader = res/colored.vsh
@@ -12,7 +12,7 @@ material box
             u_worldViewProjectionMatrix = WORLD_VIEW_PROJECTION_MATRIX
             u_inverseTransposeWorldViewMatrix = INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX
             u_ambientColor = 0.2, 0.2, 0.2
-            u_diffuseColor = 1.0, 1.0, 1.0, 1.0
+            u_baseColor = 1.0, 1.0, 1.0, 1.0
 
             // render state
             renderState

+ 16 - 92
gameplay-template/res/colored.fsh

@@ -3,109 +3,33 @@ precision highp float;
 #endif
 
 // Uniforms
+uniform vec3 u_lightDirection;       	        // Light direction
 uniform vec3 u_lightColor;                      // Light color
 uniform vec3 u_ambientColor;                    // Ambient color
-uniform vec4 u_diffuseColor;                    // Diffuse color
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
+uniform vec4 u_baseColor;                    	// Base color
 
 // Inputs
-varying vec3 v_normalVector;                    // NormalVector in view space.
-
-// Global variables
-vec4 _baseColor;                                // Base color
-vec3 _ambientColor;                             // Ambient Color
-vec3 _diffuseColor;                             // Diffuse Color
-
-void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-    float ddot = dot(normalVector, lightDirection);
-    float diffuseIntensity = attenuation * ddot;
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-}
-
-#if defined(POINT_LIGHT)
+varying vec3 v_normalVector;                    // Normal vector in view space.
 
-varying vec4 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection.xyz);
-    
-    // Fetch point light attenuation.
-    float pointLightAttenuation = v_vertexToPointLightDirection.w;
-    lighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightDirection;              // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;           // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
+void main()
 {
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 spotLightDirection = u_spotLightDirection; 
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-
-    // "-lightDirection" is used because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
-}
+	// Base color
+    vec4 baseColor = u_baseColor;
 
-#else
-
-uniform vec3 u_lightDirection;       	        // Light direction
-
-void applyLight()
-{
     // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
     vec3 lightDirection = normalize(u_lightDirection);
+    vec3 normalVector = normalize(v_normalVector);
 
-    lighting(normalVector, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Fetch diffuse color from texture.
-    _baseColor = u_diffuseColor;
+    // Ambient
+    vec3 ambientColor = baseColor.rgb * u_ambientColor;
 
-    // Apply light
-    applyLight();
+    // Diffuse
+	float attenuation = 1.0;
+    float ddot = dot(normalVector, lightDirection);
+    float intensity =  max(0.0, attenuation * ddot);
+    vec3 diffuseColor = u_lightColor * baseColor.rgb * intensity;
 
     // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
+    gl_FragColor.a = baseColor.a;
+    gl_FragColor.rgb = ambientColor + diffuseColor;
 }

+ 4 - 164
gameplay-template/res/colored.vsh

@@ -7,177 +7,17 @@ attribute vec4 a_position;                          // Vertex Position (x, y, z,
 attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
 
 // Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space.
-
-#if defined(SKINNING)
-
-attribute vec4 a_blendWeights;
-attribute vec4 a_blendIndices;
-
-// 32 4x3 matrices as an array of floats
-uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
-
-// Common vectors.
-vec4 _skinnedPosition;
-vec3 _skinnedNormal;
-
-void skinPosition(float blendWeight, int matrixIndex)
-{
-    vec4 tmp;
-
-    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
-    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
-    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
-    tmp.w = a_position.w;
-
-    _skinnedPosition += blendWeight * tmp;
-}
-
-vec4 getPosition()
-{
-    _skinnedPosition = vec4(0.0);
-
-    // Transform position to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    return _skinnedPosition;    
-}
-
-void skinNormal(float blendWeight, int matrixIndex)
-{
-    vec3 tmp;
-
-    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
-    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
-    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
-
-    _skinnedNormal += blendWeight * tmp;
-}
-
-vec3 getNormal()
-{
-    _skinnedNormal = vec3(0.0);
-
-    // Transform normal to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    return _skinnedNormal;
-}
-
-#else
-
-vec4 getPosition()
-{
-    return a_position;    
-}
-
-vec3 getNormal()
-{
-    return a_normal;
-}
-
-#endif
-
-#if defined(POINT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRangeInverse;             // Inverse of light range.
-varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
-
-void applyLight(vec4 position)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-    
-    // Compute the light direction.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-    
-    vec4 vertexToPointLightDirection;
-    vertexToPointLightDirection.xyz = lightDirection;
-    
-    // Attenuation.
-    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToPointLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_spotLightPosition;                   // Position
-uniform float u_spotLightRangeInverse;              // Inverse of light range.
-varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;               // Attenuation of spot light.
-
-void applyLight(vec4 position)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-
-    // Compute the light direction.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-void applyLight(vec4 position)
-{
-}
-
-#endif
+varying vec3 v_normalVector;                        // Normal vector in view space.
 
 void main()
 {
-    vec4 position = getPosition();
-    vec3 normal = getNormal();
+    vec4 position = a_position;
+    vec3 normal = a_normal;
         
     // Transform position to clip space.
     gl_Position = u_worldViewProjectionMatrix * position;
 
     // Transform normal to view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
-                                                u_inverseTransposeWorldViewMatrix[1].xyz,
-                                                u_inverseTransposeWorldViewMatrix[2].xyz);
+    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz, u_inverseTransposeWorldViewMatrix[1].xyz, u_inverseTransposeWorldViewMatrix[2].xyz);
     v_normalVector = inverseTransposeWorldViewMatrix * normal;
-
-    // Apply light.
-    applyLight(position);
 }

+ 17 - 2
gameplay-template/src/TemplateGame.cpp

@@ -26,6 +26,8 @@ void TemplateGame::initialize()
     Node* boxNode = _scene->findNode("box");
     Model* boxModel = boxNode->getModel();
     Material* boxMaterial = boxModel->setMaterial("res/box.material");
+	boxMaterial->getParameter("u_ambientColor")->setValue(_scene->getAmbientColor());
+	boxMaterial->getParameter("u_ambientColor")->setValue(_scene->getAmbientColor());
     boxMaterial->getParameter("u_lightColor")->setValue(light->getColor());
     boxMaterial->getParameter("u_lightDirection")->setValue(lightNode->getForwardVectorView());
 }
@@ -35,13 +37,13 @@ void TemplateGame::finalize()
     SAFE_RELEASE(_scene);
 }
 
-void TemplateGame::update(long elapsedTime)
+void TemplateGame::update(float elapsedTime)
 {
     // Rotate model
     _scene->findNode("box")->rotateY(MATH_DEG_TO_RAD((float)elapsedTime / 1000.0f * 180.0f));
 }
 
-void TemplateGame::render(long elapsedTime)
+void TemplateGame::render(float elapsedTime)
 {
     // Clear the color and depth buffers
     clear(CLEAR_COLOR_DEPTH, Vector4::zero(), 1.0f, 0);
@@ -61,6 +63,19 @@ bool TemplateGame::drawScene(Node* node)
     return true;
 }
 
+void TemplateGame::keyEvent(Keyboard::KeyEvent evt, int key)
+{
+    if (evt == Keyboard::KEY_PRESS)
+    {
+        switch (key)
+        {
+        case Keyboard::KEY_ESCAPE:
+            exit();
+            break;
+        }
+    }
+}
+
 void TemplateGame::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
     switch (evt)

+ 7 - 2
gameplay-template/src/TemplateGame.h

@@ -17,6 +17,11 @@ public:
      */
     TemplateGame();
 
+    /**
+     * @see Game::keyEvent
+     */
+	void keyEvent(Keyboard::KeyEvent evt, int key);
+	
     /**
      * @see Game::touchEvent
      */
@@ -37,12 +42,12 @@ protected:
     /**
      * @see Game::update
      */
-    void update(long elapsedTime);
+    void update(float elapsedTime);
 
     /**
      * @see Game::render
      */
-    void render(long elapsedTime);
+    void render(float elapsedTime);
 
 private:
 

+ 21 - 20
gameplay/gameplay.vcxproj

@@ -43,6 +43,7 @@
     <ClCompile Include="src\FrameBuffer.cpp" />
     <ClCompile Include="src\Frustum.cpp" />
     <ClCompile Include="src\Game.cpp" />
+    <ClCompile Include="src\Gamepad.cpp" />
     <ClCompile Include="src\gameplay-main-android.cpp" />
     <ClCompile Include="src\gameplay-main-qnx.cpp" />
     <ClCompile Include="src\gameplay-main-win32.cpp" />
@@ -135,6 +136,7 @@
     <ClInclude Include="src\FrameBuffer.h" />
     <ClInclude Include="src\Frustum.h" />
     <ClInclude Include="src\Game.h" />
+    <ClInclude Include="src\Gamepad.h" />
     <ClInclude Include="src\gameplay.h" />
     <ClInclude Include="src\Image.h" />
     <ClInclude Include="src\Joint.h" />
@@ -204,26 +206,25 @@
     <None Include="res\logo_powered_black.png" />
     <None Include="res\logo_powered_white.png" />
     <None Include="res\logo_white.png" />
-    <None Include="res\shaders\bumped-specular.fsh" />
-    <None Include="res\shaders\bumped-specular.vsh" />
-    <None Include="res\shaders\bumped.fsh" />
-    <None Include="res\shaders\bumped.vsh" />
-    <None Include="res\shaders\colored-specular.fsh" />
-    <None Include="res\shaders\colored-specular.vsh" />
-    <None Include="res\shaders\colored.fsh" />
-    <None Include="res\shaders\colored.vsh" />
-    <None Include="res\shaders\diffuse-specular.fsh" />
-    <None Include="res\shaders\diffuse-specular.vsh" />
-    <None Include="res\shaders\diffuse.fsh" />
-    <None Include="res\shaders\diffuse.vsh" />
-    <None Include="res\shaders\parallax-specular.fsh" />
-    <None Include="res\shaders\parallax-specular.vsh" />
-    <None Include="res\shaders\parallax.fsh" />
-    <None Include="res\shaders\parallax.vsh" />
-    <None Include="res\shaders\solid.fsh" />
-    <None Include="res\shaders\solid.vsh" />
-    <None Include="res\shaders\textured.fsh" />
-    <None Include="res\shaders\textured.vsh" />
+    <None Include="res\shaders\bumped.frag" />
+    <None Include="res\shaders\bumped.vert" />
+    <None Include="res\shaders\colored-unlit.frag" />
+    <None Include="res\shaders\colored-unlit.vert" />
+    <None Include="res\shaders\colored.frag" />
+    <None Include="res\shaders\colored.vert" />
+    <None Include="res\shaders\lib\attributes-skinning.vert" />
+    <None Include="res\shaders\lib\attributes.vert" />
+    <None Include="res\shaders\lib\lighting-directional.frag" />
+    <None Include="res\shaders\lib\lighting-directional.vert" />
+    <None Include="res\shaders\lib\lighting-point.frag" />
+    <None Include="res\shaders\lib\lighting-point.vert" />
+    <None Include="res\shaders\lib\lighting-spot.frag" />
+    <None Include="res\shaders\lib\lighting-spot.vert" />
+    <None Include="res\shaders\lib\lighting.frag" />
+    <None Include="res\shaders\textured-unlit.frag" />
+    <None Include="res\shaders\textured-unlit.vert" />
+    <None Include="res\shaders\textured.frag" />
+    <None Include="res\shaders\textured.vert" />
     <None Include="src\BoundingBox.inl" />
     <None Include="src\BoundingSphere.inl" />
     <None Include="src\Curve.inl" />

+ 66 - 60
gameplay/gameplay.vcxproj.filters

@@ -10,6 +10,9 @@
     <Filter Include="res\shaders">
       <UniqueIdentifier>{be0b36f1-49ed-4a06-9f1f-57c654a554fe}</UniqueIdentifier>
     </Filter>
+    <Filter Include="res\shaders\lib">
+      <UniqueIdentifier>{ab587dd0-fd08-4b5e-a38d-7b3a706ab53b}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\Animation.cpp">
@@ -279,6 +282,9 @@
     <ClCompile Include="src\Joystick.cpp">
       <Filter>src</Filter>
     </ClCompile>
+    <ClCompile Include="src\Gamepad.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -557,68 +563,11 @@
     <ClInclude Include="src\MathUtil.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="src\Gamepad.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <None Include="res\shaders\bumped-specular.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\colored.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\colored.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\colored-specular.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\colored-specular.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\diffuse.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\diffuse.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\diffuse-specular.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\diffuse-specular.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\parallax.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\parallax.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\parallax-specular.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\parallax-specular.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\solid.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\solid.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\textured.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\textured.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\bumped.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\bumped.vsh">
-      <Filter>res\shaders</Filter>
-    </None>
-    <None Include="res\shaders\bumped-specular.fsh">
-      <Filter>res\shaders</Filter>
-    </None>
     <None Include="src\gameplay-main-macosx.mm">
       <Filter>src</Filter>
     </None>
@@ -664,6 +613,63 @@
     <None Include="src\Joystick.inl">
       <Filter>src</Filter>
     </None>
+    <None Include="res\shaders\textured.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\textured.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\textured-unlit.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\textured-unlit.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored-unlit.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored-unlit.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\bumped.vert">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\bumped.frag">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\lib\lighting.frag">
+      <Filter>res\shaders\lib</Filter>
+    </None>
+    <None Include="res\shaders\lib\lighting-spot.vert">
+      <Filter>res\shaders\lib</Filter>
+    </None>
+    <None Include="res\shaders\lib\lighting-spot.frag">
+      <Filter>res\shaders\lib</Filter>
+    </None>
+    <None Include="res\shaders\lib\lighting-point.vert">
+      <Filter>res\shaders\lib</Filter>
+    </None>
+    <None Include="res\shaders\lib\lighting-point.frag">
+      <Filter>res\shaders\lib</Filter>
+    </None>
+    <None Include="res\shaders\lib\lighting-directional.vert">
+      <Filter>res\shaders\lib</Filter>
+    </None>
+    <None Include="res\shaders\lib\lighting-directional.frag">
+      <Filter>res\shaders\lib</Filter>
+    </None>
+    <None Include="res\shaders\lib\attributes.vert">
+      <Filter>res\shaders\lib</Filter>
+    </None>
+    <None Include="res\shaders\lib\attributes-skinning.vert">
+      <Filter>res\shaders\lib</Filter>
+    </None>
   </ItemGroup>
   <ItemGroup>
     <None Include="src\PhysicsFixedConstraint.inl">

+ 0 - 124
gameplay/res/shaders/bumped-specular.fsh

@@ -1,124 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec3 u_lightColor;                  // Light color.
-uniform vec3 u_ambientColor;                // Ambient color.
-uniform float u_specularExponent;           // Specular exponent or shininess property.
-uniform sampler2D u_diffuseTexture;         // Diffuse texture.
-uniform sampler2D u_normalMapTexture;       // Normal map texture.
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
-
-// Inputs
-varying vec2 v_texCoord;                    // Texture Coordinate.
-varying vec3 v_cameraDirection;             // Direction the camera is looking at in tangent space.
-
-// Global variables
-vec4 _baseColor;                            // Base color
-vec3 _ambientColor;                         // Ambient Color
-vec3 _diffuseColor;                         // Diffuse Color
-vec3 _specularColor;                        // Specular color
-
-void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-    float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-
-    // Specular
-    vec3 halfVector = normalize(cameraDirection + lightDirection);
-    float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
-    specularIntensity = max(0.0, specularIntensity);
-    _specularColor = u_lightColor * _baseColor.rgb * specularIntensity;
-}
-
-#if defined(POINT_LIGHT)
-
-varying vec3 v_vertexToPointLightDirection;   // Light direction w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;        // Attenuation of point light.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    // Fetch normals from the normal map.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
-    
-    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
-    
-    lighting(normalVector, cameraDirection, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform float u_spotLightInnerAngleCos;       // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;       // The soft outer part [0.0 - 1.0]
-varying vec3 v_spotLightDirection;            // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;    // Direction of the spot light w.r.t current vertex in tangent space.
-varying float v_spotLightAttenuation;         // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
-{
-    // Fetch normals from the normal map.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 spotLightDirection = normalize(v_spotLightDirection);
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-    
-    // "-lightDirection" because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-    
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    lighting(normalVector, cameraDirection, vertexToSpotLightDirection, spotLightAttenuation);
-}
-
-#else
-
-varying vec3 v_lightDirection;                 // Direction of light in tangent space.
-
-void applyLight()
-{
-    // Fetch normals from the normal map
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 lightDirection = normalize(v_lightDirection);
-
-    lighting(normalVector, cameraDirection, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, v_texCoord);
-
-    // Apply light
-    applyLight();
-
-    // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 0 - 248
gameplay/res/shaders/bumped-specular.vsh

@@ -1,248 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
-uniform vec3 u_cameraPosition;                      // Position of the camera.
-
-// Inputs
-attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                          // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                           // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                          // Vertex Binormal (actually Bi-tangent) (x, y, z)
-
-// Outputs
-varying vec2 v_texCoord;                            // Texture Coordinate (u,v)
-varying vec3 v_cameraDirection;                     // Direction the camera is looking at in tangent space.
-
-#if defined(SKINNING)
-
-attribute vec4 a_blendWeights;
-attribute vec4 a_blendIndices;
-
-// 32 4x3 matrices as an array of floats
-uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
-
-// Common vectors.
-vec4 _skinnedPosition;
-vec3 _skinnedNormal;
-
-void skinPosition(float blendWeight, int matrixIndex)
-{
-    vec4 tmp;
-
-    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
-    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
-    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
-    tmp.w = a_position.w;
-
-    _skinnedPosition += blendWeight * tmp;
-}
-
-vec4 getPosition()
-{
-    _skinnedPosition = vec4(0.0);
-
-    // Transform position to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    return _skinnedPosition;    
-}
-
-void skinTangentSpaceVector(vec3 vector, float blendWeight, int matrixIndex)
-{
-    vec3 tmp;
-
-    tmp.x = dot(vector, u_matrixPalette[matrixIndex].xyz);
-    tmp.y = dot(vector, u_matrixPalette[matrixIndex + 1].xyz);
-    tmp.z = dot(vector, u_matrixPalette[matrixIndex + 2].xyz);
-
-    _skinnedNormal += blendWeight * tmp;
-}
-
-vec3 getTangentSpaceVector(vec3 vector)
-{
-    _skinnedNormal = vec3(0.0);
-
-    // Transform normal to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
-
-    return _skinnedNormal;
-}
-
-vec3 getNormal()
-{
-    return getTangentSpaceVector(a_normal);
-}
-
-vec3 getTangent()
-{
-    return getTangentSpaceVector(a_tangent);
-}
-
-vec3 getBinormal()
-{
-    return getTangentSpaceVector(a_binormal);
-}
-
-#else
-
-vec4 getPosition()
-{
-    return a_position;    
-}
-
-vec3 getNormal()
-{
-    return a_normal;
-}
-
-vec3 getTangent()
-{
-    return a_tangent;
-}
-
-vec3 getBinormal()
-{
-    return a_binormal;
-}
-
-#endif
-
-#if defined(POINT_LIGHT)
-
-uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRangeInverse;             // Inverse of light range 
-varying vec3 v_vertexToPointLightDirection;         // Direction of point light w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;              // Attenuation of point light.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-    
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-    
-    // Transform current light direction to tangent space.
-    vec3 vertexToPointLightDirection = tangentSpaceTransformMatrix * lightDirection;
-
-    // Attenuation
-    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToPointLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightPosition;                   // Position
-uniform float u_spotLightRangeInverse;              // Inverse of light range.
-uniform vec3 u_spotLightDirection;                  // Direction
-varying vec3 v_spotLightDirection;                  // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;          // Direction of the spot light w.r.t current vertex in tangent space.
-varying float v_spotLightAttenuation;               // Attenuation of spot light.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-
-    // Transform spot light direction to tangent space.
-    v_spotLightDirection = tangentSpaceTransformMatrix * u_spotLightDirection;
-
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-    
-    // Transform current light direction to tangent space.
-    lightDirection = tangentSpaceTransformMatrix * lightDirection;
-    
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-uniform vec3 u_lightDirection;                      // Direction
-varying vec3 v_lightDirection;                      // Direction of light in tangent space.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-    
-    // Transform light direction to tangent space.
-    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
-}
-
-#endif
-
-void main()
-{
-    vec4 position = getPosition();
-    vec3 normal = getNormal();
-    vec3 tangent = getTangent();
-    vec3 binormal = getBinormal();
-    
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * position;
-
-    // Transform the normal, tangent and binormals to  view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
-                                                u_inverseTransposeWorldViewMatrix[1].xyz,
-                                                u_inverseTransposeWorldViewMatrix[2].xyz);
-    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * tangent);
-    vec3 normalVector = normalize(inverseTransposeWorldViewMatrix * normal);
-    vec3 binormalVector = normalize(inverseTransposeWorldViewMatrix * binormal);
-
-    // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x,
-                                            tangentVector.y, binormalVector.y, normalVector.y,
-                                            tangentVector.z, binormalVector.z, normalVector.z);
-    // Apply light.
-    applyLight(tangentSpaceTransformMatrix);
-
-    // Pass on the texture coordinates to Fragment shader.
-    v_texCoord = a_texCoord;
-}

+ 69 - 0
gameplay/res/shaders/bumped.frag

@@ -0,0 +1,69 @@
+#define LIGHTING
+#define BUMPED
+#ifdef OPENGL_ES
+precision highp float;
+#endif
+
+// Inputs
+varying vec3 v_normalVector;					// Normal vector in view space
+varying vec2 v_texCoord;						// Texture Coordinate
+#if defined(SPECULAR)
+varying vec3 v_cameraDirection;                 // Camera direction
+#endif
+#if defined(POINT_LIGHT)
+varying vec3 v_vertexToPointLightDirection;		// Light direction w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;			// Attenuation of point light.
+#elif defined(SPOT_LIGHT)
+varying vec3 v_spotLightDirection;				// Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;		// Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;			// Attenuation of spot light.
+#else
+varying vec3 v_lightDirection;					// Direction of light in tangent space.
+#endif
+#if defined(SPECULAR)
+varying vec3 v_cameraDirection;                 // Camera direction
+#endif
+
+// Uniforms
+uniform sampler2D u_textureDiffuse;        		// Diffuse map texture
+uniform sampler2D u_textureNormal;       		// Normal map texture
+uniform vec3 u_lightDirection;					// Light direction
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_ambientColor;                    // Ambient color
+#if defined(SPECULAR)
+uniform float u_specularExponent;				// Specular exponent.
+#endif
+#if defined(MODULATE_COLOR)
+uniform vec4 u_modulateColor;					// Modulation color
+#endif
+#if defined(MODULATE_ALPHA)
+uniform float u_modulateAlpha;					// Modulation alpha
+#endif
+#include "lib/lighting.frag"
+#if defined(POINT_LIGHT)
+#include "lib/lighting-point.frag"
+#elif defined(SPOT_LIGHT)
+uniform float u_spotLightInnerAngleCos;			// The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;			// The soft outer part [0.0 - 1.0]
+#include "lib/lighting-spot.frag"
+#else
+#include "lib/lighting-directional.frag"
+#endif
+
+void main()
+{
+    // Fetch diffuse color from texture.
+    _baseColor = texture2D(u_textureDiffuse, v_texCoord);
+
+    // Light the pixel
+    gl_FragColor.a = _baseColor.a;
+    gl_FragColor.rgb = getLitPixel();
+
+	// Global color modulation
+	#if defined(MODULATE_COLOR)
+	gl_FragColor *= u_modulateColor;
+	#endif
+	#if defined(MODULATE_ALPHA)
+    gl_FragColor.a *= u_modulateAlpha;
+    #endif
+}

+ 0 - 113
gameplay/res/shaders/bumped.fsh

@@ -1,113 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec3 u_lightColor;                   // Light color.
-uniform vec3 u_ambientColor;                 // Ambient color.
-uniform sampler2D u_diffuseTexture;          // Diffuse texture.
-uniform sampler2D u_normalMapTexture;        // Normal map texture.
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
-
-// Inputs
-varying vec2 v_texCoord;                     // Texture Coordinate.
-
-// Common colors
-vec4 _baseColor;                             // Base color
-vec3 _ambientColor;                          // Ambient Color
-vec3 _diffuseColor;                          // Diffuse Color
-
-void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-    float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-}
-
-#if defined(POINT_LIGHT)
-
-varying vec3 v_vertexToPointLightDirection;  // Light direction w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;       // Attenuation of point light.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    // Fetch normals from the normal map.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
-    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
-    
-    // Fetch point light attenuation.
-    lighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform float u_spotLightInnerAngleCos;       // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;       // The soft outer part [0.0 - 1.0]
-varying vec3 v_spotLightDirection;            // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;    // Direction of the spot light w.r.t current vertex in tangent space.
-varying float v_spotLightAttenuation;         // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
-{
-    // Fetch normals from the normal map.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).xyz * 2.0 - 1.0);
-    vec3 spotLightDirection =normalize(v_spotLightDirection);
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-    
-    // "-lightDirection" because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-    
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
-}
-
-#else
-
-varying vec3 v_lightDirection;                  // Direction of light in tangent space.
-
-void applyLight()
-{
-    // Normalize vectors.
-    // Fetch normals from the normal map
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).xyz * 2.0 - 1.0);
-    vec3 lightDirection = normalize(v_lightDirection);
-
-    lighting(normalVector, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, v_texCoord);
-
-    // Apply light
-    applyLight();
-
-    // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 94 - 0
gameplay/res/shaders/bumped.vert

@@ -0,0 +1,94 @@
+#define LIGHTING
+#define BUMPED
+
+// Uniforms
+uniform mat4 u_worldViewProjectionMatrix;					// Matrix to transform a position to clip space
+uniform mat4 u_inverseTransposeWorldViewMatrix;				// Matrix to transform a normal to view space
+#if defined(SKINNING)
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];		// Array of 4x3 matrices as an array of floats
+#endif
+#if defined(SPECULAR)
+uniform mat4 u_worldViewMatrix;								// Matrix to tranform a position to view space
+uniform vec3 u_cameraPosition;                 				// Position of the camera in view space
+#endi
+#if defined(TEXTURE_REPEAT)
+uniform vec2 u_textureRepeat;
+#endif
+#if defined(TEXTURE_OFFSET)
+uniform vec2 u_textureOffset;
+#endif
+#if defined(POINT_LIGHT)
+uniform vec3 u_pointLightPosition;							// Position
+uniform float u_pointLightRangeInverse;						// Inverse of light range
+#elif defined(SPOT_LIGHT)
+uniform vec3 u_spotLightPosition;							// Position
+uniform float u_spotLightRangeInverse;						// Inverse of light range
+uniform vec3 u_spotLightDirection;							// Direction
+#else
+uniform vec3 u_lightDirection;								// Direction
+#endif
+
+// Inputs
+attribute vec4 a_position;									// Vertex Position              (x, y, z, w)
+attribute vec3 a_normal;									// Vertex Normal                (x, y, z)
+attribute vec2 a_texCoord;									// Vertex Texture Coordinate    (u, v)
+attribute vec3 a_tangent;									// Vertex Tangent               (x, y, z)
+attribute vec3 a_binormal;									// Vertex Binormal/Bitangent    (x, y, z)
+
+// Outputs
+varying vec3 v_normalVector;								// Normal vector in view space
+varying vec2 v_texCoord;									// Output Texture Coordinate     (u,v)
+// Lighting
+#if defined(POINT_LIGHT)
+varying vec3 v_vertexToPointLightDirection;					// Direction of point light w.r.t current vertex in tangent space
+varying float v_pointLightAttenuation;						// Attenuation of point light
+#include "lib/lighting-point.vert"
+#elif defined(SPOT_LIGHT)
+varying vec3 v_vertexToSpotLightDirection;					// Direction of the spot light w.r.t current vertex in tangent space
+varying float v_spotLightAttenuation;						// Attenuation of spot light
+varying vec3 v_spotLightDirection;							// Direction of spot light in tangent space
+#include "lib/lighting-spot.vert"
+#else
+uniform vec3 u_lightDirection;								// Direction of light
+#include "lib/lighting-directional.vert"
+#endif
+
+// Vertex Attribute Accessors
+#if defined(SKINNING)
+#include "lib/attributes-skinning.vert"
+#else
+#include "lib/attributes.vert" 
+#endif
+
+void main()
+{
+    // Get the position, normal, tangents and binormals.
+    vec4 position = getPosition();
+    vec3 normal = getNormal();
+    vec3 tangent = getTangent();
+    vec3 binormal = getBinormal();
+    
+    // Transform position to clip space.
+    gl_Position = u_worldViewProjectionMatrix * position;
+
+    // Transform the normal, tangent and binormals to view space.
+    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz, u_inverseTransposeWorldViewMatrix[1].xyz, u_inverseTransposeWorldViewMatrix[2].xyz);
+    vec3 normalVector = normalize(inverseTransposeWorldViewMatrix * normal);
+    
+    // Create a transform to convert a vector to tangent space.
+    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * tangent);
+    vec3 binormalVector = normalize(inverseTransposeWorldViewMatrix * binormal);
+    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x, tangentVector.y, binormalVector.y, normalVector.y, tangentVector.z, binormalVector.z, normalVector.z);
+    
+    // Apply light.
+    applyLight(tangentSpaceTransformMatrix);
+    
+    // Texture transformation.
+    v_texCoord = a_texCoord;
+    #if defined(TEXTURE_REPEAT)
+    v_texCoord *= u_textureRepeat;
+    #endif
+    #if defined(TEXTURE_OFFSET)
+    v_texCoord += u_textureOffset;
+    #endif
+}

+ 0 - 236
gameplay/res/shaders/bumped.vsh

@@ -1,236 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewProjectionMatrix;       // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix; // Matrix to transform a normal to view space.
-
-// Inputs
-attribute vec4 a_position;                      // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                        // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                      // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                       // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                      // Vertex Binormal (actually Bi-tangent) (x, y, z)
-
-// Outputs
-varying vec2 v_texCoord;                        // Texture Coordinate (u,v)
-
-#if defined(SKINNING)
-
-attribute vec4 a_blendWeights;
-attribute vec4 a_blendIndices;
-
-// 32 4x3 matrices as an array of floats
-uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
-
-// Common vectors.
-vec4 _skinnedPosition;
-vec3 _skinnedNormal;
-
-void skinPosition(float blendWeight, int matrixIndex)
-{
-    vec4 tmp;
-
-    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
-    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
-    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
-    tmp.w = a_position.w;
-
-    _skinnedPosition += blendWeight * tmp;
-}
-
-vec4 getPosition()
-{
-    _skinnedPosition = vec4(0.0);
-
-    // Transform position to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    return _skinnedPosition;    
-}
-
-void skinTangentSpaceVector(vec3 vector, float blendWeight, int matrixIndex)
-{
-    vec3 tmp;
-
-    tmp.x = dot(vector, u_matrixPalette[matrixIndex].xyz);
-    tmp.y = dot(vector, u_matrixPalette[matrixIndex + 1].xyz);
-    tmp.z = dot(vector, u_matrixPalette[matrixIndex + 2].xyz);
-
-    _skinnedNormal += blendWeight * tmp;
-}
-
-vec3 getTangentSpaceVector(vec3 vector)
-{
-    _skinnedNormal = vec3(0.0);
-
-    // Transform normal to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
-
-    return _skinnedNormal;
-}
-
-vec3 getNormal()
-{
-    return getTangentSpaceVector(a_normal);
-}
-
-vec3 getTangent()
-{
-    return getTangentSpaceVector(a_tangent);
-}
-
-vec3 getBinormal()
-{
-    return getTangentSpaceVector(a_binormal);
-}
-
-#else
-
-vec4 getPosition()
-{
-    return a_position;    
-}
-
-vec3 getNormal()
-{
-    return a_normal;
-}
-
-vec3 getTangent()
-{
-    return a_tangent;
-}
-
-vec3 getBinormal()
-{
-    return a_binormal;
-}
-
-#endif
-
-#if defined(POINT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                 // Matrix to tranform a position to view space.
-uniform vec3 u_pointLightPosition;              // Position
-uniform float u_pointLightRangeInverse;         // Inverse of light range.
-varying vec3 v_vertexToPointLightDirection;     // Direction of point light w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;          // Attenuation of point light.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    // World space position.
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-    
-    // Transform current light direction to tangent space.
-    vec3 vertexToSpotLightDirection = tangentSpaceTransformMatrix * lightDirection;
-
-    // Attenuation
-    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToSpotLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                 // Matrix to tranform a position to view space.
-uniform vec3 u_spotLightPosition;               // Position
-uniform float u_spotLightRangeInverse;          // Inverse of light range.
-uniform vec3 u_spotLightDirection;              // Direction
-varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;      // Direction of the spot light w.r.t current vertex in tangent space.
-varying float v_spotLightAttenuation;           // Attenuation of spot light.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-
-    // Transform spot light direction to tangent space.
-    v_spotLightDirection = tangentSpaceTransformMatrix * u_spotLightDirection;
-
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-    
-    // Transform current light direction to tangent space.
-    lightDirection = tangentSpaceTransformMatrix * lightDirection;
-    
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-uniform vec3 u_lightDirection;                  // Direction
-varying vec3 v_lightDirection;                  // Direction of light in tangent space.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    // Transform light direction to tangent space.
-    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
-}
-
-#endif
-
-void main()
-{
-    vec4 position = getPosition();
-    vec3 normal = getNormal();
-    vec3 tangent = getTangent();
-    vec3 binormal = getBinormal();
-    
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * position;
-
-    // Transform the normal, tangent and binormals to  view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * tangent);
-    vec3 normalVector = normalize(inverseTransposeWorldViewMatrix * normal);
-    vec3 binormalVector = normalize(inverseTransposeWorldViewMatrix * binormal);
-
-    // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x,
-                                            tangentVector.y, binormalVector.y, normalVector.y,
-                                            tangentVector.z, binormalVector.z, normalVector.z);
-
-    // Apply light.
-    applyLight(tangentSpaceTransformMatrix);
-
-    // Pass on the texture coordinates to Fragment shader.
-    v_texCoord = a_texCoord;
-}

+ 0 - 132
gameplay/res/shaders/colored-specular.fsh

@@ -1,132 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec3 u_lightColor;                      // Light color
-uniform vec3 u_ambientColor;                    // Ambient color
-uniform float u_specularExponent;               // Specular exponent or shininess property
-#if !defined(VERTEX_COLOR)
-uniform vec4 u_diffuseColor;                    // Diffuse color
-#endif
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
-
-// Inputs
-varying vec3 v_normalVector;                    // NormalVector in view space
-varying vec3 v_cameraDirection;                 // Camera direction
-#if defined(VERTEX_COLOR)
-varying vec4 v_color;							// Vertex color
-#endif
-
-// Global variables
-vec4 _baseColor;                                // Base color
-vec3 _ambientColor;                             // Ambient Color
-vec3 _diffuseColor;                             // Diffuse Color
-vec3 _specularColor;                            // Specular color
-
-void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-    float ddot = abs(dot(normalVector, lightDirection));
-    float diffuseIntensity = attenuation * ddot;
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-
-    // Specular
-    vec3 halfVector = normalize(cameraDirection + lightDirection);
-    float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
-    specularIntensity = max(0.0, specularIntensity);
-    _specularColor = u_lightColor * _baseColor.rgb * specularIntensity;
-}
-
-#if defined(POINT_LIGHT)
-
-varying vec4 v_vertexToPointLightDirection;      // Light direction w.r.t current vertex.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection.xyz);
-
-    // Fetch point light attenuation.
-    float pointLightAttenuation = v_vertexToPointLightDirection.w;
-    lighting(normalVector, cameraDirection, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightDirection;              // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;           // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 spotLightDirection = normalize(u_spotLightDirection); 
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-
-    // "-lightDirection" is used because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    lighting(normalVector, cameraDirection, vertexToSpotLightDirection, spotLightAttenuation);
-}
-
-#else
-
-uniform vec3 u_lightDirection;                  // Light direction
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 lightDirection = normalize(u_lightDirection);
-
-    lighting(normalVector, cameraDirection, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Set base diffuse color
-#if defined(VERTEX_COLOR)
-	_baseColor = v_color;
-#else
-	_baseColor = u_diffuseColor;
-#endif
-
-    // Apply light
-    applyLight();
-
-    // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 0 - 203
gameplay/res/shaders/colored-specular.vsh

@@ -1,203 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
-uniform mat4 u_worldMatrix;                         // Matrix to tranform a position to world space.
-uniform vec3 u_cameraPosition;                      // Position of the camera.
-
-// Inputs
-attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-#if defined(VERTEX_COLOR)
-attribute vec4 a_color;
-#endif
-
-// Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space
-varying vec3 v_cameraDirection;                     // Camera direction
-#if defined(VERTEX_COLOR)
-varying vec4 v_color;								// Vertex color
-#endif
-
-#if defined(SKINNING)
-
-attribute vec4 a_blendWeights;
-attribute vec4 a_blendIndices;
-
-// 32 4x3 matrices as an array of floats
-uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
-
-// Common vectors.
-vec4 _skinnedPosition;
-vec3 _skinnedNormal;
-
-void skinPosition(float blendWeight, int matrixIndex)
-{
-    vec4 tmp;
-
-    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
-    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
-    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
-    tmp.w = a_position.w;
-
-    _skinnedPosition += blendWeight * tmp;
-}
-
-vec4 getPosition()
-{
-    _skinnedPosition = vec4(0.0);
-
-    // Transform position to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    return _skinnedPosition;    
-}
-
-void skinNormal(float blendWeight, int matrixIndex)
-{
-    vec3 tmp;
-
-    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
-    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
-    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
-
-    _skinnedNormal += blendWeight * tmp;
-}
-
-vec3 getNormal()
-{
-    _skinnedNormal = vec3(0.0);
-
-    // Transform normal to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    return _skinnedNormal;
-}
-
-#else
-
-vec4 getPosition()
-{
-    return a_position;    
-}
-
-vec3 getNormal()
-{
-    return a_normal;
-}
-
-#endif
-
-
-#if defined(POINT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRangeInverse;             // Inverse of light range. 
-varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
-
-void applyLight(vec4 position)
-{
-    // World space position.
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-    
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-    
-    vec4 vertexToPointLightDirection;
-    vertexToPointLightDirection.xyz = lightDirection;
-    
-    // Attenuation
-    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToPointLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_spotLightPosition;                   // Position
-uniform float u_spotLightRangeInverse;              // Inverse of light range.
-varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;               // Attenuation of spot light.
-
-void applyLight(vec4 position)
-{
-    // World space position.
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Compute the light direction with light position and the vertex position.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-void applyLight(vec4 position)
-{
-}
-
-#endif
-
-void main()
-{
-    vec4 position = getPosition();
-    vec3 normal = getNormal();
-
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * position;
-
-    // Transform normal to view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
-                                                u_inverseTransposeWorldViewMatrix[1].xyz,
-                                                u_inverseTransposeWorldViewMatrix[2].xyz);
-    v_normalVector = inverseTransposeWorldViewMatrix * normal;
-
-    // Compute the camera direction.
-    vec4 positionWorldSpace = u_worldMatrix * position;
-    v_cameraDirection = u_cameraPosition - positionWorldSpace.xyz;
-
-#if defined(VERTEX_COLOR)
-	v_color = a_color;
-#endif
-
-    // Apply light.
-    applyLight(position);
-}

+ 37 - 0
gameplay/res/shaders/colored-unlit.frag

@@ -0,0 +1,37 @@
+#ifdef OPENGL_ES
+precision highp float;
+#endif
+
+// Inputs
+#if defined(VERTEX_COLOR)
+varying vec3 v_color;						// Input Vertex color ( r g b )
+#endif
+
+uniform vec4 u_baseColor;               	// Base color
+
+// Uniforms
+#if defined(MODULATE_COLOR)
+uniform vec4 u_modulateColor;               // Modulation color
+#endif
+#if defined(MODULTE_ALPHA)
+uniform float u_modulateAlpha;              // Modulation alpha
+#endif
+
+// Fragment program
+void main()
+{
+    // Set base diffuse color
+    #if defined(VERTEX_COLOR)
+	gl_FragColor.rgb = v_color;
+	#else
+	gl_FragColor = u_baseColor;
+    #endif
+	
+	// Global color modulation
+	#if defined(MODULATE_COLOR)
+	gl_FragColor *= u_modulateColor;
+	#endif
+	#if defined(MODULTE_ALPHA)
+    gl_FragColor.a *= u_modulateAlpha;
+    #endif
+}

+ 39 - 0
gameplay/res/shaders/colored-unlit.vert

@@ -0,0 +1,39 @@
+// Inputs
+attribute vec4 a_position;									// Vertex Position							(x, y, z, w)
+#if defined(SKINNING)
+attribute vec4 a_blendWeights;								// Vertex blend weight, up to 4				(0, 1, 2, 3) 
+attribute vec4 a_blendIndices;								// Vertex blend index int u_matrixPalette	(0, 1, 2, 3)
+#endif
+#if defined(VERTEX_COLOR)
+attribute vec3 a_color;										// Vertex Color								(r, g, b)
+varying vec3 v_color;										// Output Vertex color						(r, g, b)
+#endif
+
+
+// Uniforms
+uniform mat4 u_worldViewProjectionMatrix;					// Matrix to transform a position to clip space.
+#if defined(SKINNING)
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];		// Array of 4x3 matrices as an array of floats
+#endif
+
+// Attribute accessor
+#if defined(SKINNING)
+#include "lib/attributes-skinning.vert"
+#else
+#include "lib/attributes.vert" 
+#endif
+
+// Vertex Program
+void main()
+{
+    // Get the vertex position
+    vec4 position = getPosition();
+    
+    // Transform position to clip space.a
+    gl_Position = u_worldViewProjectionMatrix *  position;
+    
+     // Pass on vertex color to fragment shader
+    #if defined(VERTEX_COLOR)
+	v_color = a_color;
+    #endif
+}

+ 70 - 0
gameplay/res/shaders/colored.frag

@@ -0,0 +1,70 @@
+#define LIGHTING
+#ifdef OPENGL_ES
+precision highp float;
+#endif
+
+// Inputs
+varying vec3 v_normalVector;					// Normal vector in view space
+#if defined(VERTEX_COLOR)
+varying vec3 v_color;							// Vertex color
+#endif
+#if defined(POINT_LIGHT)
+varying vec3 v_vertexToPointLightDirection;		// Light direction w.r.t current vertex in tangent space
+varying float v_pointLightAttenuation;			// Attenuation of point light
+#elif defined(SPOT_LIGHT)
+varying vec3 v_spotLightDirection;				// Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;		// Direction of the spot light w.r.t current vertex in tangent space
+varying float v_spotLightAttenuation;			// Attenuation of spot light
+#else
+varying vec3 v_lightDirection;					// Direction of light in tangent space
+#endif
+#if defined(SPECULAR)
+varying vec3 v_cameraDirection;                 // Camera direction
+#endif
+
+// Uniforms
+uniform vec4 u_baseColor;               		// Base color
+uniform vec3 u_lightDirection;					// Light direction
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_ambientColor;                    // Ambient color
+#if defined(SPECULAR)
+uniform float u_specularExponent;				// Specular exponent
+#endif
+#if defined(MODULATE_COLOR)
+uniform vec4 u_modulateColor;					// Modulation color
+#endif
+#if defined(MODULATE_ALPHA)
+uniform float u_modulateAlpha;					// Modulation alpha
+#endif
+#include "lib/lighting.frag"
+#if defined(POINT_LIGHT)
+#include "lib/lighting-point.frag"
+#elif defined(SPOT_LIGHT)
+uniform float u_spotLightInnerAngleCos;			// The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;			// The soft outer part [0.0 - 1.0]
+#include "lib/lighting-spot.frag"
+#else
+#include "lib/lighting-directional.frag"
+#endif
+
+// Fragment program
+void main()
+{
+    // Set base diffuse color
+    #if defined(VERTEX_COLOR)
+	_baseColor.rgb = v_color;
+	#else
+	_baseColor = u_baseColor;
+	#endif
+
+    // Light the pixel
+    gl_FragColor.a = _baseColor.a;
+    gl_FragColor.rgb = getLitPixel();
+    
+	#if defined(MODULATE_COLOR)
+    gl_FragColor.a *= u_modulateColor;
+    #endif
+	#if defined(MODULATE_ALPHA)
+    gl_FragColor.a *= u_modulateAlpha;
+    #endif
+}

+ 0 - 111
gameplay/res/shaders/colored.fsh

@@ -1,111 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec3 u_lightColor;                      // Light color
-uniform vec3 u_ambientColor;                    // Ambient color
-uniform vec4 u_diffuseColor;                    // Diffuse color
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
-
-// Inputs
-varying vec3 v_normalVector;                    // NormalVector in view space.
-
-// Global variables
-vec4 _baseColor;                                // Base color
-vec3 _ambientColor;                             // Ambient Color
-vec3 _diffuseColor;                             // Diffuse Color
-
-void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-    float ddot = dot(normalVector, lightDirection);
-    float diffuseIntensity = attenuation * ddot;
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-}
-
-#if defined(POINT_LIGHT)
-
-varying vec4 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection.xyz);
-    
-    // Fetch point light attenuation.
-    float pointLightAttenuation = v_vertexToPointLightDirection.w;
-    lighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightDirection;              // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;           // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 spotLightDirection = u_spotLightDirection; 
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-
-    // "-lightDirection" is used because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
-}
-
-#else
-
-uniform vec3 u_lightDirection;       	        // Light direction
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 lightDirection = normalize(u_lightDirection);
-
-    lighting(normalVector, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Fetch diffuse color from texture.
-    _baseColor = u_diffuseColor;
-
-    // Apply light
-    applyLight();
-
-    // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 81 - 0
gameplay/res/shaders/colored.vert

@@ -0,0 +1,81 @@
+#define LIGHTING
+
+// Inputs
+attribute vec4 a_position;									// Vertex Position							(x, y, z, w)
+attribute vec3 a_normal;									// Vertex Normal							(x, y, z)
+#if defined(SKINNING)
+attribute vec4 a_blendWeights;								// Vertex blend weight, up to 4				(0, 1, 2, 3) 
+attribute vec4 a_blendIndices;								// Vertex blend index int u_matrixPalette	(0, 1, 2, 3)
+#endif
+#if defined(VERTEX_COLOR)
+attribute vec3 a_color;										// Output Vertex Color
+varying vec3 v_color;										// Output Vertex Color 
+#endif
+
+// Uniforms
+uniform mat4 u_worldViewProjectionMatrix;					// Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;				// Matrix to transform a normal to view space.
+#if defined(SKINNING)
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];		// Array of 4x3 matrices
+#endif
+#if defined(SPECULAR)
+uniform mat4 u_worldViewMatrix;								// Matrix to tranform a position to view space.
+uniform vec3 u_cameraPosition;                 				// Position of the camera in view space.
+#endif
+#if defined(POINT_LIGHT)
+uniform vec3 u_pointLightPosition;							// Position of light
+uniform float u_pointLightRangeInverse;						// Inverse of light range 
+#elif defined(SPOT_LIGHT)
+uniform vec3 u_spotLightPosition;							// Position of light
+uniform float u_spotLightRangeInverse;						// Inverse of light range.
+#else
+#endif
+
+// Outputs
+varying vec3 v_normalVector;								// Normal vector in view space.
+#if defined(SPECULAR)
+varying vec3 v_cameraDirection;								// Direction the camera is looking at in tangent space.
+#endif
+// Lighting
+#if defined(POINT_LIGHT)
+varying vec3 v_vertexToPointLightDirection;					// Direction of point light w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;						// Attenuation of point light.
+#include "lib/lighting-point.vert"
+#elif defined(SPOT_LIGHT)
+varying vec3 v_vertexToSpotLightDirection;					// Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;						// Attenuation of spot light.
+#include "lib/lighting-spot.vert"
+#else
+uniform vec3 u_lightDirection;								// Direction of light
+#include "lib/lighting-directional.vert"
+#endif
+
+// Vertex attribute accessors
+#if defined(SKINNING)
+#include "lib/attributes-skinning.vert"
+#else
+#include "lib/attributes.vert" 
+#endif
+
+// Vertex program
+void main()
+{
+    // Get the position and normal
+    vec4 position = getPosition();
+    vec3 normal = getNormal();
+
+    // Transform position to clip space.
+    gl_Position = u_worldViewProjectionMatrix * position;
+
+    // Transform normal to view space.
+    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz, u_inverseTransposeWorldViewMatrix[1].xyz, u_inverseTransposeWorldViewMatrix[2].xyz);
+    v_normalVector = inverseTransposeWorldViewMatrix * normal;
+
+    // Apply light.
+    applyLight(position);
+    
+    // Pass the vertex color to fragment shader
+    #if defined(VERTEX_COLOR)
+	v_color = a_color;
+    #endif
+}

+ 0 - 183
gameplay/res/shaders/colored.vsh

@@ -1,183 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
-
-// Inputs
-attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-
-// Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space.
-
-#if defined(SKINNING)
-
-attribute vec4 a_blendWeights;
-attribute vec4 a_blendIndices;
-
-// 32 4x3 matrices as an array of floats
-uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
-
-// Common vectors.
-vec4 _skinnedPosition;
-vec3 _skinnedNormal;
-
-void skinPosition(float blendWeight, int matrixIndex)
-{
-    vec4 tmp;
-
-    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
-    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
-    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
-    tmp.w = a_position.w;
-
-    _skinnedPosition += blendWeight * tmp;
-}
-
-vec4 getPosition()
-{
-    _skinnedPosition = vec4(0.0);
-
-    // Transform position to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    return _skinnedPosition;    
-}
-
-void skinNormal(float blendWeight, int matrixIndex)
-{
-    vec3 tmp;
-
-    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
-    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
-    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
-
-    _skinnedNormal += blendWeight * tmp;
-}
-
-vec3 getNormal()
-{
-    _skinnedNormal = vec3(0.0);
-
-    // Transform normal to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    return _skinnedNormal;
-}
-
-#else
-
-vec4 getPosition()
-{
-    return a_position;    
-}
-
-vec3 getNormal()
-{
-    return a_normal;
-}
-
-#endif
-
-#if defined(POINT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRangeInverse;             // Inverse of light range.
-varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
-
-void applyLight(vec4 position)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-    
-    // Compute the light direction.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-    
-    vec4 vertexToPointLightDirection;
-    vertexToPointLightDirection.xyz = lightDirection;
-    
-    // Attenuation.
-    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToPointLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_spotLightPosition;                   // Position
-uniform float u_spotLightRangeInverse;              // Inverse of light range.
-varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;               // Attenuation of spot light.
-
-void applyLight(vec4 position)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-
-    // Compute the light direction.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-void applyLight(vec4 position)
-{
-}
-
-#endif
-
-void main()
-{
-    vec4 position = getPosition();
-    vec3 normal = getNormal();
-        
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * position;
-
-    // Transform normal to view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
-                                                u_inverseTransposeWorldViewMatrix[1].xyz,
-                                                u_inverseTransposeWorldViewMatrix[2].xyz);
-    v_normalVector = inverseTransposeWorldViewMatrix * normal;
-
-    // Apply light.
-    applyLight(position);
-}

+ 0 - 124
gameplay/res/shaders/diffuse-specular.fsh

@@ -1,124 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec3 u_lightColor;                      // Light color
-uniform vec3 u_ambientColor;                    // Ambient color
-uniform float u_specularExponent;               // Specular exponent or shininess property.
-uniform sampler2D u_diffuseTexture;             // Diffuse texture.
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
-
-// Inputs
-varying vec3 v_normalVector;                    // NormalVector in view space.
-varying vec2 v_texCoord;                        // Texture coordinate (u, v).
-varying vec3 v_cameraDirection;                 // Camera direction
-
-// Global variables
-vec4 _baseColor;                                // Base color
-vec3 _ambientColor;                             // Ambient Color
-vec3 _diffuseColor;                             // Diffuse Color
-vec3 _specularColor;                            // Specular color
-
-void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-    float ddot = dot(normalVector, lightDirection);
-    float diffuseIntensity = attenuation * ddot;
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-
-    // Specular
-    vec3 halfVector = normalize(lightDirection + cameraDirection);
-    float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
-    specularIntensity = max(0.0, specularIntensity);
-    _specularColor = u_lightColor * _baseColor.rgb * specularIntensity;
-}
-
-#if defined(POINT_LIGHT)
-
-varying vec4 v_vertexToPointLightDirection;      // Light direction w.r.t current vertex.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection.xyz);
-    
-    // Fetch point light attenuation.
-    float pointLightAttenuation = v_vertexToPointLightDirection.w;
-    lighting(normalVector, cameraDirection, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightDirection;              // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;           // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 spotLightDirection = normalize(u_spotLightDirection); 
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-
-    // "-lightDirection" is used because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-    
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    lighting(normalVector, cameraDirection, vertexToSpotLightDirection, spotLightAttenuation);
-}
-
-#else
-
-uniform vec3 u_lightDirection;                  // Light direction
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 lightDirection = normalize(u_lightDirection);
-
-    lighting(normalVector, cameraDirection, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, v_texCoord);
-
-    // Apply light
-    applyLight();
-
-    // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 0 - 194
gameplay/res/shaders/diffuse-specular.vsh

@@ -1,194 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_cameraPosition;                      // Position of the camera in view space.
-
-// Inputs
-attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                          // Vertex Texture Coordinate (u, v)
-
-// Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space.
-varying vec2 v_texCoord;                            // Texture coordinate (u, v).
-varying vec3 v_cameraDirection;                     // Camera direction
-
-#if defined(SKINNING)
-
-attribute vec4 a_blendWeights;
-attribute vec4 a_blendIndices;
-
-// 32 4x3 matrices as an array of floats
-uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
-
-// Common vectors.
-vec4 _skinnedPosition;
-vec3 _skinnedNormal;
-
-void skinPosition(float blendWeight, int matrixIndex)
-{
-    vec4 tmp;
-
-    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
-    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
-    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
-    tmp.w = a_position.w;
-
-    _skinnedPosition += blendWeight * tmp;
-}
-
-vec4 getPosition()
-{
-    _skinnedPosition = vec4(0.0);
-
-    // Transform position to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    return _skinnedPosition;    
-}
-
-void skinNormal(float blendWeight, int matrixIndex)
-{
-    vec3 tmp;
-
-    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
-    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
-    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
-
-    _skinnedNormal += blendWeight * tmp;
-}
-
-vec3 getNormal()
-{
-    _skinnedNormal = vec3(0.0);
-
-    // Transform normal to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    return _skinnedNormal;
-}
-
-#else
-
-vec4 getPosition()
-{
-    return a_position;    
-}
-
-vec3 getNormal()
-{
-    return a_normal;
-}
-
-#endif
-
-#if defined(POINT_LIGHT)
-
-uniform vec3 u_pointLightPosition;                      // Position
-uniform float u_pointLightRangeInverse;                 // Inverse of light range.
-varying vec4 v_vertexToPointLightDirection;             // Light direction w.r.t current vertex.
-
-void applyLight(vec4 position)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-    
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-
-    vec4 vertexToPointLightDirection;
-    vertexToPointLightDirection.xyz = lightDirection;
-
-    // Attenuation
-    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToPointLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightPosition;                       // Position
-uniform float u_spotLightRangeInverse;                  // Inverse of light range.
-varying vec3 v_vertexToSpotLightDirection;              // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;                   // Attenuation of spot light.
-
-void applyLight(vec4 position)
-{
-    // World space position.
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Compute the light direction with light position and the vertex position.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-void applyLight(vec4 position)
-{
-}
-
-#endif
-
-void main()
-{
-    vec4 position = getPosition();
-    vec3 normal = getNormal();
-
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * position;
-
-    // Transform normal to view space.
-    mat3 normalMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
-                             u_inverseTransposeWorldViewMatrix[1].xyz,
-                             u_inverseTransposeWorldViewMatrix[2].xyz);
-    v_normalVector = normalMatrix * normal;
-
-    // Compute the camera direction.
-    vec4 positionWorldSpace = u_worldViewMatrix * position;
-    v_cameraDirection = u_cameraPosition - positionWorldSpace.xyz;
-
-    // Apply light.
-    applyLight(position);
-
-	// Pass on the texture coordinates to Fragment shader.
-    v_texCoord = a_texCoord;
-}

+ 0 - 111
gameplay/res/shaders/diffuse.fsh

@@ -1,111 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec3 u_lightColor;                      // Light color
-uniform vec3 u_ambientColor;                    // Ambient color
-uniform sampler2D u_diffuseTexture;             // Diffuse texture.
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
-
-// Inputs
-varying vec3 v_normalVector;                    // NormalVector in view space.
-varying vec2 v_texCoord;                        // Texture coordinate (u, v).
-
-// Global variables
-vec4 _baseColor;                                // Base color
-vec3 _ambientColor;                             // Ambient Color
-vec3 _diffuseColor;                             // Diffuse Color
-
-void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-	float ddot = dot(normalVector, lightDirection);
-    float diffuseIntensity = attenuation * ddot;
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-}
-
-#if defined(POINT_LIGHT)
-
-varying vec4 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection.xyz);
-    
-    // Fetch point light attenuation.
-    float pointLightAttenuation = v_vertexToPointLightDirection.w;
-    lighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightDirection;              // Direction of the spot light.
-uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
-varying vec3 v_vertexToSpotLightDirection;      // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;           // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 spotLightDirection =normalize(u_spotLightDirection); 
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-
-    // "-lightDirection" is used because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
-}
-
-#else
-
-uniform vec3 u_lightDirection;                  // Light direction
-
-void applyLight()
-{
-    vec3 normalVector = normalize(v_normalVector);
-    vec3 lightDirection = normalize(u_lightDirection);
-
-    lighting(normalVector, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, v_texCoord);
-
-    // Apply light
-    applyLight();
-
-    // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 0 - 191
gameplay/res/shaders/diffuse.vsh

@@ -1,191 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
-
-// Inputs
-attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                          // Vertex Texture Coordinate (u, v)
-
-// Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space.
-varying vec2 v_texCoord;                            // Texture coordinate (u, v).
-varying vec3 v_cameraDirection;                     // Camera direction
-
-#if defined(SKINNING)
-
-attribute vec4 a_blendWeights;
-attribute vec4 a_blendIndices;
-
-// 32 4x3 matrices as an array of floats
-uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
-
-// Common vectors.
-vec4 _skinnedPosition;
-vec3 _skinnedNormal;
-
-void skinPosition(float blendWeight, int matrixIndex)
-{
-    vec4 tmp;
-
-    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
-    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
-    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
-    tmp.w = a_position.w;
-
-    _skinnedPosition += blendWeight * tmp;
-}
-
-vec4 getPosition()
-{
-    _skinnedPosition = vec4(0.0);
-
-    // Transform position to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    return _skinnedPosition;    
-}
-
-void skinNormal(float blendWeight, int matrixIndex)
-{
-    vec3 tmp;
-
-    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
-    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
-    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
-
-    _skinnedNormal += blendWeight * tmp;
-}
-
-vec3 getNormal()
-{
-    _skinnedNormal = vec3(0.0);
-
-    // Transform normal to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinNormal(blendWeight, matrixIndex);
-
-    return _skinnedNormal;
-}
-
-#else
-
-vec4 getPosition()
-{
-    return a_position;    
-}
-
-vec3 getNormal()
-{
-    return a_normal;
-}
-
-#endif
-
-#if defined(POINT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRange;                    // Inverse of light range.
-varying vec4 v_vertexToPointLightDirection;         // Light direction w.r.t current vertex.
-
-void applyLight(vec4 position)
-{
-    // World space position.
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-    
-    // Compute the light direction.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-    
-    vec4 vertexToPointLightDirection;
-    vertexToPointLightDirection.xyz = lightDirection;
-    
-    // Attenuation
-    vertexToPointLightDirection.w = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToPointLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform mat4 u_worldViewMatrix;                     // Matrix to tranform a position to view space.
-uniform vec3 u_spotLightPosition;                   // Position
-uniform float u_spotLightRangeInverse;              // Inverse of light range.
-varying vec3 v_vertexToSpotLightDirection;          // Light direction w.r.t current vertex.
-varying float v_spotLightAttenuation;               // Attenuation of spot light.
-
-void applyLight(vec4 position)
-{
-    // World space position.
-    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
-
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-void applyLight(vec4 position)
-{
-}
-
-#endif
-
-void main()
-{
-    vec4 position = getPosition();
-    vec3 normal = getNormal();
-    
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * position;
-
-    // Transform normal to view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
-                                                u_inverseTransposeWorldViewMatrix[1].xyz,
-                                                u_inverseTransposeWorldViewMatrix[2].xyz);
-    v_normalVector = inverseTransposeWorldViewMatrix * normal;
-
-    // Apply light.
-    applyLight(position);
-
-    // Pass on the texture coordinates to Fragment shader.
-    v_texCoord = a_texCoord;
-}

+ 93 - 0
gameplay/res/shaders/lib/attributes-skinning.vert

@@ -0,0 +1,93 @@
+vec4 _skinnedPosition;
+#if defined(LIGHTING)
+vec3 _skinnedNormal;
+#endif
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using matrix palette with four matrices used to transform a vertex.
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[3]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+void skinTangentSpaceVector(vec3 vector, float blendWeight, int matrixIndex)
+{
+    vec3 tmp;
+    tmp.x = dot(vector, u_matrixPalette[matrixIndex].xyz);
+    tmp.y = dot(vector, u_matrixPalette[matrixIndex + 1].xyz);
+    tmp.z = dot(vector, u_matrixPalette[matrixIndex + 2].xyz);
+    _skinnedNormal += blendWeight * tmp;
+}
+
+vec3 getTangentSpaceVector(vec3 vector)
+{
+    _skinnedNormal = vec3(0.0);
+
+    // Transform normal to view space using matrix palette with four matrices used to transform a vertex.
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[3]) * 3;
+    skinTangentSpaceVector(vector, blendWeight, matrixIndex);
+
+    return _skinnedNormal;
+}
+
+#if defined(LIGHTING)
+
+vec3 getNormal()
+{
+    return getTangentSpaceVector(a_normal);
+}
+
+#if defined(BUMPED)
+
+vec3 getTangent()
+{
+    return getTangentSpaceVector(a_tangent);
+}
+
+vec3 getBinormal()
+{
+    return getTangentSpaceVector(a_binormal);
+}
+
+#endif
+#endif

+ 27 - 0
gameplay/res/shaders/lib/attributes.vert

@@ -0,0 +1,27 @@
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+#if defined(LIGHTING)
+
+vec3 getNormal()
+{
+    return a_normal;
+}
+
+#if defined(BUMPED)
+
+vec3 getTangent()
+{
+    return a_tangent;
+}
+
+vec3 getBinormal()
+{
+    return a_binormal;
+}
+
+#endif
+
+#endif

+ 41 - 0
gameplay/res/shaders/lib/lighting-directional.frag

@@ -0,0 +1,41 @@
+#if defined(BUMPED)
+
+vec3 getLitPixel()
+{
+    // Fetch normals from the normal map
+    vec3 normalVector = normalize(texture2D(u_textureNormal, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 lightDirection = normalize(v_lightDirection);
+    
+    #if defined(SPECULAR)
+    
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    return computeLighting(normalVector, -lightDirection, 1.0, cameraDirection);
+    
+    #else
+    
+    return computeLighting(normalVector, -lightDirection, 1.0);
+    
+    #endif
+}
+
+#else
+
+vec3 getLitPixel()
+{
+    // Normalize the vectors.
+    vec3 normalVector = normalize(v_normalVector);
+    vec3 lightDirection = normalize(u_lightDirection);
+
+    #if defined(SPECULAR)
+    
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    return computeLighting(normalVector, -lightDirection, 1.0, cameraDirection);
+    
+    #else
+    
+    return computeLighting(normalVector, -lightDirection, 1.0);
+    
+    #endif
+}
+
+#endif

+ 31 - 0
gameplay/res/shaders/lib/lighting-directional.vert

@@ -0,0 +1,31 @@
+#if defined(BUMPED)
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    // Transform light direction to tangent space
+    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
+    
+    #if defined(SPECULAR)
+
+    // Compute the camera direction for specular lighting
+    vec4 positionWorldSpace = u_worldViewMatrix * a_position;
+    v_cameraDirection = u_cameraPosition - positionWorldSpace.xyz;
+    
+    #endif
+}
+
+#else
+
+void applyLight(vec4 position)
+{
+    
+    #if defined(SPECULAR)
+
+    // Compute the camera direction for specular lighting
+    vec4 positionWorldSpace = u_worldViewMatrix * position;
+    v_cameraDirection = u_cameraPosition - positionWorldSpace.xyz;
+
+    #endif
+}
+
+#endif

+ 46 - 0
gameplay/res/shaders/lib/lighting-point.frag

@@ -0,0 +1,46 @@
+#if defined(BUMPED)
+
+vec3 getLitPixel()
+{
+    // Fetch normals from the normal map and normalize the vectors
+    vec3 normalVector = normalize(texture2D(u_textureNormal, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
+    
+    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
+    
+    #if defined(SPECULAR)
+    
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    return computeLighting(normalVector, vertexToPointLightDirection, pointLightAttenuation, cameraDirection);
+    
+    #else
+    
+    return computeLighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
+    
+    #endif
+}
+
+#else
+
+vec3 getLitPixel()
+{
+    // Normalize the vectors.
+    vec3 normalVector = normalize(v_normalVector);    
+    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
+    
+    // Fetch point light attenuation.
+    float pointLightAttenuation = v_pointLightAttenuation;
+    
+    #if defined (SPECULAR)
+    
+    vec3 cameraDirection = normalize(v_cameraDirection);    
+    return computeLighting(normalVector, vertexToPointLightDirection, pointLightAttenuation, cameraDirection);
+    
+    #else
+    
+    return computeLighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
+    
+    #endif
+}
+
+#endif

+ 53 - 0
gameplay/res/shaders/lib/lighting-point.vert

@@ -0,0 +1,53 @@
+#if defined(BUMPED)
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute the light direction with light position and the vertex position.
+    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    vec3 vertexToPointLightDirection = tangentSpaceTransformMatrix * lightDirection;
+
+    // Attenuation
+    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToPointLightDirection =  vertexToPointLightDirection;
+    
+    #if defined (SPECULAR)
+ 
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
+    #endif
+}
+
+#else
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+    
+    // Compute the light direction.
+    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+   
+    vec4 vertexToPointLightDirection;
+    vertexToPointLightDirection.xyz = lightDirection;
+   
+    // Attenuation
+    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToPointLightDirection =  vertexToPointLightDirection;
+   
+    #if defined (SPECULAR)
+   
+    vec3 cameraDirection = normalize(v_cameraDirection);
+
+    #endif
+}
+
+#endif

+ 63 - 0
gameplay/res/shaders/lib/lighting-spot.frag

@@ -0,0 +1,63 @@
+float lerpstep( float lower, float upper, float s)
+{
+    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
+}
+
+#if defined(BUMPED)
+
+vec3 getLitPixel()
+{
+    // Fetch normals from the normal map.
+    vec3 normalVector = normalize(texture2D(u_textureNormal, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 spotLightDirection = normalize(v_spotLightDirection);
+    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
+    
+    // "-lightDirection" because light direction points in opposite direction to to spot direction.
+    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
+    
+    // Intensity of spot depends on the spot light attenuation and the part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+
+    #if defined(SPECULAR)
+    
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    return computeLighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation, cameraDirection);
+    
+    #else
+    
+    return computeLighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
+    
+    #endif
+}
+
+#else
+
+vec3 getLitPixel()
+{
+    // Normalize the vectors.
+    vec3 normalVector = normalize(v_normalVector);
+    vec3 spotLightDirection = normalize(u_spotLightDirection); 
+    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
+
+    // "-lightDirection" is used because light direction points in opposite direction to to spot direction.
+    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
+    
+    // Intensity of spot depends on the spot light attenuation and the 
+    // part of the cone vertexToSpotLightDirection points to (inner or outer).
+    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
+    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
+
+    #if defined(SPECULAR)
+    
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    return computeLighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation, cameraDirection);
+    
+    #else
+    
+    return computeLighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
+    
+    #endif
+}
+
+#endif

+ 54 - 0
gameplay/res/shaders/lib/lighting-spot.vert

@@ -0,0 +1,54 @@
+#if defined(BUMPED)
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+
+    // Transform spot light direction to tangent space.
+    v_spotLightDirection = tangentSpaceTransformMatrix * u_spotLightDirection;
+
+    // Compute the light direction with light position and the vertex position.
+    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    lightDirection = tangentSpaceTransformMatrix * lightDirection;
+    
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToSpotLightDirection = lightDirection;
+    
+    #if defined(SPECULAR)
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
+    #endif
+}
+
+#else
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+
+    // Compute the light direction with light position and the vertex position.
+    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+
+    // Attenuation
+    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
+
+    // Output light direction.
+    v_vertexToSpotLightDirection = lightDirection;
+    
+    #if defined(SPECULAR)
+    
+    // Compute camera direction and transform it to tangent space.
+    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
+    
+    #endif
+}
+
+#endif

+ 46 - 0
gameplay/res/shaders/lib/lighting.frag

@@ -0,0 +1,46 @@
+vec4 _baseColor;
+vec3 _ambientColor;
+vec3 _diffuseColor;
+
+#if defined(SPECULAR)
+
+vec3 _specularColor;
+
+vec3 computeLighting(vec3 normalVector, vec3 lightDirection, float attenuation, vec3 cameraDirection)
+{
+    // Ambient
+    _ambientColor = _baseColor.rgb * u_ambientColor;
+
+    // Diffuse
+    float ddot = dot(normalVector, lightDirection);
+    float diffuseIntensity = attenuation * ddot;
+    diffuseIntensity = max(0.0, diffuseIntensity);
+    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
+
+    // Specular
+    vec3 halfVector = normalize(lightDirection + cameraDirection);
+    float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
+    specularIntensity = max(0.0, specularIntensity);
+    _specularColor = u_lightColor * _baseColor.rgb * specularIntensity;
+	
+	return _ambientColor + _diffuseColor + _specularColor;
+}
+
+#else
+
+vec3 computeLighting(vec3 normalVector, vec3 lightDirection, float attenuation)
+{
+    // Ambient
+    _ambientColor = _baseColor.rgb * u_ambientColor;
+
+    // Diffuse
+	float ddot = dot(normalVector, lightDirection);
+    float diffuseIntensity = attenuation * ddot;
+    diffuseIntensity = max(0.0, diffuseIntensity);
+    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
+	
+	return _ambientColor + _diffuseColor;
+}
+
+#endif
+

+ 0 - 175
gameplay/res/shaders/parallax-specular.fsh

@@ -1,175 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec3 u_lightColor;                      // Light color.
-uniform vec3 u_ambientColor;                    // Ambient color.
-uniform float u_specularExponent;               // Specular exponent or shininess property.
-uniform sampler2D u_diffuseTexture;             // Diffuse texture.
-uniform sampler2D u_bumpMapTexture;             // Height map texture
-uniform sampler2D u_normalMapTexture;           // Normal map texture.
-uniform float u_parallaxHeight;                 // Parallax height
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
-
-// Inputs
-varying vec2 v_texCoord;                        // Texture Coordinate.
-varying vec3 v_cameraDirection;                 // Direction the camera is looking at in tangent space.
-
-// Global variables
-vec4 _baseColor;                                // Base color
-vec3 _ambientColor;                             // Ambient Color
-vec3 _diffuseColor;                             // Diffuse Color
-vec3 _specularColor;                            // Specular color
-
-void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-    float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-
-    // Specular
-    vec3 halfVector = normalize(cameraDirection + lightDirection);
-    float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
-    specularIntensity = max(0.0, specularIntensity);
-    _specularColor = u_lightColor * _baseColor.rgb * specularIntensity;
-}
-
-#if defined(POINT_LIGHT)
-
-varying vec3 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;          // Attenuation of point light.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
-    
-    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
-
-    // Get the height in the bumpmap texture.
-    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
-
-    // Compute offset within the range (-parallax height to +parallax height).
-    float offset = u_parallaxHeight * (2.0 * height - 1.0);
-    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
-
-    // Compute offset again with the new texture coordinates to get better precision.
-    // Find out the mean height.
-    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
-    offset = u_parallaxHeight * (height - 1.0);
-    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
-
-    // Fetch normals from the normal map with the modified texture coordinates.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
-
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
-    
-    lighting(normalVector, cameraDirection, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
-varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;      // Direction of the spot light w.r.t current vertex in tangent space.
-varying float v_spotLightAttenuation;           // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
-{
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 spotLightDirection = normalize(v_spotLightDirection);
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-
-    // "-lightDirection" because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-    
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    // Get the height in the bumpmap texture.
-    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
-
-    // Compute offset within the range (-parallax height to +parallax height).
-    float offset = u_parallaxHeight * (2.0 * height - 1.0);
-    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
-
-    // Compute offset again with the new texture coordinates to get better precision.
-    // Find out the mean height.
-    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
-    offset = u_parallaxHeight * (height - 1.0);
-    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
-
-    // Fetch normals from the normal map with the modified texture coordinates.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
-
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
-
-    lighting(normalVector, cameraDirection, vertexToSpotLightDirection, spotLightAttenuation);
-}
-
-#else
-
-varying vec3 v_lightDirection;                  // Direction of light in tangent space.
-
-void applyLight()
-{
-    // Normalize vectors.
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 lightDirection = normalize(v_lightDirection);
-
-    // Get the height in the bumpmap texture.
-    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
-
-    // Compute offset within the range (-parallax height to +parallax height).
-    float offset = u_parallaxHeight * (2.0 * height - 1.0);
-    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
-
-    // Compute offset again with the new texture coordinates to get better precision.
-    // Find out the mean height.
-    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
-    offset = u_parallaxHeight * (height - 1.0);
-    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
-
-    // Fetch normals from the normal map with the modified texture coordinates.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
-
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
-
-    lighting(normalVector, cameraDirection, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Apply light
-    applyLight();
-
-    // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 0 - 118
gameplay/res/shaders/parallax-specular.vsh

@@ -1,118 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewMatrix;                     // Matrix to transform a position to view space.
-uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
-uniform vec3 u_cameraPosition;                      // Position of the camera.
-
-
-// Inputs
-attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                          // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                           // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                          // Vertex Binormal (actually Bi-tangent) (x, y, z)
-
-// Outputs
-varying vec2 v_texCoord;                            // Texture Coordinate (u,v)
-varying vec3 v_cameraDirection;                     // Direction the camera is looking at in tangent space.
-
-#if defined(POINT_LIGHT)
-
-uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRangeInverse;             // Inverse of light range 
-varying vec3 v_vertexToPointLightDirection;         // Direction of point light w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;              // Attenuation of point light.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-    
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-    
-    // Transform current light direction to tangent space.
-    vec3 vertexToPointLightDirection = tangentSpaceTransformMatrix * lightDirection;
-
-    // Attenuation
-    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToPointLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightPosition;                   // Position
-uniform float u_spotLightRangeInverse;              // Inverse of light range.
-uniform vec3 u_spotLightDirection;                  // Direction
-varying vec3 v_spotLightDirection;                  // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;          // Direction of the spot light w.r.t current vertex in tangent space.
-varying float v_spotLightAttenuation;               // Attenuation of spot light.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-
-    // Transform spot light direction to tangent space.
-    v_spotLightDirection = tangentSpaceTransformMatrix * u_spotLightDirection;
-
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-    
-    // Transform current light direction to tangent space.
-    lightDirection = tangentSpaceTransformMatrix * lightDirection;
-    
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-uniform vec3 u_lightDirection;                      // Direction
-varying vec3 v_lightDirection;                      // Direction of light in tangent space.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-    
-    // Transform light direction to tangent space.
-    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
-}
-
-#endif
-
-void main()
-{
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
-
-    // Transform the normal, tangent and binormals to  view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
-                                                u_inverseTransposeWorldViewMatrix[1].xyz,
-                                                u_inverseTransposeWorldViewMatrix[2].xyz);
-    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * a_tangent);
-    vec3 normalVector = normalize(inverseTransposeWorldViewMatrix * a_normal);
-    vec3 binormalVector = normalize(inverseTransposeWorldViewMatrix * a_binormal);
-
-    // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x,
-                                            tangentVector.y, binormalVector.y, normalVector.y,
-                                            tangentVector.z, binormalVector.z, normalVector.z);
-    // Apply light.
-    applyLight(tangentSpaceTransformMatrix);
-
-    // Pass on the texture coordinates to Fragment shader.
-    v_texCoord = a_texCoord;
-}

+ 0 - 167
gameplay/res/shaders/parallax.fsh

@@ -1,167 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec3 u_lightColor;                      // Light color.
-uniform vec3 u_ambientColor;                    // Ambient color.
-uniform sampler2D u_diffuseTexture;             // Diffuse texture.
-uniform sampler2D u_bumpMapTexture;             // Height map texture
-uniform sampler2D u_normalMapTexture;           // Normal map texture.
-uniform float u_parallaxHeight;                 // Parallax height
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;                    // Global alpha value
-#endif
-
-// Inputs
-varying vec2 v_texCoord;                        // Texture Coordinate.
-varying vec3 v_cameraDirection;                 // Direction the camera is looking at in tangent space.
-
-// Global variables
-vec4 _baseColor;                                // Base color
-vec3 _ambientColor;                             // Ambient Color
-vec3 _diffuseColor;                             // Diffuse Color
-
-void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
-{
-    // Ambient
-    _ambientColor = _baseColor.rgb * u_ambientColor;
-
-    // Diffuse
-    float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
-    diffuseIntensity = max(0.0, diffuseIntensity);
-    _diffuseColor = u_lightColor * _baseColor.rgb * diffuseIntensity;
-}
-
-#if defined(POINT_LIGHT)
-
-varying vec3 v_vertexToPointLightDirection;     // Light direction w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;          // Attenuation of point light.
-
-void applyLight()
-{
-    // Normalize the vectors.
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 vertexToPointLightDirection = normalize(v_vertexToPointLightDirection);
-    
-    float pointLightAttenuation = clamp(v_pointLightAttenuation, 0.0, 1.0);
-
-    // Get the height in the bumpmap texture.
-    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
-
-    // Compute offset within the range (-parallax height to +parallax height).
-    float offset = u_parallaxHeight * (2.0 * height - 1.0);
-    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
-
-    // Compute offset again with the new texture coordinates to get better precision.
-    // Find out the mean height.
-    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
-    offset = u_parallaxHeight * (height - 1.0);
-    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
-
-    // Fetch normals from the normal map with the modified texture coordinates.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
-
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
-    
-    lighting(normalVector, vertexToPointLightDirection, pointLightAttenuation);
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform float u_spotLightInnerAngleCos;         // The bright spot [0.0 - 1.0]
-uniform float u_spotLightOuterAngleCos;         // The soft outer part [0.0 - 1.0]
-varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;      // Direction of the spot light w.r.t current vertex in tangent space.
-varying float v_spotLightAttenuation;           // Attenuation of spot light.
-
-float lerpstep( float lower, float upper, float s)
-{
-    return clamp( ( s - lower ) / ( upper - lower ), 0.0, 1.0 );
-}
-
-void applyLight()
-{
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 spotLightDirection = normalize(v_spotLightDirection);
-    vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection);
-
-    // "-lightDirection" because light direction points in opposite direction to
-    // to spot direction.
-    // Calculate spot light effect.
-    float spotCurrentAngleCos = max(0.0, dot(spotLightDirection, -vertexToSpotLightDirection));
-    
-    // Intensity of spot depends on the spot light attenuation and the 
-    // part of the cone vertexToSpotLightDirection points to (inner or outer).
-    float spotLightAttenuation = clamp(v_spotLightAttenuation, 0.0, 1.0);
-    spotLightAttenuation *= lerpstep(u_spotLightOuterAngleCos, u_spotLightInnerAngleCos, spotCurrentAngleCos);
-
-    // Get the height in the bumpmap texture.
-    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
-
-    // Compute offset within the range (-parallax height to +parallax height).
-    float offset = u_parallaxHeight * (2.0 * height - 1.0);
-    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
-
-    // Compute offset again with the new texture coordinates to get better precision.
-    // Find out the mean height.
-    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
-    offset = u_parallaxHeight * (height - 1.0);
-    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
-
-    // Fetch normals from the normal map with the modified texture coordinates.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
-
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
-
-    lighting(normalVector, vertexToSpotLightDirection, spotLightAttenuation);
-}
-
-#else
-
-varying vec3 v_lightDirection;                      // Direction of light in tangent space.
-
-void applyLight()
-{
-    // Normalize vectors.
-    vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 lightDirection = normalize(v_lightDirection);
-
-    // Get the height in the bumpmap texture.
-    float height = texture2D(u_bumpMapTexture, v_texCoord).r;
-
-    // Compute offset within the range (-parallax height to +parallax height).
-    float offset = u_parallaxHeight * (2.0 * height - 1.0);
-    vec2 parallaxTexCoord = v_texCoord + (cameraDirection.xy * offset);
-
-    // Compute offset again with the new texture coordinates to get better precision.
-    // Find out the mean height.
-    height += texture2D(u_bumpMapTexture, parallaxTexCoord).r;
-    offset = u_parallaxHeight * (height - 1.0);
-    parallaxTexCoord = v_texCoord + ( cameraDirection.xy * offset);
-
-    // Fetch normals from the normal map with the modified texture coordinates.
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, parallaxTexCoord).xyz * 2.0 - 1.0);
-
-    // Fetch diffuse color from texture.
-    _baseColor = texture2D(u_diffuseTexture, parallaxTexCoord);
-
-    lighting(normalVector, -lightDirection, 1.0);
-}
-#endif
-
-void main()
-{
-    // Apply light
-    applyLight();
-
-    // Light the pixel
-    gl_FragColor.a = _baseColor.a;
-    gl_FragColor.rgb = _ambientColor + _diffuseColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 0 - 118
gameplay/res/shaders/parallax.vsh

@@ -1,118 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewMatrix;                     // Matrix to transform a position to view space.
-uniform mat4 u_worldViewProjectionMatrix;           // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
-uniform vec3 u_cameraPosition;                      // Position of the camera.
-
-
-// Inputs
-attribute vec4 a_position;                          // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                          // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                           // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                          // Vertex Binormal (actually Bi-tangent) (x, y, z)
-
-// Outputs
-varying vec2 v_texCoord;                            // Texture Coordinate (u,v)
-varying vec3 v_cameraDirection;                     // Direction the camera is looking at in tangent space.
-
-#if defined(POINT_LIGHT)
-
-uniform vec3 u_pointLightPosition;                  // Position
-uniform float u_pointLightRangeInverse;             // Inverse of light range 
-varying vec3 v_vertexToPointLightDirection;         // Direction of point light w.r.t current vertex in tangent space.
-varying float v_pointLightAttenuation;              // Attenuation of point light.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-    
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
-    
-    // Transform current light direction to tangent space.
-    vec3 vertexToPointLightDirection = tangentSpaceTransformMatrix * lightDirection;
-
-    // Attenuation
-    v_pointLightAttenuation = 1.0 - dot(lightDirection * u_pointLightRangeInverse, lightDirection * u_pointLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToPointLightDirection =  vertexToPointLightDirection;
-}
-
-#elif defined(SPOT_LIGHT)
-
-uniform vec3 u_spotLightPosition;                   // Position
-uniform float u_spotLightRangeInverse;              // Inverse of light range.
-uniform vec3 u_spotLightDirection;                  // Direction
-varying vec3 v_spotLightDirection;                  // Direction of spot light in tangent space.
-varying vec3 v_vertexToSpotLightDirection;          // Direction of the spot light w.r.t current vertex in tangent space.
-varying float v_spotLightAttenuation;               // Attenuation of spot light.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-
-    // Transform spot light direction to tangent space.
-    v_spotLightDirection = tangentSpaceTransformMatrix * u_spotLightDirection;
-
-    // Compute the light direction with light position and the vertex position.
-    vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
-    
-    // Transform current light direction to tangent space.
-    lightDirection = tangentSpaceTransformMatrix * lightDirection;
-    
-    // Attenuation
-    v_spotLightAttenuation = 1.0 - dot(lightDirection * u_spotLightRangeInverse, lightDirection * u_spotLightRangeInverse);
-
-    // Output light direction.
-    v_vertexToSpotLightDirection = lightDirection;
-}
-
-#else
-
-uniform vec3 u_lightDirection;                      // Direction
-varying vec3 v_lightDirection;                      // Direction of light in tangent space.
-
-void applyLight(mat3 tangentSpaceTransformMatrix)
-{
-    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
-    
-    // Compute camera direction and transform it to tangent space.
-    v_cameraDirection = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldViewSpace.xyz);
-    
-    // Transform light direction to tangent space.
-    v_lightDirection = tangentSpaceTransformMatrix * u_lightDirection;
-}
-
-#endif
-
-void main()
-{
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
-
-    // Transform the normal, tangent and binormals to  view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz,
-                                                u_inverseTransposeWorldViewMatrix[1].xyz,
-                                                u_inverseTransposeWorldViewMatrix[2].xyz);
-    vec3 tangentVector  = normalize(inverseTransposeWorldViewMatrix * a_tangent);
-    vec3 normalVector = inverseTransposeWorldViewMatrix * a_normal;
-    vec3 binormalVector = inverseTransposeWorldViewMatrix * a_binormal;
-
-    // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangentVector.x, binormalVector.x, normalVector.x,
-                                            tangentVector.y, binormalVector.y, normalVector.y,
-                                            tangentVector.z, binormalVector.z, normalVector.z);
-    // Apply light.
-    applyLight(tangentSpaceTransformMatrix);
-
-    // Pass on the texture coordinates to Fragment shader.
-    v_texCoord = a_texCoord;
-}

+ 0 - 18
gameplay/res/shaders/solid.fsh

@@ -1,18 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform vec4 u_diffuseColor;        // Diffuse color
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;        // Global alpha value
-#endif
-
-void main()
-{
-    gl_FragColor = u_diffuseColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 0 - 10
gameplay/res/shaders/solid.vsh

@@ -1,10 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewProjectionMatrix;        // Matrix to transform a position to clip space.
-
-// Inputs
-attribute vec4 a_position;                        // Vertex Position (x, y, z, w)
-
-void main()
-{
-    gl_Position = u_worldViewProjectionMatrix *  a_position;
-}

+ 36 - 0
gameplay/res/shaders/textured-unlit.frag

@@ -0,0 +1,36 @@
+#ifdef OPENGL_ES
+precision highp float;
+#endif
+
+// Uniforms
+uniform sampler2D u_textureDiffuse;     	// Diffuse texture
+#if defined(TEXTURE_LIGHT)
+uniform sampler2D u_textureLight;     		// Lightmap texture
+#endif
+#if defined(MODULATE_COLOR)
+uniform vec4 u_modulateColor;               // Modulation color
+#endif
+#if defined(MODULATE_ALPHA)
+uniform float u_modulateAlpha;              // Modulation alpha
+#endif
+
+// Inputs
+varying vec2 v_texCoord;                	// Texture coordinate(u, v)
+
+// Fragment Program
+void main()
+{
+    // Sample the texture for the color
+    gl_FragColor = texture2D(u_textureDiffuse, v_texCoord);
+	#if defined(TEXTURE_LIGHT)
+	vec4 lightColor = texture2D(u_textureLight, v_texCoord);
+	gl_FragColor.a *= lightColor.a;
+	#endif
+	// Global color modulation
+	#if defined(MODULATE_COLOR)
+	gl_FragColor *= u_modulateColor;
+	#endif
+	#if defined(MODULATE_ALPHA)
+    gl_FragColor.a *= u_modulateAlpha;
+    #endif
+}

+ 48 - 0
gameplay/res/shaders/textured-unlit.vert

@@ -0,0 +1,48 @@
+// Inputs
+attribute vec4 a_position;									// Vertex Position							(x, y, z, w)
+attribute vec2 a_texCoord;									// Vertex Texture Coordinate				(u, v)
+#if defined(SKINNING)
+attribute vec4 a_blendWeights;								// Vertex blend weight, up to 4				(0, 1, 2, 3) 
+attribute vec4 a_blendIndices;								// Vertex blend index int u_matrixPalette	(0, 1, 2, 3)
+#endif
+
+// Uniforms
+uniform mat4 u_worldViewProjectionMatrix;					// Matrix to transform a position to clip space
+#if defined(SKINNING)
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];		// Array of 4x3 matrices
+#endif
+#if defined(TEXTURE_REPEAT)
+uniform vec2 u_textureRepeat;								// Texture repeat for tiling
+#endif
+#if defined(TEXTURE_OFFSET)
+uniform vec2 u_textureOffset;								// Texture offset
+#endif
+
+// Outputs
+varying vec2 v_texCoord;									// Texture Coordinate
+
+// Vertex attribute accessors
+#if defined(SKINNING)
+#include "lib/attributes-skinning.vert"
+#else
+#include "lib/attributes.vert" 
+#endif
+
+// Vertex Program
+void main()
+{
+    // Get the vertex position
+    vec4 position = getPosition();
+
+    // Transform position to clip space.
+    gl_Position = u_worldViewProjectionMatrix * position;
+
+    // Texture transformation.
+    v_texCoord = a_texCoord;
+    #if defined(TEXTURE_REPEAT)
+    v_texCoord *= u_textureRepeat;
+    #endif
+    #if defined(TEXTURE_OFFSET)
+    v_texCoord += u_textureOffset;
+    #endif
+}

+ 66 - 0
gameplay/res/shaders/textured.frag

@@ -0,0 +1,66 @@
+#define LIGHTING
+
+#ifdef OPENGL_ES
+precision highp float;
+#endif
+
+// Inputs
+varying vec3 v_normalVector;                    // Normal vector in view space
+varying vec2 v_texCoord;                        // Texture coordinate
+#if defined(POINT_LIGHT)
+varying vec3 v_vertexToPointLightDirection;		// Light direction w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;			// Attenuation of point light.
+#elif defined(SPOT_LIGHT)
+varying vec3 v_spotLightDirection;				// Direction of spot light in tangent space.
+varying vec3 v_vertexToSpotLightDirection;		// Direction of the spot light w.r.t current vertex in tangent space.
+varying float v_spotLightAttenuation;			// Attenuation of spot light.
+#else
+varying vec3 v_lightDirection;					// Direction of light in tangent space.
+#endif
+#if defined(SPECULAR)
+varying vec3 v_cameraDirection;                 // Camera direction
+#endif
+
+// Uniforms
+uniform sampler2D u_textureDiffuse;             // Diffuse map texture
+uniform vec3 u_lightDirection;					// Light direction
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_ambientColor;                    // Ambient color
+#if defined(SPECULAR)
+uniform float u_specularExponent;				// Specular exponent
+#endif
+#if defined(MODULATE_COLOR)
+uniform vec4 u_modulateColor;               	// Modulation color
+#endif
+#if defined(MODULATE_ALPHA)
+uniform float u_modulateAlpha;              	// Modulation alpha
+#endif
+#include "/lib/lighting.frag"
+#if defined(POINT_LIGHT)
+#include "lib/lighting-point.frag"
+#elif defined(SPOT_LIGHT)
+uniform float u_spotLightInnerAngleCos;			// The bright spot [0.0 - 1.0]
+uniform float u_spotLightOuterAngleCos;			// The soft outer part [0.0 - 1.0]
+#include "lib/lighting-spot.frag"
+#else
+#include "lib/lighting-directional.frag"
+#endif
+
+// Fragment Program
+void main()
+{
+    // Sample the diffuse texture for base color
+    _baseColor = texture2D(u_textureDiffuse, v_texCoord);
+
+    // Light the pixel
+    gl_FragColor.a = _baseColor.a;
+    gl_FragColor.rgb = getLitPixel();
+	
+	// Global color modulation
+	#if defined(MODULATE_COLOR)
+	gl_FragColor *= u_modulateColor;
+	#endif
+	#if defined(MODULATE_ALPHA)
+    gl_FragColor.a *= u_modulateAlpha;
+    #endif
+}

+ 0 - 22
gameplay/res/shaders/textured.fsh

@@ -1,22 +0,0 @@
-#ifdef OPENGL_ES
-precision highp float;
-#endif
-
-// Uniforms
-uniform sampler2D u_diffuseTexture;     // Diffuse texture
-uniform vec4 u_diffuseColor;            // Diffuse color/tint
-#if defined(GLOBAL_ALPHA)
-uniform float u_globalAlpha;            // Global alpha value
-#endif
-
-// Inputs
-varying vec2 v_texCoord;                // Texture coordinate (u, v).
-
-void main()
-{
-    gl_FragColor = texture2D(u_diffuseTexture, v_texCoord) * u_diffuseColor;
-
-#if defined(GLOBAL_ALPHA)
-    gl_FragColor.a *= u_globalAlpha;
-#endif
-}

+ 87 - 0
gameplay/res/shaders/textured.vert

@@ -0,0 +1,87 @@
+#define LIGHTING
+
+// Inputs
+attribute vec4 a_position;									// Vertex position							(x, y, z, w)
+attribute vec3 a_normal;									// Vertex normal							(x, y, z)
+attribute vec2 a_texCoord;									// Vertex texture coordinate				(u, v)
+#if defined(SKINNING)
+attribute vec4 a_blendWeights;								// Vertex blend weight, up to 4				(0, 1, 2, 3) 
+attribute vec4 a_blendIndices;								// Vertex blend index int u_matrixPalette	(0, 1, 2, 3)
+#endif
+
+// Uniforms
+uniform mat4 u_worldViewProjectionMatrix;					// Matrix to transform a position to clip space
+uniform mat4 u_inverseTransposeWorldViewMatrix;				// Matrix to transform a normal to view space
+#if defined(SKINNING)
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];		// Array of 4x3 matrices
+#endif
+#if defined(SPECULAR)
+uniform mat4 u_worldViewMatrix;								// Matrix to tranform a position to view space
+uniform vec3 u_cameraPosition;                 				// Position of the camera in view space
+#endif
+#if defined(TEXTURE_REPEAT)
+uniform vec2 u_textureRepeat;								// Texture repeat for tiling
+#endif
+#if defined(TEXTURE_OFFSET)
+uniform vec2 u_textureOffset;								// Texture offset
+#endif
+#if defined(POINT_LIGHT)
+uniform vec3 u_pointLightPosition;							// Position of light
+uniform float u_pointLightRangeInverse;						// Inverse of light range 
+#elif defined(SPOT_LIGHT)
+uniform vec3 u_spotLightPosition;							// Position of light
+uniform float u_spotLightRangeInverse;						// Inverse of light range
+#else
+#endif
+
+// Outputs
+varying vec3 v_normalVector;								// Normal vector in view space
+varying vec2 v_texCoord;									// Texture coordinate
+#if defined(SPECULAR)
+varying vec3 v_cameraDirection;								// Direction the camera is looking at in tangent space
+#endif
+#if defined(POINT_LIGHT)
+varying vec3 v_vertexToPointLightDirection;					// Direction of point light w.r.t current vertex in tangent space
+varying float v_pointLightAttenuation;						// Attenuation of point light
+#include "lib/lighting-point.vert"
+#elif defined(SPOT_LIGHT)
+varying vec3 v_vertexToSpotLightDirection;					// Direction of the spot light w.r.t current vertex in tangent space
+varying float v_spotLightAttenuation;						// Attenuation of spot light
+#include "lib/lighting-spot.vert"
+#else
+#include "lib/lighting-directional.vert"
+#endif
+
+// Vertex attribute accessors
+#if defined(SKINNING)
+#include "lib/attributes-skinning.vert"
+#else
+#include "lib/attributes.vert" 
+#endif
+
+// Vertex Program
+void main()
+{
+    // Get the position and normal from attribute accessors
+    vec4 position = getPosition();
+    vec3 normal = getNormal();
+
+    // Transform position to clip space.
+    gl_Position = u_worldViewProjectionMatrix * position;
+
+    // Transform normal to view space.
+    mat3 normalMatrix = mat3(u_inverseTransposeWorldViewMatrix[0].xyz, u_inverseTransposeWorldViewMatrix[1].xyz, u_inverseTransposeWorldViewMatrix[2].xyz);
+    v_normalVector = normalMatrix * normal;
+
+    // Apply light.
+    applyLight(position);
+    
+    // Texture transformation
+    v_texCoord = a_texCoord;
+    #if defined(TEXTURE_REPEAT)
+    v_texCoord *= u_textureRepeat;
+    #endif
+    #if defined(TEXTURE_OFFSET)
+    v_texCoord += u_textureOffset;
+    #endif
+}

+ 0 - 78
gameplay/res/shaders/textured.vsh

@@ -1,78 +0,0 @@
-// Uniforms
-uniform mat4 u_worldViewProjectionMatrix;       // Matrix to transform a position to clip space.
-
-// Inputs
-attribute vec4 a_position;                      // Vertex Position (x, y, z, w).
-attribute vec2 a_texCoord;                      // Vertex Texture Coordinate (u, v).
-
-// Outputs
-varying vec2 v_texCoord;                        // Texture coordinate (u, v).
-
-#if defined(SKINNING)
-
-attribute vec4 a_blendWeights;
-attribute vec4 a_blendIndices;
-
-// 32 4x3 matrices as an array of floats
-uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
-
-// Common vectors.
-vec4 _skinnedPosition;
-
-void skinPosition(float blendWeight, int matrixIndex)
-{
-    vec4 tmp;
-
-    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
-    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
-    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
-    tmp.w = a_position.w;
-
-    _skinnedPosition += blendWeight * tmp;
-}
-
-vec4 getPosition()
-{
-    _skinnedPosition = vec4(0.0);
-
-    // Transform position to view space using 
-    // matrix palette with four matrices used to transform a vertex.
-
-    float blendWeight = a_blendWeights[0];
-    int matrixIndex = int (a_blendIndices[0]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[1];
-    matrixIndex = int(a_blendIndices[1]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[2];
-    matrixIndex = int(a_blendIndices[2]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    blendWeight = a_blendWeights[3];
-    matrixIndex = int(a_blendIndices[3]) * 3;
-    skinPosition(blendWeight, matrixIndex);
-
-    return _skinnedPosition;    
-}
-
-#else
-
-vec4 getPosition()
-{
-    return a_position;    
-}
-
-#endif
-
-void main()
-{
-    vec4 position = getPosition();
-
-    // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * position;
-
-    // Pass on texture coordinate to fragment shader.
-    v_texCoord = a_texCoord;
-}

+ 54 - 6
gameplay/src/Button.cpp

@@ -5,11 +5,24 @@ namespace gameplay
 {
 
 Button::Button()
+    : _gamepadButtonIndex(NULL)
 {
 }
 
 Button::~Button()
 {
+    if (_gamepadButtonIndex)
+        SAFE_DELETE(_gamepadButtonIndex);
+}
+
+Button* Button::create(const char* id, Theme::Style* style)
+{
+    Button* button = new Button();
+
+    button->_id = id;
+    button->_style = style;
+
+    return button;
 }
 
 Button* Button::create(Theme::Style* style, Properties* properties)
@@ -23,21 +36,56 @@ Button* Button::create(Theme::Style* style, Properties* properties)
 bool Button::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
     if (!isEnabled())
-    {
         return false;
-    }
 
     switch (evt)
     {
     case Touch::TOUCH_PRESS:
-        setState(Control::ACTIVE);
+        if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+            y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
+        {
+            _contactIndex = (int) contactIndex;
+
+            setState(Control::ACTIVE);
+
+            notifyListeners(Listener::PRESS);
+
+            return _consumeInputEvents;
+        }
+        else
+        {
+            setState(Control::NORMAL);
+        }
         break;
+
     case Touch::TOUCH_RELEASE:
-        setState(Control::NORMAL);
+        _contactIndex = INVALID_CONTACT_INDEX;
+        notifyListeners(Listener::RELEASE);
+        if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+            y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
+        {
+            setState(Control::FOCUS);
+
+            notifyListeners(Listener::CLICK);
+
+            return _consumeInputEvents;
+        }
+        else
+        {
+            setState(Control::NORMAL);
+        }
         break;
+
+    case Touch::TOUCH_MOVE:
+        return _consumeInputEvents;
     }
 
-    return Control::touchEvent(evt, x, y, contactIndex);
+    return false;
 }
 
-}
+const char* Button::getType() const
+{
+    return "button";
+}
+
+}

+ 21 - 1
gameplay/src/Button.h

@@ -32,6 +32,19 @@ namespace gameplay
 class Button : public Label
 {
     friend class Container;
+    friend class Gamepad;
+
+public:
+
+    /**
+     * Create a new button control.
+     *
+     * @param id The control's ID.
+     * @param style The control's style.
+     *
+     * @return The new button.
+     */
+    static Button* create(const char* id, Theme::Style* style);
 
 protected:
 
@@ -69,14 +82,21 @@ protected:
      */
     bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
 private:
 
     /**
      * Constructor.
      */
     Button(const Button& copy);
+
+    int* _gamepadButtonIndex;
 };
 
 }
 
-#endif
+#endif

+ 17 - 0
gameplay/src/CheckBox.cpp

@@ -19,6 +19,18 @@ CheckBox::~CheckBox()
 
 }
 
+CheckBox* CheckBox::create(const char* id, Theme::Style* style)
+{
+    GP_ASSERT(style);
+
+    CheckBox* checkBox = new CheckBox();
+    if (id)
+        checkBox->_id = id;
+    checkBox->setStyle(style);
+
+    return checkBox;
+}
+
 CheckBox* CheckBox::create(Theme::Style* style, Properties* properties)
 {
     GP_ASSERT(properties);
@@ -159,4 +171,9 @@ void CheckBox::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
     spriteBatch->draw(pos.x, pos.y, size.x, size.y, uvs.u1, uvs.v1, uvs.u2, uvs.v2, color, _viewportClipBounds);
 }
 
+const char* CheckBox::getType() const
+{
+    return "checkBox";
+}
+
 }

+ 19 - 4
gameplay/src/CheckBox.h

@@ -37,6 +37,16 @@ class CheckBox : public Button
 
 public:
 
+    /**
+     * Create a new check box control.
+     *
+     * @param id The control's ID.
+     * @param style The control's style.
+     *
+     * @return The new check box.
+     */
+    static CheckBox* create(const char* id, Theme::Style* style);
+
     /**
      * Gets whether this checkbox is checked.
      *
@@ -66,6 +76,11 @@ public:
      */
     const Vector2& getImageSize() const;
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
     /**
      * Add a listener to be notified of specific events affecting
      * this control.  Event types can be OR'ed together.
@@ -130,7 +145,7 @@ protected:
      * @param clip The container position this control is relative to.
      */
     void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
-
+
     /**
      * Whether this checkbox is currently checked.
      */
@@ -140,11 +155,11 @@ protected:
      * The size to draw the checkbox icon, if different from its size in the texture.
      */
     Vector2 _imageSize;
-
+
     /**
      * The Theme::ThemeImage to display for the checkbox.
      */
-    Theme::ThemeImage* _image;
+    Theme::ThemeImage* _image;
 
 private:
 
@@ -156,4 +171,4 @@ private:
 
 }
 
-#endif
+#endif

+ 82 - 17
gameplay/src/Container.cpp

@@ -31,7 +31,7 @@ Container::Container()
       _scrollingVelocity(Vector2::zero()), _scrollingFriction(1.0f),
       _scrollingRight(false), _scrollingDown(false),
       _scrollingMouseVertically(false), _scrollingMouseHorizontally(false),
-      _scrollBarOpacityClip(NULL), _zIndexDefault(0), _totalWidth(0), _totalHeight(0)
+      _scrollBarOpacityClip(NULL), _zIndexDefault(0), _focusIndexDefault(0), _focusIndexMax(0), _totalWidth(0), _totalHeight(0)
 {
 }
 
@@ -49,6 +49,17 @@ Container::~Container()
     SAFE_RELEASE(_layout);
 }
 
+Container* Container::create(const char* id, Theme::Style* style, Layout::Type layoutType)
+{
+    GP_ASSERT(style);
+
+    Container* container = Container::create(layoutType);
+    if (id)
+        container->_id = id;
+    container->_style = style;
+    return container;
+}
+
 Container* Container::create(Layout::Type type)
 {
     Layout* layout = NULL;
@@ -160,6 +171,15 @@ void Container::addControls(Theme* theme, Properties* properties)
             {
                 control->setZIndex(_zIndexDefault++);
             }
+
+            if (control->getFocusIndex() == -1)
+            {
+                control->setFocusIndex(_focusIndexDefault++);
+            }
+
+            int focusIndex = control->getFocusIndex();
+            if (focusIndex > _focusIndexMax)
+                _focusIndexMax = focusIndex;
         }
 
         // Get the next control.
@@ -313,6 +333,11 @@ Animation* Container::getAnimation(const char* id) const
     return NULL;
 }
 
+const char* Container::getType() const
+{
+    return "container";
+}
+
 void Container::update(const Control* container, const Vector2& offset)
 {
     // Update this container's viewport.
@@ -395,7 +420,8 @@ void Container::draw(SpriteBatch* spriteBatch, const Rectangle& clip, bool needs
 
         spriteBatch->begin();
 
-        if (_scrollBarBounds.height > 0)
+        if (_scrollBarBounds.height > 0 &&
+            ((_scroll & SCROLL_VERTICAL) == SCROLL_VERTICAL))
         {
             const Rectangle& topRegion = _scrollBarTopCap->getRegion();
             const Theme::UVs& topUVs = _scrollBarTopCap->getUVs();
@@ -428,7 +454,8 @@ void Container::draw(SpriteBatch* spriteBatch, const Rectangle& clip, bool needs
             spriteBatch->draw(bounds.x, bounds.y, bounds.width, bounds.height, bottomUVs.u1, bottomUVs.v1, bottomUVs.u2, bottomUVs.v2, bottomColor, clipRegion);
         }
 
-        if (_scrollBarBounds.width > 0)
+        if (_scrollBarBounds.width > 0 &&
+            ((_scroll & SCROLL_HORIZONTAL) == SCROLL_HORIZONTAL))
         {
             const Rectangle& leftRegion = _scrollBarLeftCap->getRegion();
             const Theme::UVs& leftUVs = _scrollBarLeftCap->getUVs();
@@ -518,17 +545,40 @@ bool Container::keyEvent(Keyboard::KeyEvent evt, int key)
             continue;
         }
 
-        if (control->isContainer() || control->getState() == Control::FOCUS)
+        if (control->getState() == Control::FOCUS)
         {
             if (control->keyEvent(evt, key))
+            {
                 return _consumeInputEvents;
+            }
+            else if (evt == Keyboard::KEY_CHAR && key == Keyboard::KEY_TAB)
+            {
+                // Shift focus to next control.
+                int focusIndex = control->getFocusIndex() + 1; // Index to search for.
+                if (focusIndex > _focusIndexMax)
+                {
+                    focusIndex = 0;
+                }
+                control->setState(Control::NORMAL);
+
+                std::vector<Control*>::const_iterator itt;
+                for (itt = _controls.begin(); itt < _controls.end(); itt++)
+                {
+                    Control* nextControl = *itt;
+                    if (nextControl->getFocusIndex() == focusIndex)
+                    {
+                        nextControl->setState(Control::FOCUS);
+                        return _consumeInputEvents;
+                    }
+                }
+            }
         }
     }
 
     return false;
 }
 
-bool Container::isContainer()
+bool Container::isContainer() const
 {
     return true;
 }
@@ -873,6 +923,12 @@ bool Container::mouseEventScroll(Mouse::MouseEvent evt, int x, int y, int wheelD
 
         case Mouse::MOUSE_WHEEL:
             _scrollPosition.y += (_totalHeight / 10.0f) * wheelDelta;
+            if (_scrollBarOpacityClip && _scrollBarOpacityClip->isPlaying())
+            {
+                _scrollBarOpacityClip->stop();
+                _scrollBarOpacityClip = NULL;
+            }
+            _scrollBarOpacity = 1.0f;
             return _consumeInputEvents;
     }
 
@@ -917,7 +973,9 @@ bool Container::pointerEvent(bool mouse, char evt, int x, int y, int data)
             boundsY += offset->y;
         }
 
-        if (control->getState() != Control::NORMAL ||
+        Control::State currentState = control->getState();
+        if ((control->isContainer() && currentState == Control::FOCUS) ||
+            (currentState != Control::NORMAL && control->_contactIndex == data) ||
             ((evt == Touch::TOUCH_PRESS ||
               evt == Mouse::MOUSE_PRESS_LEFT_BUTTON ||
               evt == Mouse::MOUSE_PRESS_MIDDLE_BUTTON ||
@@ -941,25 +999,32 @@ bool Container::pointerEvent(bool mouse, char evt, int x, int y, int data)
         return (_consumeInputEvents | eventConsumed);
     }
 
-    switch (evt)
-    {
-    case Touch::TOUCH_PRESS:
-        setState(Control::FOCUS);
-        break;
-    case Touch::TOUCH_RELEASE:
-        setState(Control::NORMAL);
-        break;
-    }
-
     if (!eventConsumed && _scroll != SCROLL_NONE)
     {
-        if (mouse && mouseEventScroll((Mouse::MouseEvent)evt, x - xPos, y - yPos, data) ||
+        if ((mouse && mouseEventScroll((Mouse::MouseEvent)evt, x - xPos, y - yPos, data)) ||
             (!mouse && touchEventScroll((Touch::TouchEvent)evt, x - xPos, y - yPos, (unsigned int)data)))
         {
             _dirty = true;
+            eventConsumed = true;
         }
     }
 
+    switch (evt)
+    {
+    case Touch::TOUCH_PRESS:
+        if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+            y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
+        {
+            setState(Control::FOCUS);
+        }
+        else
+        {
+            setState(Control::NORMAL);
+            return false;
+        }
+        break;
+    }
+
     return (_consumeInputEvents | eventConsumed);
 }
 

+ 20 - 3
gameplay/src/Container.h

@@ -45,7 +45,6 @@ namespace gameplay
  */
 class Container : public Control
 {
-    friend class DropDownList;
 
 public:
 
@@ -65,6 +64,17 @@ public:
         SCROLL_BOTH = SCROLL_HORIZONTAL | SCROLL_VERTICAL
     };
 
+    /**
+     * Create a new container.
+     *
+     * @param id The container's ID.
+     * @param style The container's style.
+     * @param layoutType The container's layout type.
+     *
+     * @return The new container.
+     */
+    static Container* create(const char* id, Theme::Style* style, Layout::Type layoutType = Layout::LAYOUT_ABSOLUTE);
+
     /**
      * Get this container's layout.
      *
@@ -167,6 +177,11 @@ public:
      */
     Animation* getAnimation(const char* id = NULL) const;
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
     /**
      * @see AnimationTarget#getAnimationPropertyComponentCount
      */
@@ -274,10 +289,10 @@ protected:
 
     /**
      * Returns whether this control is a container.
-     * 
+     *
      * @return true if this is a container, false if not.
      */
-    bool isContainer();
+    bool isContainer() const;
 
     /**
      * Returns whether this container or any of its controls have been modified and require an update.
@@ -458,6 +473,8 @@ private:
 
     AnimationClip* _scrollBarOpacityClip;
     int _zIndexDefault;
+    int _focusIndexDefault;
+    int _focusIndexMax;
 
     float _totalWidth;
     float _totalHeight;

+ 61 - 14
gameplay/src/Control.cpp

@@ -6,8 +6,9 @@ namespace gameplay
 {
 
 Control::Control()
-    : _id(""), _state(Control::NORMAL), _bounds(Rectangle::empty()), _clipBounds(Rectangle::empty()), _viewportClipBounds(Rectangle::empty()),
-    _dirty(true), _consumeInputEvents(true), _listeners(NULL), _styleOverridden(false), _skin(NULL), _clearBounds(Rectangle::empty())
+    : _id(""), _state(Control::NORMAL), _bounds(Rectangle::empty()), _clipBounds(Rectangle::empty()), _viewportClipBounds(Rectangle::empty()),
+    _clearBounds(Rectangle::empty()), _dirty(true), _consumeInputEvents(true), _listeners(NULL), _contactIndex(INVALID_CONTACT_INDEX),
+    _styleOverridden(false), _skin(NULL)
 {
 }
 
@@ -52,6 +53,15 @@ void Control::initialize(Theme::Style* style, Properties* properties)
         _zIndex = -1;
     }
 
+    if (properties->exists("focusIndex"))
+    {
+        _focusIndex = properties->getInt("focusIndex");
+    }
+    else
+    {
+        _focusIndex = -1;
+    }
+
     Vector2 position;
     Vector2 size;
     if (properties->exists("position"))
@@ -75,8 +85,6 @@ void Control::initialize(Theme::Style* style, Properties* properties)
     }
     setBounds(Rectangle(position.x, position.y, size.x, size.y));
 
-    _state = Control::getState(properties->getString("state"));
-
     const char* id = properties->getId();
     if (id)
         _id = id;
@@ -121,6 +129,11 @@ void Control::initialize(Theme::Style* style, Properties* properties)
     }
 }
 
+void initialize(const char* id, Theme::Style* style, const Vector2& position, const Vector2& size)
+{
+
+}
+
 const char* Control::getID() const
 {
     return _id.c_str();
@@ -631,6 +644,16 @@ void Control::setZIndex(int zIndex)
     }
 }
 
+int Control::getFocusIndex() const
+{
+    return _focusIndex;
+}
+
+void Control::setFocusIndex(int focusIndex)
+{
+    _focusIndex = focusIndex;
+}
+
 void Control::addListener(Control::Listener* listener, int eventFlags)
 {
     GP_ASSERT(listener);
@@ -684,26 +707,46 @@ void Control::addSpecificListener(Control::Listener* listener, Listener::EventTy
 bool Control::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
     if (!isEnabled())
-    {
         return false;
-    }
 
     switch (evt)
     {
     case Touch::TOUCH_PRESS:
-        notifyListeners(Listener::PRESS);
-        return _consumeInputEvents;
+        // Controls that don't have an ACTIVE state go to the FOCUS state when pressed.
+        // (Other controls, such as buttons and sliders, become ACTIVE when pressed and go to the FOCUS state on release.)
+        // Labels are never any state other than NORMAL.
+        if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+            y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
+        {
+            _contactIndex = (int) contactIndex;
+
+            notifyListeners(Listener::PRESS);
+
+            return _consumeInputEvents;
+        }
+        else
+        {
+            // If this control was in focus, it's not any more.
+            _state = NORMAL;
+            _contactIndex = INVALID_CONTACT_INDEX;
+        }
+        break;
             
     case Touch::TOUCH_RELEASE:
+
+        _contactIndex = INVALID_CONTACT_INDEX;
+
         // Always trigger Listener::RELEASE
         notifyListeners(Listener::RELEASE);
 
         // Only trigger Listener::CLICK if both PRESS and RELEASE took place within the control's bounds.
-        if (x > 0 && x <= _bounds.width &&
-            y > 0 && y <= _bounds.height)
+        if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+            y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
         {
-            notifyListeners(Listener::CLICK);
+            // Leave this control in the FOCUS state.
+            notifyListeners(Listener::CLICK);
         }
+
         return _consumeInputEvents;
     }
 
@@ -955,7 +998,7 @@ bool Control::isDirty()
     return _dirty;
 }
 
-bool Control::isContainer()
+bool Control::isContainer() const
 {
     return false;
 }
@@ -999,6 +1042,11 @@ Theme::ThemeImage* Control::getImage(const char* id, State state)
     return imageList->getImage(id);
 }
 
+const char* Control::getType() const
+{
+    return "control";
+}
+
 // Implementation of AnimationHandler
 unsigned int Control::getAnimationPropertyComponentCount(int propertyId) const
 {
@@ -1085,8 +1133,7 @@ void Control::setAnimationPropertyValue(int propertyId, AnimationValue* value, f
         _dirty = true;
         break;
     case ANIMATE_OPACITY:
-        _dirty = true;
-    default:
+        _dirty = true;
         break;
     }
 }

+ 56 - 6
gameplay/src/Control.h

@@ -25,6 +25,7 @@ class Control : public Ref, public AnimationTarget
     friend class AbsoluteLayout;
     friend class VerticalLayout;
     friend class FlowLayout;
+    friend class Gamepad;
 
 public:
 
@@ -683,6 +684,20 @@ public:
      */
     void setZIndex(int zIndex);
 
+    /**
+     * Get this control's focus index.
+     *
+     * @return This control's focus index.
+     */
+    int getFocusIndex() const;
+
+    /**
+     * Set this control's focus index.
+     *
+     * @param focusIndex The new focus index.
+     */
+    void setFocusIndex(int focusIndex);
+
     /**
      * Add a listener to be notified of specific events affecting
      * this control.  Event types can be OR'ed together.
@@ -695,6 +710,13 @@ public:
      */
     virtual void addListener(Control::Listener* listener, int eventFlags);
 
+    /**
+     * Gets the type of the Control and returns it as a string.
+     *
+     * @return The string of the Control type, all in lower-case.
+     */
+    virtual const char* getType() const;
+
     /**
      * @see AnimationTarget#getAnimationPropertyComponentCount
      */
@@ -712,6 +734,11 @@ public:
 
 protected:
 
+    /**
+     *  Constant value representing an unset or invalid contact index.
+     */
+    static const int INVALID_CONTACT_INDEX = -1;
+
     /**
      * Constructor.
      */
@@ -807,16 +834,29 @@ protected:
     virtual void draw(SpriteBatch* spriteBatch, const Rectangle& clip, bool needsClear, bool cleared, float targetHeight);
 
     /**
-     * Initialize properties common to STATE_ALL Controls.
+     * Initialize properties common to all Controls from a Properties object.
+     *
+     * @param style The style to apply to this control.
+     * @param properties The properties to set on this control.
      */
     virtual void initialize(Theme::Style* style, Properties* properties);
 
+    /**
+     * Initialize properties common to all Controls.
+     *
+     * @param id This control's ID.
+     * @param style The style to apply to this control.
+     * @param position This control's position.
+     * @param size This control's size.
+     */
+    //virtual void initialize(const char* id, Theme::Style* style, const Vector2& position, const Vector2& size);
+
     /**
      * Container and classes that extend it should implement this and return true.
      *
      * @return true if this object is of class Container, false otherwise.
      */
-    virtual bool isContainer();
+    virtual bool isContainer() const;
 
     /**
      * Returns whether this control has been modified and requires an update.
@@ -930,14 +970,14 @@ protected:
     bool _autoHeight;
     
     /**
-     * The Control's Theme::Style.
+     * Listeners map of EventType's to a list of Listeners.
      */
-    Theme::Style* _style;
+    std::map<Listener::EventType, std::list<Listener*>*>* _listeners;
     
     /**
-     * Listeners map of EventType's to a list of Listeners.
+     * The Control's Theme::Style.
      */
-    std::map<Listener::EventType, std::list<Listener*>*>* _listeners;
+    Theme::Style* _style;
 
     /**
      * The current opacity of the control.
@@ -949,6 +989,16 @@ protected:
      */
     int _zIndex;
 
+    /**
+     * The contact index assigned to this control.
+     */
+    int _contactIndex;
+
+    /**
+     * The focus order of the control.
+     */
+    int _focusIndex;
+
 private:
 
     /*

+ 139 - 10
gameplay/src/Effect.cpp

@@ -2,7 +2,7 @@
 #include "Effect.h"
 #include "FileSystem.h"
 
-#define OPENGL_ES_DEFINE  "#define OPENGL_ES"
+#define OPENGL_ES_DEFINE  "#define OPENGL_ES\n"
 
 namespace gameplay
 {
@@ -102,6 +102,111 @@ Effect* Effect::createFromSource(const char* vshSource, const char* fshSource, c
     return createFromSource(NULL, vshSource, NULL, fshSource, defines);
 }
 
+
+void replaceDefines(const char* defines, std::string& out)
+{
+    if (defines && strlen(defines) != 0)
+    {
+        out = defines;
+        unsigned int pos;
+        out.insert(0, "#define ");
+        while ((pos = out.find(';')) != std::string::npos)
+        {
+            out.replace(pos, 1, "\n#define ");
+        }
+        out += "\n";
+    }
+#ifdef OPENGL_ES
+    out.insert(0, OPENGL_ES_DEFINE);
+#endif
+}
+
+void replaceIncludes(const char* filepath, const char* source, std::string& out)
+{
+    // Replace the #include "xxxx.xxx" with the sourced file contents of "filepath/xxxx.xxx"
+    std::string str = source;
+    size_t lastPos = 0;
+    size_t headPos = 0;
+    size_t tailPos = 0;
+    size_t fileLen = str.length();
+    tailPos = fileLen;
+    while (headPos < fileLen)
+    {
+        lastPos = headPos;
+        if (headPos == 0)
+        {
+            // find the first "#include"
+            headPos = str.find("#include");
+        }
+        else
+        {
+            // find the next "#include"
+            headPos = str.find("#include", headPos + 1);
+        }
+
+        // If "#include" is found
+        if (headPos != std::string::npos)
+        {
+            // append from our last position for the legth (head - last position) 
+            out.append(str.substr(lastPos,  headPos - lastPos));
+
+            // find the start quote "
+            size_t startQuote = str.find("\"", headPos) + 1;
+            if (startQuote == std::string::npos)
+            {
+                // We have started an "#include" but missing the leading quote "
+                GP_ERROR("Compile failed for shader '%s' missing leading \".", filepath);
+                return;
+            }
+            // find the end quote "
+            size_t endQuote = str.find("\"", startQuote);
+            if (endQuote == std::string::npos)
+            {
+                // We have a start quote but missing the trailing quote "
+                GP_ERROR("Compile failed for shader '%s' missing trailing \".", filepath);
+                return;
+            }
+
+            // jump the head position past the end quote
+            headPos = endQuote + 1;
+            
+            // File path to include and 'stitch' in the value in the quotes to the file path and source it.
+            std::string filepathStr = filepath;
+            std::string directoryPath = filepathStr.substr(0, filepathStr.rfind('/') + 1);
+            size_t len = endQuote - (startQuote);
+            std::string includeStr = str.substr(startQuote, len);
+            directoryPath.append(includeStr);
+            const char* includedSource = FileSystem::readAll(directoryPath.c_str());
+            if (includedSource == NULL)
+            {
+                GP_ERROR("Compile failed for shader '%s' invalid filepath.", filepathStr.c_str());
+                return;
+            }
+            else
+            {
+                // Valid file so lets attempt to see if we need to append anything to it too (recurse...)
+                replaceIncludes(directoryPath.c_str(), includedSource, out);
+                SAFE_DELETE_ARRAY(includedSource);
+            }
+        }
+        else
+        {
+            // Append the remaining
+            out.append(str.c_str(), lastPos, tailPos);
+        }
+    }
+}
+
+void writeShaderToErrorFile(const char* filePath, const char* source)
+{
+    std::string path = filePath;
+    path += ".err";
+    FILE* file = FileSystem::openFile(path.c_str(), "wb");
+    int err = ferror(file);
+    fwrite(source, 1, strlen(source), file);
+    fclose(file);
+}
+
 Effect* Effect::createFromSource(const char* vshPath, const char* vshSource, const char* fshPath, const char* fshSource, const char* defines)
 {
     GP_ASSERT(vshSource);
@@ -116,16 +221,23 @@ Effect* Effect::createFromSource(const char* vshPath, const char* vshSource, con
     GLint length;
     GLint success;
 
-    // Compile vertex shader.
-    std::string definesStr = (defines == NULL) ? "" : defines;
-#ifdef OPENGL_ES
-    if (defines && strlen(defines) != 0)
-        definesStr += "\n";
-    definesStr+= OPENGL_ES_DEFINE;
-#endif
+    // Replace all comma seperated definitions with #define prefix and \n suffix
+    std::string definesStr = "";
+    replaceDefines(defines, definesStr);
+    
     shaderSource[0] = definesStr.c_str();
     shaderSource[1] = "\n";
-    shaderSource[2] = vshSource;
+    std::string vshSourceStr = "";
+    if (vshPath)
+    {
+        // Replace the #include "xxxxx.xxx" with the sources that come from file paths
+        replaceIncludes(vshPath, vshSource, vshSourceStr);
+        if (vshSource && strlen(vshSource) != 0)
+            vshSourceStr += "\n";
+            
+        //writeShaderToErrorFile(vshPath, vshSourceStr.c_str());   // Debugging
+    }
+    shaderSource[2] = vshPath ? vshSourceStr.c_str() :  vshSource;
     GL_ASSERT( vertexShader = glCreateShader(GL_VERTEX_SHADER) );
     GL_ASSERT( glShaderSource(vertexShader, SHADER_SOURCE_LENGTH, shaderSource, NULL) );
     GL_ASSERT( glCompileShader(vertexShader) );
@@ -139,6 +251,9 @@ Effect* Effect::createFromSource(const char* vshPath, const char* vshSource, con
             GL_ASSERT( glGetShaderInfoLog(vertexShader, length, NULL, infoLog) );
             infoLog[length-1] = '\0';
         }
+
+        // Write out the expanded shader file.
+        writeShaderToErrorFile(vshPath, shaderSource[2]);
         GP_ERROR("Compile failed for vertex shader '%s' with error '%s'.", vshPath == NULL ? "NULL" : vshPath, infoLog == NULL ? "" : infoLog);
         SAFE_DELETE_ARRAY(infoLog);
 
@@ -149,7 +264,17 @@ Effect* Effect::createFromSource(const char* vshPath, const char* vshSource, con
     }
 
     // Compile the fragment shader.
-    shaderSource[2] = fshSource;
+    std::string fshSourceStr;
+    if (fshPath)
+    {
+        // Replace the #include "xxxxx.xxx" with the sources that come from file paths
+        replaceIncludes(fshPath, fshSource, fshSourceStr);
+        if (fshSource && strlen(fshSource) != 0)
+            fshSourceStr += "\n";
+
+        //writeShaderToErrorFile(fshPath, fshSourceStr.c_str()); // Debugging
+    }
+    shaderSource[2] = fshPath ? fshSourceStr.c_str() : fshSource;
     GL_ASSERT( fragmentShader = glCreateShader(GL_FRAGMENT_SHADER) );
     GL_ASSERT( glShaderSource(fragmentShader, SHADER_SOURCE_LENGTH, shaderSource, NULL) );
     GL_ASSERT( glCompileShader(fragmentShader) );
@@ -163,6 +288,10 @@ Effect* Effect::createFromSource(const char* vshPath, const char* vshSource, con
             GL_ASSERT( glGetShaderInfoLog(fragmentShader, length, NULL, infoLog) );
             infoLog[length-1] = '\0';
         }
+        
+        // Write out the expanded shader file.
+        writeShaderToErrorFile(fshPath, shaderSource[2]);
+
         GP_ERROR("Compile failed for fragment shader (%s): %s", fshPath == NULL ? "NULL" : fshPath, infoLog == NULL ? "" : infoLog);
         SAFE_DELETE_ARRAY(infoLog);
 

+ 8 - 5
gameplay/src/FileSystem.cpp

@@ -200,14 +200,14 @@ bool FileSystem::listFiles(const char* dirPath, std::vector<std::string>& files)
 #endif
 }
 
-bool FileSystem::fileExists(const char* path)
+bool FileSystem::fileExists(const char* filePath)
 {
-    GP_ASSERT(path);
+    GP_ASSERT(filePath);
 
     std::string fullPath(__resourcePath);
-    fullPath += resolvePath(path);
+    fullPath += resolvePath(filePath);
 
-    createFileFromAsset(path);
+    createFileFromAsset(filePath);
 
     gp_stat_struct s;
 // Win32 doesn't support an asset or bundle definitions.
@@ -216,7 +216,7 @@ bool FileSystem::fileExists(const char* path)
     {
         fullPath = __resourcePath;
         fullPath += "../../gameplay/";
-        fullPath += path;
+        fullPath += filePath;
         
         return stat(fullPath.c_str(), &s) == 0;
     }
@@ -229,6 +229,7 @@ bool FileSystem::fileExists(const char* path)
 FILE* FileSystem::openFile(const char* path, const char* mode)
 {
     GP_ASSERT(path);
+    GP_ASSERT(mode);
 
     std::string fullPath(__resourcePath);
     fullPath += resolvePath(path);
@@ -254,6 +255,8 @@ FILE* FileSystem::openFile(const char* path, const char* mode)
 
 char* FileSystem::readAll(const char* filePath, int* fileSize)
 {
+    GP_ASSERT(filePath);
+
     // Open file for reading.
     FILE* file = openFile(filePath, "rb");
     if (file == NULL)

+ 4 - 4
gameplay/src/FileSystem.h

@@ -95,10 +95,10 @@ public:
     /**
      * Checks if the file at the given path exists.
      * 
-     * @param path The path to the file.
+     * @param filePath The path to the file.
      * @return <code>true</code> if the file exists; <code>false</code> otherwise.
      */
-    static bool fileExists(const char* path);
+    static bool fileExists(const char* filePath);
 
     /**
      * Opens the specified file.
@@ -106,12 +106,12 @@ public:
      * The file at the specified location is opened, relative to the currently set
      * resource path.
      *
-     * @param path The path to the file to be opened, relative to the currently set resource path.
+     * @param filePath The path to the file to be opened, relative to the currently set resource path.
      * @param mode The mode used to open the file, passed directly to fopen.
      * 
      * @see setResourcePath(const char*)
      */
-    static FILE* openFile(const char* path, const char* mode);
+    static FILE* openFile(const char* filePath, const char* mode);
 
     /**
      * Reads the entire contents of the specified file and returns its contents.

+ 57 - 9
gameplay/src/Form.cpp

@@ -39,6 +39,43 @@ Form::~Form()
     }
 }
 
+Form* Form::create(const char* id, Theme::Style* style, Layout::Type layoutType)
+{
+    GP_ASSERT(style);
+
+    Layout* layout;
+    switch (layoutType)
+    {
+    case Layout::LAYOUT_ABSOLUTE:
+        layout = AbsoluteLayout::create();
+        break;
+    case Layout::LAYOUT_FLOW:
+        layout = FlowLayout::create();
+        break;
+    case Layout::LAYOUT_VERTICAL:
+        layout = VerticalLayout::create();
+        break;
+    default:
+        GP_ERROR("Unsupported layout type '%d'.", layoutType);
+        break;
+    }
+
+    Form* form = new Form();
+    if (id)
+        form->_id = id;
+    form->_style = style;
+    form->_layout = layout;
+    form->_theme = style->getTheme();
+
+    // Get default projection matrix.
+    Game* game = Game::getInstance();
+    Matrix::createOrthographicOffCenter(0, game->getWidth(), game->getHeight(), 0, 0, 1, &form->_defaultProjectionMatrix);
+
+    __forms.push_back(form);
+
+    return form;
+}
+
 Form* Form::create(const char* url)
 {
     // Load Form from .form file.
@@ -99,9 +136,7 @@ Form* Form::create(const char* url)
     }
     else
     {
-        Theme::Style::Overlay* overlay = Theme::Style::Overlay::create();
-        style = new Theme::Style(theme, "", 1.0f / theme->_texture->getWidth(), 1.0f / theme->_texture->getHeight(),
-            Theme::Margin::empty(), Theme::Border::empty(), overlay, overlay, overlay, overlay);
+        style = theme->getEmptyStyle();
     }
     form->initialize(style, formProperties);
 
@@ -159,6 +194,11 @@ Form* Form::getForm(const char* id)
     return NULL;
 }
 
+Theme* Form::getTheme() const
+{
+    return _theme;
+}
+
 void Form::setSize(float width, float height)
 {
     if (_autoWidth)
@@ -482,6 +522,11 @@ void Form::draw()
     }
 }
 
+const char* Form::getType() const
+{
+    return "form";
+}
+
 void Form::initializeQuad(Mesh* mesh)
 {
     // Release current model.
@@ -519,6 +564,7 @@ bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int
 {
     // Check for a collision with each Form in __forms.
     // Pass the event on.
+    bool eventConsumed = false;
     std::vector<Form*>::const_iterator it;
     for (it = __forms.begin(); it < __forms.end(); it++)
     {
@@ -540,7 +586,7 @@ bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int
                          point.y >= bounds.y &&
                          point.y <= bounds.y + bounds.height))
                     {
-                        return form->touchEvent(evt, point.x - bounds.x, bounds.height - point.y - bounds.y, contactIndex);
+                        eventConsumed |= form->touchEvent(evt, point.x - bounds.x, bounds.height - point.y - bounds.y, contactIndex);
                     }
                 }
             }
@@ -556,13 +602,13 @@ bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int
                         y <= bounds.y + bounds.height))
                 {
                     // Pass on the event's position relative to the form.
-                    return form->touchEvent(evt, x - bounds.x, y - bounds.y, contactIndex);
+                    eventConsumed |= form->touchEvent(evt, x - bounds.x, y - bounds.y, contactIndex);
                 }
             }
         }
     }
 
-    return false;
+    return eventConsumed;
 }
 
 bool Form::keyEventInternal(Keyboard::KeyEvent evt, int key)
@@ -584,6 +630,8 @@ bool Form::keyEventInternal(Keyboard::KeyEvent evt, int key)
 
 bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
 {
+    bool eventConsumed = false;
+
     std::vector<Form*>::const_iterator it;
     for (it = __forms.begin(); it < __forms.end(); it++)
     {
@@ -608,7 +656,7 @@ bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelt
                          point.y >= bounds.y &&
                          point.y <= bounds.y + bounds.height))
                     {
-                        return form->mouseEvent(evt, point.x - bounds.x, bounds.height - point.y - bounds.y, wheelDelta);
+                        eventConsumed |= form->mouseEvent(evt, point.x - bounds.x, bounds.height - point.y - bounds.y, wheelDelta);
                     }
                 }
             }
@@ -627,13 +675,13 @@ bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelt
                         y <= bounds.y + bounds.height))
                 {
                     // Pass on the event's position relative to the form.
-                    return form->mouseEvent(evt, x - bounds.x, y - bounds.y, wheelDelta);
+                    eventConsumed |= form->mouseEvent(evt, x - bounds.x, y - bounds.y, wheelDelta);
                 }
             }
         }
     }
 
-    return false;
+    return eventConsumed;
 }
 
 bool Form::projectPoint(int x, int y, Vector3* point)

+ 20 - 2
gameplay/src/Form.h

@@ -55,10 +55,21 @@ public:
      * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
      * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
      * 
-     * @param url The URL pointing to the Properties object defining the animation data. 
+     * @param url The URL pointing to the Properties object defining the form. 
      */
     static Form* create(const char* url);
 
+    /**
+     * Create a new Form.
+     *
+     * @param id The Form's ID.
+     * @param style The Form's style.
+     * @param layoutType The form's layout type.
+     *
+     * @return The new Form.
+     */
+    static Form* create(const char* id, Theme::Style* style, Layout::Type layoutType = Layout::LAYOUT_ABSOLUTE);
+
     /**
      * Get a form from its ID.
      *
@@ -68,6 +79,8 @@ public:
      */
     static Form* getForm(const char* id);
 
+    Theme* getTheme() const;
+
     /**
      * Set the desired size of this form.
      *
@@ -143,6 +156,11 @@ public:
      */
     void draw();
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
 private:
     
     /**
@@ -224,4 +242,4 @@ private:
 
 }
 
-#endif
+#endif

+ 1 - 1
gameplay/src/FrameBuffer.cpp

@@ -86,7 +86,7 @@ FrameBuffer* FrameBuffer::create(const char* id, unsigned int width, unsigned in
     frameBuffer->_renderTargets = renderTargets;
 
     frameBuffer->setRenderTarget(renderTarget, 0);
-    renderTarget->release(); // framebuffer now owns the rendertarget
+    SAFE_RELEASE(renderTarget);
 
     __frameBuffers.push_back(frameBuffer);
 

+ 76 - 2
gameplay/src/Game.cpp

@@ -20,7 +20,8 @@ Game::Game()
     : _initialized(false), _state(UNINITIALIZED), 
       _frameLastFPS(0), _frameCount(0), _frameRate(0), 
       _clearDepth(1.0f), _clearStencil(0), _properties(NULL),
-      _animationController(NULL), _audioController(NULL), _physicsController(NULL), _audioListener(NULL)
+      _animationController(NULL), _audioController(NULL), _physicsController(NULL), _audioListener(NULL), 
+      _gamepadCount(0), _gamepads(NULL)
 {
     GP_ASSERT(__gameInstance == NULL);
     __gameInstance = this;
@@ -95,7 +96,7 @@ bool Game::startup()
     setViewport(Rectangle(0.0f, 0.0f, (float)_width, (float)_height));
     RenderState::initialize();
     FrameBuffer::initialize();
-
+    
     _animationController = new AnimationController();
     _animationController->initialize();
 
@@ -105,6 +106,8 @@ bool Game::startup()
     _physicsController = new PhysicsController();
     _physicsController->initialize();
 
+    loadGamepad();
+    
     _state = RUNNING;
 
     return true;
@@ -122,6 +125,15 @@ void Game::shutdown()
         Platform::signalShutdown();
         finalize();
 
+        if (_gamepads)
+        {
+            for (unsigned int i = 0; i < _gamepadCount; i++)
+            {
+                SAFE_DELETE(_gamepads[i]);
+            }
+            SAFE_DELETE_ARRAY(_gamepads);
+        }
+
         _animationController->finalize();
         SAFE_DELETE(_animationController);
 
@@ -207,6 +219,12 @@ void Game::frame()
         // Update the physics.
         _physicsController->update(elapsedTime);
 
+        if (_gamepads)
+        {
+            for (unsigned int i = 0; i < _gamepadCount; i++)
+                _gamepads[i]->update();
+        }
+
         // Application Update.
         update(elapsedTime);
 
@@ -215,6 +233,12 @@ void Game::frame()
 
         // Graphics Rendering.
         render(elapsedTime);
+        
+        if (_gamepads)
+        {
+            for (unsigned int i = 0; i < _gamepadCount; i++)
+                _gamepads[i]->render();
+        }
 
         // Update FPS.
         ++_frameCount;
@@ -305,6 +329,10 @@ void Game::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactI
 {
 }
 
+void Game::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int index)
+{
+}
+
 void Game::schedule(float timeOffset, TimeListener* timeListener, void* cookie)
 {
     GP_ASSERT(_timeEvents);
@@ -386,4 +414,50 @@ bool Game::TimeEvent::operator<(const TimeEvent& v) const
     return time > v.time;
 }
 
+Gamepad* Game::createGamepad(const char* gamepadFormPath)
+{
+    GP_ASSERT(gamepadFormPath);
+
+    Gamepad* gamepad = new Gamepad(gamepadFormPath);
+    GP_ASSERT(gamepad);
+
+    if (!_gamepads)
+    {
+        _gamepadCount++;
+        _gamepads = new Gamepad*[_gamepadCount];
+        _gamepads[0] = gamepad;
+    }
+    else
+    {
+        int oldSize = _gamepadCount;
+        _gamepadCount++;
+        Gamepad** tempGamepads = new Gamepad*[_gamepadCount];
+        memcpy(tempGamepads, _gamepads, sizeof(Gamepad*) * oldSize);
+        tempGamepads[oldSize] = gamepad;
+        
+        SAFE_DELETE_ARRAY(_gamepads);
+        _gamepads = tempGamepads;
+    }
+
+    return gamepad;
+}
+
+void Game::loadGamepad()
+{
+    if (_properties)
+    {
+        // Check if there is a virtual keyboard included in the .config file.
+        // If there is, try to create it and assign it to "player one".
+        Properties* gamepadProperties = _properties->getNamespace("gamepad", true);
+        if (gamepadProperties && gamepadProperties->exists("form"))
+        {
+            const char* gamepadFormPath = gamepadProperties->getString("form");
+            GP_ASSERT(gamepadFormPath);
+
+            Gamepad* gamepad = createGamepad(gamepadFormPath);
+            GP_ASSERT(gamepad);
+        }
+    }
+}
+
 }

+ 33 - 0
gameplay/src/Game.h

@@ -13,6 +13,7 @@
 #include "Rectangle.h"
 #include "Vector4.h"
 #include "TimeListener.h"
+#include "Gamepad.h"
 
 namespace gameplay
 {
@@ -22,6 +23,7 @@ namespace gameplay
  */
 class Game
 {
+
 public:
 
     /**
@@ -267,6 +269,15 @@ public:
      */
     virtual bool mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
 
+    /**
+     * Gamepad callback on gamepad events.
+     *
+     * @param evt The gamepad event that occured.
+     * @param gamepad the gamepad the event occured on
+     * @param index The joystick or button index that triggered the event.
+     */
+    virtual void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int index);
+
     /**
      * Sets muli-touch is to be enabled/disabled. Default is disabled.
      *
@@ -299,6 +310,21 @@ public:
      */
     void schedule(float timeOffset, TimeListener* timeListener, void* cookie = 0);
 
+    /** 
+     * Creates a Gamepad object from a .form file.
+     *
+     * @param playerIndex
+     * @param formPath
+     */
+    Gamepad* createGamepad(const char* gamepadFormPath);
+
+    /**
+     * Gets the gamepad for the specified player index.
+     *
+     * @param playerIndex The player index to get the gamepad for (0 <= playerIndex <= 3) 
+     */
+    inline Gamepad* getGamepad(unsigned int playerIndex = 0);
+
 protected:
 
     /**
@@ -405,6 +431,11 @@ private:
      */
     void loadConfig();
 
+    /**
+     * Loads a gamepad from the configuration file.
+     */
+    void loadGamepad();
+
     bool _initialized;                          // If game has initialized yet.
     State _state;                               // The game state.
     static double _pausedTimeLast;              // The last time paused.
@@ -423,6 +454,8 @@ private:
     AudioController* _audioController;          // Controls audio sources that are playing in the game.
     PhysicsController* _physicsController;      // Controls the simulation of a physics scene and entities.
     AudioListener* _audioListener;              // The audio listener in 3D space.
+    unsigned int _gamepadCount;
+    Gamepad** _gamepads;
     std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >* _timeEvents; // Contains the scheduled time events.
 
     // Note: Do not add STL object member variables on the stack; this will cause false memory leaks to be reported.

+ 11 - 1
gameplay/src/Game.inl

@@ -72,4 +72,14 @@ inline void Game::displayKeyboard(bool display)
     Platform::displayKeyboard(display);
 }
 
-}
+inline Gamepad* Game::getGamepad(unsigned int playerIndex)
+{
+    GP_ASSERT(playerIndex < _gamepadCount);
+
+    if (_gamepads)
+        return _gamepads[playerIndex];
+    else
+        return NULL;
+}
+
+}

+ 181 - 0
gameplay/src/Gamepad.cpp

@@ -0,0 +1,181 @@
+#include "Base.h"
+#include "Gamepad.h"
+#include "Joystick.h"
+#include "Game.h"
+
+namespace gameplay
+{
+
+Gamepad::Gamepad()
+    : _playerIndex(-1), _joystickValues(NULL), _joystickCount(0), _buttonStates(NULL), _buttonCount(0), _gamepadForm(NULL)
+{
+}
+
+Gamepad::Gamepad(const char* formPath)
+    : _playerIndex(-1), _joystickValues(NULL), _joystickCount(0), _buttonStates(NULL), _buttonCount(0), _gamepadForm(NULL)
+{
+    GP_ASSERT(formPath);
+
+    _gamepadForm = Form::create(formPath);
+    GP_ASSERT(_gamepadForm);
+
+    _gamepadForm->setConsumeInputEvents(false);
+
+    getGamepadControls(_gamepadForm);
+
+    if (_joystickCount > 0)
+    {
+        _joystickValues = new Vector2*[_joystickCount];
+        for (unsigned int i = 0; i < _joystickCount; i++)
+        {
+            _joystickValues[i] = new Vector2();
+        }
+    }
+    if (_buttonCount > 0)
+    {
+        _buttonStates = new ButtonState*[_buttonCount];
+        for (unsigned int i = 0; i < _buttonCount; i++)
+        {
+            _buttonStates[i] = new ButtonState();
+        }
+    }
+}
+
+void Gamepad::getGamepadControls(Form* form)
+{
+    std::vector<Control*> controls = form->getControls();
+    std::vector<Control*>::iterator itr = controls.begin();
+
+    for (; itr != controls.end(); itr++)
+    {
+        Control* control = *itr;
+        GP_ASSERT(control);
+
+        if (std::strcmp("container", control->getType()) == 0)
+        {
+            getGamepadControls((Form*) control);
+        }
+        else if (std::strcmp("joystick", control->getType()) == 0)
+        {
+            control->addListener(this, Control::Listener::PRESS | Control::Listener::VALUE_CHANGED | Control::Listener::RELEASE);
+            Joystick* joystick = (Joystick*) control;
+            
+            if (!joystick->_gamepadJoystickIndex)
+                joystick->_gamepadJoystickIndex = new int[1];
+            
+            *joystick->_gamepadJoystickIndex = _joystickCount;
+            _joystickCount++;
+        }
+        else if (std::strcmp("button", control->getType()) == 0)
+        {
+            control->addListener(this, Control::Listener::PRESS | Control::Listener::RELEASE);
+            Button* button = (Button*) control;
+            
+            if (!button->_gamepadButtonIndex)
+                button->_gamepadButtonIndex = new int[1];
+
+            *button->_gamepadButtonIndex = _buttonCount;
+            _buttonCount++;
+        }
+    }
+}
+
+Gamepad::~Gamepad()
+{
+    if (_joystickValues)
+    {
+        for (unsigned int i = 0; i < _joystickCount; i++)
+            SAFE_DELETE(_joystickValues[i]);
+        SAFE_DELETE_ARRAY(_joystickValues);
+    }
+
+    if (_buttonStates)
+    {
+        for (unsigned int i = 0; i < _buttonCount; i++)
+           SAFE_DELETE(_buttonStates[i]);
+        SAFE_DELETE_ARRAY(_buttonStates);
+    }
+
+    if (_gamepadForm)
+        SAFE_RELEASE(_gamepadForm);
+}
+
+void Gamepad::update()
+{
+    if (_gamepadForm && _gamepadForm->isEnabled())
+    {
+        _gamepadForm->update();
+    }
+}
+
+void Gamepad::render()
+{
+    if (_gamepadForm && _gamepadForm->isEnabled())
+    {
+        _gamepadForm->draw();
+    }
+}
+
+void Gamepad::controlEvent(Control* control, Control::Listener::EventType evt)
+{
+    if (_gamepadForm && _gamepadForm->isEnabled())
+    {
+        if (std::strcmp("joystick", control->getType()) == 0)
+        {
+            int joystickIndex = *(((Joystick*) control)->_gamepadJoystickIndex);
+            switch(evt)
+            {
+                case Control::Listener::PRESS:
+                case Control::Listener::VALUE_CHANGED:
+                    _joystickValues[joystickIndex]->set(((Joystick*)control)->getValue());
+                    break;
+                case Control::Listener::RELEASE:
+                    _joystickValues[joystickIndex]->set(0.0f, 0.0f);
+                    break;
+            }
+            Game::getInstance()->gamepadEvent(JOYSTICK_EVENT, this, joystickIndex);
+        }
+        else if (std::strcmp("button", control->getType()) == 0)
+        {
+            int buttonIndex = *(((Button*) control)->_gamepadButtonIndex);
+            switch(evt)
+            {
+                case Control::Listener::PRESS:
+                    *_buttonStates[buttonIndex] = BUTTON_PRESSED;
+                    break;
+                case Control::Listener::RELEASE:
+                    *_buttonStates[buttonIndex] = BUTTON_RELEASED;
+                    break;
+            }
+            Game::getInstance()->gamepadEvent(BUTTON_EVENT, this, buttonIndex);
+        }
+    }
+}
+
+Gamepad::ButtonState Gamepad::getButtonState(unsigned int buttonId) const
+{
+    GP_ASSERT(buttonId < _buttonCount);
+
+    return *_buttonStates[buttonId];
+}
+
+bool Gamepad::isJoystickActive(unsigned int joystickId) const
+{
+    GP_ASSERT(joystickId < _joystickCount);
+
+    return !(_joystickValues[joystickId]->isZero());
+}
+
+const Vector2& Gamepad::getJoystickValue(unsigned int joystickId) const
+{
+    GP_ASSERT(joystickId < _joystickCount);
+
+    return *_joystickValues[joystickId];
+}
+
+bool Gamepad::isVirtual() const
+{
+    return (_gamepadForm && _gamepadForm->isEnabled());
+}
+
+}

+ 113 - 0
gameplay/src/Gamepad.h

@@ -0,0 +1,113 @@
+#ifndef GAMEPAD_H_
+#define GAMEPAD_H_
+
+#include "Form.h"
+#include "Button.h"
+
+namespace gameplay
+{
+
+/**
+ * Defines an interface for handling gamepad support.
+ */
+class Gamepad : public Control::Listener
+{
+    friend class Game;
+
+public:
+
+    enum GamepadEvent
+    {
+        JOYSTICK_EVENT,
+        BUTTON_EVENT
+    };
+
+    enum ButtonState
+    {
+        BUTTON_PRESSED = gameplay::Button::Listener::PRESS, 
+        BUTTON_RELEASED = gameplay::Button::Listener::RELEASE
+    };
+    
+    /** 
+     * Gets the current state of the specified button.
+     */
+    ButtonState getButtonState(unsigned int buttonId) const;
+
+    /**
+     * Gets whether the specified joystick's state is active or not.
+     * 
+     * @param joystickId The unique integer ID of the joystick to set.
+     * @return Whether the given joystick is active or not.
+     */
+    bool isJoystickActive(unsigned int joystickId) const;
+
+    /**
+     * Returns the specified joystick's value as a Vector2.
+     *
+     * @param joystickId The unique integer ID of the joystick to set.
+     * @return A Vector2 of the joystick displacement for the specified joystick.
+     */
+    const Vector2& getJoystickValue(unsigned int joystickId) const;
+
+    /** 
+     * Listener for Control events on the gamepads Joystick or Buttons.
+     */
+    void controlEvent(Control* control, Control::Listener::EventType evt);
+
+    /**
+     * Returns whether the gamepad is represented with a UI form or not.
+     */
+    bool isVirtual() const;
+
+private:
+
+    /**
+     * Constructor.
+     */
+    Gamepad();
+    
+    /**
+     * Constructor.
+     * Create a gamepad from the specified formPath.
+     *
+     * @param formPath
+     */ 
+    Gamepad(const char* formPath);
+
+    /**
+     * Copy constructor.
+     */
+    Gamepad(const Gamepad& copy);
+
+    /** 
+     * Destructor.
+     */
+    virtual ~Gamepad();
+    
+    /** 
+     * Gets the Joystick and Button Control object's from the specified form.
+     */
+    void getGamepadControls(Form* form);
+
+    /**
+     * Updates the gamepad.
+     */
+    void update();
+
+    /**
+     * Renders the gamepad if it is based on a form and if the form is enabled.
+     */
+    void render();
+
+    int _playerIndex;
+    Vector2** _joystickValues;
+    unsigned int _joystickCount;
+    ButtonState** _buttonStates;
+    unsigned int _buttonCount;
+
+    Form* _gamepadForm;
+};
+
+}
+
+#endif

+ 77 - 47
gameplay/src/Joystick.cpp

@@ -1,12 +1,10 @@
 #include "Base.h"
 #include "Joystick.h"
 
-#define INVALID_CONTACT_INDEX ((unsigned int)-1)
-
 namespace gameplay
 {
 
-Joystick::Joystick() : _contactIndex(INVALID_CONTACT_INDEX), _absolute(true)
+Joystick::Joystick() : _absolute(true), _gamepadJoystickIndex(NULL)
 {
 }
 
@@ -16,6 +14,20 @@ Joystick::Joystick(const Joystick& copy)
 
 Joystick::~Joystick()
 {
+    if (_gamepadJoystickIndex)
+        SAFE_DELETE(_gamepadJoystickIndex);
+}
+
+Joystick* Joystick::create(const char* id, Theme::Style* style)
+{
+    GP_ASSERT(style);
+
+    Joystick* joystick = new Joystick();
+    if (id)
+        joystick->_id = id;
+    joystick->setStyle(style);
+
+    return joystick;
 }
 
 Joystick* Joystick::create(Theme::Style* style, Properties* properties)
@@ -40,6 +52,11 @@ void Joystick::initialize(Theme::Style* style, Properties* properties)
     }
     _radius = properties->getFloat("radius");
 
+    if (properties->exists("absolute"))
+    {
+        setAbsolute(properties->getBool("absolute"));
+    }
+
     Vector4 v;
     if (properties->getVector4("region", &v))
     {
@@ -84,10 +101,12 @@ bool Joystick::touchEvent(Touch::TouchEvent touchEvent, int x, int y, unsigned i
                 _region.y = y + _bounds.y - _region.height * 0.5f;
             }
 
-            if ((dx >= -_radius && dx <= _radius) && (dy >= -_radius && dy <= _radius) && 
-                _contactIndex == INVALID_CONTACT_INDEX)
+            if ((dx >= -_radius && dx <= _radius) && (dy >= -_radius && dy <= _radius))
             {
-                _contactIndex = contactIndex;
+                _contactIndex = (int) contactIndex;
+
+                notifyListeners(Listener::PRESS);
+
                 _displacement.set(0.0f, 0.0f);
                 
                 Vector2 value(0.0f, 0.0f);
@@ -99,67 +118,71 @@ bool Joystick::touchEvent(Touch::TouchEvent touchEvent, int x, int y, unsigned i
                 }
 
                 _state = ACTIVE;
+
+                return _consumeInputEvents;
+            }
+            else
+            {
+                _state = NORMAL;
             }
+            break;
         }
         case Touch::TOUCH_MOVE:
         {
-            if (_contactIndex == contactIndex)
+            float dx = x - ((!_absolute) ? _region.x - _bounds.x : 0.0f) - _region.width * 0.5f;
+            float dy = -(y - ((!_absolute) ? _region.y - _bounds.y : 0.0f) - _region.height * 0.5f);
+            if (((dx * dx) + (dy * dy)) <= (_radius * _radius))
             {
-                float dx = x - ((!_absolute) ? _region.x - _bounds.x : 0.0f) - _region.width * 0.5f;
-                float dy = -(y - ((!_absolute) ? _region.y - _bounds.y : 0.0f) - _region.height * 0.5f);
-                if (((dx * dx) + (dy * dy)) <= (_radius * _radius))
-                {
-                    GP_ASSERT(_radius);
-                    Vector2 value(dx, dy);
-                    value.scale(1.0f / _radius);
-                    if (_value != value)
-                    {
-                        _value.set(value);
-                        _dirty = true;
-                        notifyListeners(Control::Listener::VALUE_CHANGED);
-                    }
-                }
-                else
+                GP_ASSERT(_radius);
+                Vector2 value(dx, dy);
+                value.scale(1.0f / _radius);
+                if (_value != value)
                 {
-                    Vector2 value(dx, dy);
-                    value.normalize();
-                    value.scale(_radius);
-                    value.normalize();
-                    if (_value != value)
-                    {
-                        _value.set(value);
-                        _dirty = true;
-                        notifyListeners(Control::Listener::VALUE_CHANGED);
-                    }
+                    _value.set(value);
+                    _dirty = true;
+                    notifyListeners(Control::Listener::VALUE_CHANGED);
                 }
-
-                _displacement.set(dx, dy);
             }
-        }
-        break;
-        case Touch::TOUCH_RELEASE:
-        {
-            if (_contactIndex == contactIndex)
+            else
             {
-                // Reset displacement and direction vectors.
-                _contactIndex = INVALID_CONTACT_INDEX;
-                _displacement.set(0.0f, 0.0f);
-                
-                Vector2 value(0.0f, 0.0f);
+                Vector2 value(dx, dy);
+                value.normalize();
+                value.scale(_radius);
+                value.normalize();
                 if (_value != value)
                 {
                     _value.set(value);
                     _dirty = true;
                     notifyListeners(Control::Listener::VALUE_CHANGED);
                 }
+            }
 
-                _state = NORMAL;
+            _displacement.set(dx, dy);
+
+            return _consumeInputEvents;
+        }
+        case Touch::TOUCH_RELEASE:
+        {
+            _contactIndex = INVALID_CONTACT_INDEX;
+
+            // Reset displacement and direction vectors.
+            _displacement.set(0.0f, 0.0f);
+
+            Vector2 value(0.0f, 0.0f);
+            if (_value != value)
+            {
+                _value.set(value);
+                _dirty = true;
+                notifyListeners(Control::Listener::VALUE_CHANGED);
             }
+
+            _state = NORMAL;
+
+            return _consumeInputEvents;
         }
-        break;
     }
 
-    return Control::touchEvent(touchEvent, x, y, contactIndex);
+    return false;
 }
 
 void Joystick::update(const Control* container, const Vector2& offset)
@@ -226,4 +249,11 @@ void Joystick::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
     spriteBatch->end();
 }
 
+const char* Joystick::getType() const
+{
+    return "joystick";
+}
+
+
+
 }

+ 17 - 1
gameplay/src/Joystick.h

@@ -12,8 +12,19 @@ namespace gameplay
 class Joystick : public Control
 {
     friend class Container;
+    friend class Gamepad;
 
 public:
+
+    /**
+     * Create a new joystick control.
+     *
+     * @param id The control's ID.
+     * @param style The control's style.
+     *
+     * @return The new joystick.
+     */
+    static Joystick* create(const char* id, Theme::Style* style);
     
     /**
      * Add a listener to be notified of specific events affecting
@@ -69,6 +80,11 @@ public:
      */
     inline bool isAbsolute() const;
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
 protected:
     
     /**
@@ -135,11 +151,11 @@ private:
     Joystick(const Joystick& copy);
 
     float _radius;
-    unsigned int _contactIndex;
     bool _absolute;
     Vector2 _displacement;
     Vector2 _value;
     Rectangle _region;
+    int* _gamepadJoystickIndex;
 };
 
 }

+ 21 - 1
gameplay/src/Label.cpp

@@ -16,11 +16,26 @@ Label::~Label()
 {
 }
 
+Label* Label::create(const char* id, Theme::Style* style)
+{
+    GP_ASSERT(style);
+
+    Label* label = new Label();
+    if (id)
+        label->_id = id;
+    label->setStyle(style);
+
+    return label;
+}
+
 Label* Label::create(Theme::Style* style, Properties* properties)
 {
     Label* label = new Label();
     label->initialize(style, properties);
     label->_consumeInputEvents = false;
+    
+    // Ensure that labels cannot receive focus.
+    label->_focusIndex = -2;
 
     return label;
 }
@@ -97,4 +112,9 @@ void Label::drawText(const Rectangle& clip)
     _dirty = false;
 }
 
-}
+const char* Label::getType() const
+{
+    return "label";
+}
+
+}

+ 16 - 1
gameplay/src/Label.h

@@ -33,6 +33,16 @@ class Label : public Control
 
 public:
 
+    /**
+     * Create a new label control.
+     *
+     * @param id The control's ID.
+     * @param style The control's style.
+     *
+     * @return The new label.
+     */
+    static Label* create(const char*id, Theme::Style* style);
+
     /**
      * Set the text for this label to display.
      *
@@ -47,6 +57,11 @@ public:
      */
     const char* getText();
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
     /**
      * Add a listener to be notified of specific events affecting
      * this control.  Event types can be OR'ed together.
@@ -132,4 +147,4 @@ private:
 
 }
 
-#endif
+#endif

+ 1 - 13
gameplay/src/Material.cpp

@@ -242,21 +242,9 @@ bool Material::loadPass(Technique* technique, Properties* passProperties)
     const char* fragmentShaderPath = passProperties->getString("fragmentShader");
     GP_ASSERT(fragmentShaderPath);
     const char* defines = passProperties->getString("defines");
-    std::string define;
-    if (defines != NULL)
-    {
-        define = defines;
-        define.insert(0, "#define ");
-        unsigned int pos;
-        while ((pos = define.find(';')) != std::string::npos)
-        {
-            define.replace(pos, 1, "\n#define ");
-        }
-        define += "\n";
-    }
 
     // Create the pass.
-    Pass* pass = Pass::create(passProperties->getId(), technique, vertexShaderPath, fragmentShaderPath, define.c_str());
+    Pass* pass = Pass::create(passProperties->getId(), technique, vertexShaderPath, fragmentShaderPath, defines);
     if (!pass)
     {
         GP_ERROR("Failed to create pass for technique.");

+ 0 - 1
gameplay/src/MaterialParameter.cpp

@@ -227,7 +227,6 @@ Texture::Sampler* MaterialParameter::setValue(const char* texturePath, bool gene
         }
         return sampler;
     }
-
     return NULL;
 }
 

+ 1 - 1
gameplay/src/PlatformWin32.cpp

@@ -312,7 +312,7 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         UpdateCapture(wParam);
         lx = GET_X_LPARAM(lParam);
         ly = GET_Y_LPARAM(lParam);
-        gameplay::Platform::mouseEventInternal(gameplay::Mouse::MOUSE_RELEASE_RIGHT_BUTTON, lx, ly, 0);
+        gameplay::Platform::mouseEventInternal(gameplay::Mouse::MOUSE_PRESS_RIGHT_BUTTON, lx, ly, 0);
         break;
 
     case WM_RBUTTONUP:

+ 18 - 1
gameplay/src/RadioButton.cpp

@@ -24,6 +24,18 @@ RadioButton::~RadioButton()
     }
 }
 
+RadioButton* RadioButton::create(const char* id, Theme::Style* style)
+{
+    GP_ASSERT(style);
+
+    RadioButton* radioButton = new RadioButton();
+    if (id)
+        radioButton->_id = id;
+    radioButton->setStyle(style);
+
+    return radioButton;
+}
+
 RadioButton* RadioButton::create(Theme::Style* style, Properties* properties)
 {
     GP_ASSERT(properties);
@@ -186,4 +198,9 @@ void RadioButton::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
     spriteBatch->draw(pos.x, pos.y, size.x, size.y, uvs.u1, uvs.v1, uvs.u2, uvs.v2, color, _viewportClipBounds);
 }
 
-}
+const char* RadioButton::getType() const
+{
+    return "radioButton";
+}
+
+}

+ 17 - 1
gameplay/src/RadioButton.h

@@ -38,6 +38,17 @@ class RadioButton : public Button
     friend class Container;
 
 public:
+
+    /**
+     * Create a new radio button control.
+     *
+     * @param id The control's ID.
+     * @param style The control's style.
+     *
+     * @return The new radio button.
+     */
+    static RadioButton* create(const char* id, Theme::Style* style);
+
     /**
      * Get whether this radio button is currently selected.
      *
@@ -60,6 +71,11 @@ public:
      */
     const Vector2& getImageSize() const;
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
     /**
      * Add a listener to be notified of specific events affecting
      * this control.  Event types can be OR'ed together.
@@ -159,4 +175,4 @@ private:
 
 }
 
-#endif
+#endif

+ 17 - 20
gameplay/src/RenderState.cpp

@@ -293,7 +293,7 @@ void RenderState::bind(Pass* pass)
     // Apply parameter bindings and renderer state for the entire hierarchy, top-down.
     rs = NULL;
     Effect* effect = pass->getEffect();
-    while (rs = getTopmost(rs))
+    while ((rs = getTopmost(rs)))
     {
         for (unsigned int i = 0, count = rs->_parameters.size(); i < count; ++i)
         {
@@ -360,8 +360,9 @@ void RenderState::cloneInto(RenderState* renderState, NodeCloneContext& context)
 }
 
 RenderState::StateBlock::StateBlock()
-    : _blendEnabled(false), _cullFaceEnabled(false), _depthTestEnabled(false), _depthWriteEnabled(false),
-      _srcBlend(RenderState::BLEND_ONE), _dstBlend(RenderState::BLEND_ZERO), _bits(0L)
+    : _cullFaceEnabled(false), _depthTestEnabled(false), _depthWriteEnabled(false),
+      _blendEnabled(false), _blendSrc(RenderState::BLEND_ONE), _blendDst(RenderState::BLEND_ONE),
+      _bits(0L)
 {
 }
 
@@ -404,11 +405,11 @@ void RenderState::StateBlock::bindNoRestore()
             GL_ASSERT( glDisable(GL_BLEND) );
         _defaultState->_blendEnabled = _blendEnabled;
     }
-    if ((_bits & RS_BLEND_FUNC) && (_srcBlend != _defaultState->_srcBlend || _dstBlend != _defaultState->_dstBlend))
+    if ((_bits & RS_BLEND_FUNC) && (_blendSrc != _defaultState->_blendSrc || _blendDst != _defaultState->_blendDst))
     {
-        GL_ASSERT( glBlendFunc((GLenum)_srcBlend, (GLenum)_dstBlend) );
-        _defaultState->_srcBlend = _srcBlend;
-        _defaultState->_dstBlend = _dstBlend;
+        GL_ASSERT( glBlendFunc((GLenum)_blendSrc, (GLenum)_blendDst) );
+        _defaultState->_blendSrc = _blendSrc;
+        _defaultState->_blendDst = _blendDst;
     }
     if ((_bits & RS_CULL_FACE) && (_cullFaceEnabled != _defaultState->_cullFaceEnabled))
     {
@@ -454,10 +455,10 @@ void RenderState::StateBlock::restore(long stateOverrideBits)
     }
     if (!(stateOverrideBits & RS_BLEND_FUNC) && (_defaultState->_bits & RS_BLEND_FUNC))
     {
-        GL_ASSERT( glBlendFunc(GL_ONE, GL_ZERO) );
+        GL_ASSERT( glBlendFunc(GL_ONE, GL_ONE) );
         _defaultState->_bits &= ~RS_BLEND_FUNC;
-        _defaultState->_srcBlend = RenderState::BLEND_ONE;
-        _defaultState->_dstBlend = RenderState::BLEND_ZERO;
+        _defaultState->_blendSrc = RenderState::BLEND_ONE;
+        _defaultState->_blendDst = RenderState::BLEND_ONE;
     }
     if (!(stateOverrideBits & RS_CULL_FACE) && (_defaultState->_bits & RS_CULL_FACE))
     {
@@ -550,11 +551,11 @@ void RenderState::StateBlock::setState(const char* name, const char* value)
     {
         setBlend(parseBoolean(value));
     }
-    else if (strcmp(name, "srcBlend") == 0)
+    else if (strcmp(name, "blendSrc") == 0 || strcmp(name, "srcBlend") == 0 )   // Leaving srcBlend for backward compat.
     {
         setBlendSrc(parseBlend(value));
     }
-    else if (strcmp(name, "dstBlend") == 0)
+    else if (strcmp(name, "blendDst") == 0 || strcmp(name, "dstBlend") == 0)    // // Leaving dstBlend for backward compat.
     {
         setBlendDst(parseBlend(value));
     }
@@ -591,30 +592,26 @@ void RenderState::StateBlock::setBlend(bool enabled)
 
 void RenderState::StateBlock::setBlendSrc(Blend blend)
 {
-    _srcBlend = blend;
-    if (_srcBlend == BLEND_ONE && _dstBlend == BLEND_ZERO)
+    _blendSrc = blend;
+    if (_blendSrc == BLEND_ONE && _blendDst == BLEND_ONE)
     {
-        // Default blend function, disable bit
         _bits &= ~RS_BLEND_FUNC;
     }
     else
     {
-        // Custom blend function, enable bit
         _bits |= RS_BLEND_FUNC;
     }
 }
 
 void RenderState::StateBlock::setBlendDst(Blend blend)
 {
-    _dstBlend = blend;
-    if (_srcBlend == BLEND_ONE && _dstBlend == BLEND_ZERO)
+    _blendDst = blend;
+    if (_blendSrc == BLEND_ONE && _blendDst == BLEND_ONE)
     {
-        // Default blend function, disable bit
         _bits &= ~RS_BLEND_FUNC;
     }
     else
     {
-        // Custom blend function, enable bit
         _bits |= RS_BLEND_FUNC;
     }
 }

+ 3 - 4
gameplay/src/RenderState.h

@@ -213,13 +213,12 @@ public:
         static void enableDepthWrite();
 
         // States
-        bool _blendEnabled;
         bool _cullFaceEnabled;
         bool _depthTestEnabled;
         bool _depthWriteEnabled;
-        Blend _srcBlend;
-        Blend _dstBlend;
-        // State bits
+        bool _blendEnabled;
+        Blend _blendSrc;
+        Blend _blendDst;
         long _bits;
 
         static StateBlock* _defaultState;

+ 74 - 2
gameplay/src/Slider.cpp

@@ -3,6 +3,9 @@
 namespace gameplay
 {
 
+// Fraction of slider to scroll when mouse scrollwheel is used.
+static const float SCROLL_FRACTION = 0.1f;
+
 Slider::Slider() : _minImage(NULL), _maxImage(NULL), _trackImage(NULL), _markerImage(NULL)
 {
 }
@@ -11,6 +14,18 @@ Slider::~Slider()
 {
 }
 
+Slider* Slider::create(const char* id, Theme::Style* style)
+{
+    GP_ASSERT(style);
+
+    Slider* slider = new Slider();
+    if (id)
+        slider->_id = id;
+    slider->setStyle(style);
+
+    return slider;
+}
+
 Slider* Slider::create(Theme::Style* style, Properties* properties)
 {
     GP_ASSERT(properties);
@@ -133,13 +148,65 @@ bool Slider::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contac
 
         if (evt == Touch::TOUCH_RELEASE)
         {
-            _state = NORMAL;
+            _state = FOCUS;
             _dirty = true;
         }
         break;
     }
+    
+    if (evt == Touch::TOUCH_MOVE)
+        return _consumeInputEvents;
+    else
+        return Control::touchEvent(evt, x, y, contactIndex);
+}
+
+bool Slider::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
+{
+    if (!isEnabled())
+    {
+        return false;
+    }
 
-    return Control::touchEvent(evt, x, y, contactIndex);
+    switch (evt)
+    {
+        case Mouse::MOUSE_PRESS_LEFT_BUTTON:
+            return touchEvent(Touch::TOUCH_PRESS, x, y, 0);
+
+        case Mouse::MOUSE_MOVE:
+            return touchEvent(Touch::TOUCH_MOVE, x, y, 0);
+
+        case Mouse::MOUSE_RELEASE_LEFT_BUTTON:
+            return touchEvent(Touch::TOUCH_RELEASE, x, y, 0);
+
+        case Mouse::MOUSE_WHEEL:
+        {
+            if (_state == FOCUS)
+            {
+                float total = _max - _min;
+                float oldValue = _value;
+                _value += (total * SCROLL_FRACTION) * wheelDelta;
+            
+                if (_value > _max)
+                    _value = _max;
+                else if (_value < _min)
+                    _value = _min;
+
+                if (_value != oldValue)
+                {
+                    notifyListeners(Listener::VALUE_CHANGED);
+                }
+
+                _dirty = true;
+                return _consumeInputEvents;
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    return false;
 }
 
 void Slider::update(const Control* container, const Vector2& offset)
@@ -208,4 +275,9 @@ void Slider::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
     spriteBatch->draw(pos.x, pos.y, markerRegion.width, markerRegion.height, marker.u1, marker.v1, marker.u2, marker.v2, markerColor, _viewportClipBounds);
 }
 
+const char* Slider::getType() const
+{
+    return "slider";
+}
+
 }

+ 29 - 0
gameplay/src/Slider.h

@@ -35,6 +35,16 @@ class Slider : public Label
 
 public:
 
+    /**
+     * Create a new slider control.
+     *
+     * @param id The control's ID.
+     * @param style The control's style.
+     *
+     * @return The new slider.
+     */
+    static Slider* create(const char* id, Theme::Style* style);
+
     /**
      * Set the minimum value that can be set on this slider.
      *
@@ -93,6 +103,11 @@ public:
      */
     float getValue();
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
     /**
      * Add a listener to be notified of specific events affecting
      * this control.  Event types can be OR'ed together.
@@ -141,6 +156,20 @@ protected:
      */
     bool touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
+    /**
+     * Mouse callback on mouse events.
+     *
+     * @param evt The mouse event that occurred.
+     * @param x The x position of the mouse in pixels. Left edge is zero.
+     * @param y The y position of the mouse in pixels. Top edge is zero.
+     * @param wheelDelta The number of mouse wheel ticks. Positive is up (forward), negative is down (backward).
+     *
+     * @return True if the mouse event is consumed or false if it is not consumed.
+     *
+     * @see Mouse::MouseEvent
+     */
+    bool mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
+
     /**
      * Draw the images associated with this control.
      *

+ 0 - 25
gameplay/src/SpriteBatch.cpp

@@ -256,17 +256,6 @@ void SpriteBatch::draw(const Vector3& position, const Vector3& right, const Vect
     float u1, float v1, float u2, float v2, const Vector4& color, const Vector2& rotationPoint, float rotationAngle)
 {
     // Calculate the vertex positions.
-    //static Vector3 p[4];
-
-    // Pre-optimized:
-    /*
-    p[0] = position - 0.5f * width * right - 0.5f * height * forward;
-    p[1] = position + 0.5f * width * right - 0.5f * height * forward;
-    p[2] = p[0] + height * forward;
-    p[3] = p[1] + height * forward;
-    */
-    
-    // Optimized:
     Vector3 tRight(right);
     tRight *= width * 0.5f;
     Vector3 tForward(forward);
@@ -288,11 +277,6 @@ void SpriteBatch::draw(const Vector3& position, const Vector3& right, const Vect
     p3 += tForward;
 
     // Calculate the rotation point.
-    
-    // Pre-optimized:
-    //Vector3 rp = p[0] + (rotationPoint.x * width * right) + (rotationPoint.y * height * forward);
-
-    // Optimized:
     Vector3 rp = p0;
     tRight = right;
     tRight *= width * rotationPoint.x;
@@ -306,15 +290,6 @@ void SpriteBatch::draw(const Vector3& position, const Vector3& right, const Vect
     static Matrix rotation;
     Matrix::createRotation(u, rotationAngle, &rotation);
 
-    // Pre-optimized:
-    /*
-    p[0] = (rotation * (p[0] - rp)) + rp;
-    p[1] = (rotation * (p[1] - rp)) + rp;
-    p[2] = (rotation * (p[2] - rp)) + rp;
-    p[3] = (rotation * (p[3] - rp)) + rp;
-    */
-
-    // Optimized:
     p0 -= rp;
     p0 *= rotation;
     p0 += rp;

+ 60 - 25
gameplay/src/TextBox.cpp

@@ -16,6 +16,18 @@ TextBox::~TextBox()
 {
 }
 
+TextBox* TextBox::create(const char* id, Theme::Style* style)
+{
+    GP_ASSERT(style);
+
+    TextBox* textBox = new TextBox();
+    if (id)
+        textBox->_id = id;
+    textBox->setStyle(style);
+
+    return textBox;
+}
+
 TextBox* TextBox::create(Theme::Style* style, Properties* properties)
 {
     TextBox* textBox = new TextBox();
@@ -49,36 +61,35 @@ bool TextBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int conta
     switch (evt)
     {
     case Touch::TOUCH_PRESS: 
-        if (_state == NORMAL)
-        {
-            _state = ACTIVE;
-            Game::getInstance()->displayKeyboard(true);
-            _dirty = true;
-            return _consumeInputEvents;
-        }
-        else if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
+        if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
                  y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
         {
-            setCaretLocation(x, y);
+            _contactIndex = (int) contactIndex;
+
+            if (_state == NORMAL)
+                Game::getInstance()->displayKeyboard(true);
+            else
+                setCaretLocation(x, y);
+
+            _state = ACTIVE;
             _dirty = true;
-            return _consumeInputEvents;
         }
         else
         {
+            _contactIndex = INVALID_CONTACT_INDEX;
             _state = NORMAL;
             Game::getInstance()->displayKeyboard(false);
             _dirty = true;
-            return _consumeInputEvents;
+            return false;
         }
         break;
     case Touch::TOUCH_MOVE:
-        if (_state == FOCUS &&
+        if (_state == ACTIVE &&
             x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
             y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
         {
             setCaretLocation(x, y);
             _dirty = true;
-            return _consumeInputEvents;
         }
         break;
     case Touch::TOUCH_RELEASE:
@@ -87,16 +98,14 @@ bool TextBox::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int conta
         {
             setCaretLocation(x, y);
             _state = FOCUS;
-            _dirty = true;
-            return _consumeInputEvents;
         }
         else
         {
             _state = NORMAL;
             Game::getInstance()->displayKeyboard(false);
-            _dirty = true;
-            return _consumeInputEvents;
         }
+        _contactIndex = INVALID_CONTACT_INDEX;
+        _dirty = true;
         break;
     }
 
@@ -156,7 +165,7 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         Font::Justify textAlignment = getTextAlignment(_state);
                         bool rightToLeft = getTextRightToLeft(_state);
 
-                        unsigned int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation,
+                        int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation,
                             textAlignment, true, rightToLeft);
                         font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, textIndex - 1,
                             textAlignment, true, rightToLeft);
@@ -187,10 +196,15 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         unsigned int fontSize = getFontSize(_state);
                         Font::Justify textAlignment = getTextAlignment(_state);
                         bool rightToLeft = getTextRightToLeft(_state);
-
+                        _prevCaretLocation.set(_caretLocation);
                         _caretLocation.y -= fontSize;
-                        font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation,
+                        int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation,
                             textAlignment, true, rightToLeft);
+                        if (textIndex == -1)
+                        {
+                            _caretLocation.set(_prevCaretLocation);
+                        }
+
                         _dirty = true;
                         consume = true;
                         break;
@@ -202,10 +216,15 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                         unsigned int fontSize = getFontSize(_state);
                         Font::Justify textAlignment = getTextAlignment(_state);
                         bool rightToLeft = getTextRightToLeft(_state);
-
+                        _prevCaretLocation.set(_caretLocation);
                         _caretLocation.y += fontSize;
-                        font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation,
+                        int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation,
                             textAlignment, true, rightToLeft);
+                        if (textIndex == -1)
+                        {
+                            _caretLocation.set(_prevCaretLocation);
+                        }
+
                         _dirty = true;
                         consume = true;
                         break;
@@ -224,6 +243,12 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
 
                 int textIndex = font->getIndexAtLocation(_text.c_str(), _textBounds, fontSize, _caretLocation, &_caretLocation,
                     textAlignment, true, rightToLeft);
+                if (textIndex == -1)
+                {
+                    textIndex = 0;
+                    font->getLocationAtIndex(_text.c_str(), _textBounds, fontSize, &_caretLocation, 0,
+                        textAlignment, true, rightToLeft);
+                }
 
                 switch (key)
                 {
@@ -237,13 +262,17 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                                 textAlignment, true, rightToLeft);
 
                             _dirty = true;
-                            consume = true;
                         }
+                        consume = true;
                         break;
                     }
                     case Keyboard::KEY_RETURN:
                         // TODO: Handle line-break insertion correctly.
                         break;
+                    case Keyboard::KEY_ESCAPE:
+                        break;
+                    case Keyboard::KEY_TAB:
+                        break;
                     default:
                     {
                         // Insert character into string.
@@ -293,6 +322,7 @@ bool TextBox::keyEvent(Keyboard::KeyEvent evt, int key)
                 }
 
                 notifyListeners(Listener::TEXT_CHANGED);
+                break;
             }
         }
     }
@@ -312,7 +342,7 @@ void TextBox::update(const Control* container, const Vector2& offset)
 
 void TextBox::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
 {
-    if (_state == FOCUS)
+    if (_state == ACTIVE || _state == FOCUS)
     {
         // Draw the cursor at its current location.
         GP_ASSERT(_caretImage);
@@ -352,4 +382,9 @@ void TextBox::setCaretLocation(int x, int y)
     }
 }
 
-}
+const char* TextBox::getType() const
+{
+    return "textBox";
+}
+
+}

+ 16 - 1
gameplay/src/TextBox.h

@@ -39,6 +39,16 @@ class TextBox : public Label
 
 public:
 
+    /**
+     * Create a new text box control.
+     *
+     * @param id The control's ID.
+     * @param style The control's style.
+     *
+     * @return The new text box.
+     */
+    static TextBox* create(const char* id, Theme::Style* style);
+
     /**
      * Add a listener to be notified of specific events affecting
      * this control.  Event types can be OR'ed together.
@@ -58,6 +68,11 @@ public:
      */
     int getLastKeypress();
 
+    /**
+     * @see Control::getType
+     */
+    const char* getType() const;
+
 protected:
 
     /**
@@ -165,4 +180,4 @@ private:
 
 }
 
-#endif
+#endif

+ 3 - 1
gameplay/src/Texture.h

@@ -99,7 +99,9 @@ public:
         void setFilterMode(Filter minificationFilter, Filter magnificationFilter);
 
         /**
-         * Returns the texture for this sampler.
+         * Gets the texture for this sampler.
+         *
+         * @return The texture for this sampler.
          */
         Texture* getTexture() const;
 

+ 29 - 17
gameplay/src/Theme.h

@@ -135,7 +135,6 @@ namespace gameplay
 class Theme: public Ref
 {
     friend class Control;
-    friend class Container;
     friend class Form;
     friend class Skin;
 
@@ -294,6 +293,35 @@ public:
         Vector4 _color;
     };
 
+    /**
+     * Creates a theme using the data from the Properties object defined at the specified URL, 
+     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
+     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
+     * 
+     * @param url The URL pointing to the Properties object defining the theme. 
+     */
+    static Theme* create(const char* url);
+
+    /**
+     * Get a style by its ID.
+     *
+     * @param id The style ID.
+     *
+     * @return The style with the specified ID, or NULL if it does not exist.
+     */
+    Theme::Style* getStyle(const char* id) const;
+
+    /**
+     * Get the empty style.  Used when a control does not specify a style.
+     * This is especially useful for containers that are being used only for
+     * layout and positioning, and have no background or border themselves.
+     * The empty style has no border, background, margin, padding, images, etc..
+     * Any needed properties can be set on the control directly.
+     *
+     * @return The empty style.
+     */
+    Theme::Style* getEmptyStyle();
+
 private:
 
     /**
@@ -406,22 +434,6 @@ private:
      */
     ~Theme();
 
-    /**
-     * Creates an instance of a Theme using the data from the Properties object defined at the specified URL, 
-     * where the URL is of the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
-     * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional). 
-     * 
-     * @param url The URL pointing to the Properties object defining the theme.
-     *
-     * @return A new Theme.
-     */
-    static Theme* create(const char* url);
-
-    Theme::Style* getStyle(const char* id) const;
-
-    // Used when a control does not specify a style.
-    Theme::Style* getEmptyStyle();
-
     void setProjectionMatrix(const Matrix& matrix);
 
     SpriteBatch* getSpriteBatch() const;

+ 5 - 0
gameplay/src/ThemeStyle.cpp

@@ -39,6 +39,11 @@ Theme::Style::~Style()
         SAFE_RELEASE(_overlays[i]);
     }
 }
+
+Theme* Theme::Style::getTheme() const
+{
+    return _theme;
+}
     
 const char* Theme::Style::getId() const
 {

+ 9 - 0
gameplay/src/ThemeStyle.h

@@ -25,6 +25,15 @@ class Theme::Style
     friend class Container;
     friend class Form;
 
+public:
+
+    /**
+     * Get the theme this style belongs to.
+     *
+     * @return The theme this style belongs to.
+     */
+    Theme* getTheme() const;
+
 private:
 
     /**

+ 7 - 9
gameplay/src/VerticalLayout.h

@@ -13,11 +13,16 @@ namespace gameplay
  */
 class VerticalLayout : public Layout
 {
-    friend class Form;
-    friend class Container;
 
 public:
 
+    /**
+     * Create a VerticalLayout.
+     *
+     * @return a VerticalLayout object.
+     */
+    static VerticalLayout* create();
+
     /**
      * Set whether this layout will start laying out controls from the bottom of the container.
      * This setting defaults to 'false', meaning controls will start at the top.
@@ -52,13 +57,6 @@ protected:
      */
     virtual ~VerticalLayout();
 
-    /**
-     * Create a VerticalLayout.
-     *
-     * @return a VerticalLayout object.
-     */
-    static VerticalLayout* create();
-
     /**
      * Update the controls contained by the specified container.
      *

+ 1 - 0
gameplay/src/gameplay.h

@@ -7,6 +7,7 @@
 #include "Mouse.h"
 #include "FileSystem.h"
 #include "Bundle.h"
+#include "Gamepad.h"
 
 // Math
 #include "Rectangle.h"