瀏覽代碼

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

Conflicts:
	gameplay-api/html/doxygen.css
	gameplay-api/html/jquery.js
	gameplay-api/html/navtree.css
	gameplay-api/html/search/all_77.html
	gameplay-api/html/search/all_78.html
	gameplay-api/html/search/all_79.html
	gameplay-api/html/search/all_7a.html
	gameplay-api/html/search/classes_65.html
	gameplay-api/html/search/classes_67.html
	gameplay-api/html/search/classes_6a.html
	gameplay-api/html/search/classes_71.html
	gameplay-api/html/search/enums_63.html
	gameplay-api/html/search/enums_69.html
	gameplay-api/html/search/enums_6a.html
	gameplay-api/html/search/enums_70.html
	gameplay-api/html/search/enums_75.html
	gameplay-api/html/search/enums_77.html
	gameplay-api/html/search/enumvalues_68.html
	gameplay-api/html/search/enumvalues_6d.html
	gameplay-api/html/search/enumvalues_77.html
	gameplay-api/html/search/functions_71.html
	gameplay-api/html/search/functions_7a.html
	gameplay-api/html/search/search.css
	gameplay-api/html/search/variables_63.html
	gameplay-api/html/search/variables_68.html
	gameplay-api/html/search/variables_69.html
	gameplay-api/html/search/variables_75.html
	gameplay-api/html/search/variables_77.html
	gameplay-api/html/search/variables_78.html
	gameplay-api/html/search/variables_79.html
	gameplay-api/html/search/variables_7a.html
	gameplay.sln
Adam Blake 13 年之前
父節點
當前提交
7b9043d612
共有 62 個文件被更改,包括 999 次插入470 次删除
  1. 2 1
      .gitignore
  2. 5 0
      gameplay-api/gameplay.html
  3. 1 32
      gameplay.doxyfile
  4. 7 7
      gameplay.sln
  5. 0 0
      gameplay/res/icon.psd
  6. 0 0
      gameplay/res/icon_128.ico
  7. 0 0
      gameplay/res/icon_16.ico
  8. 0 0
      gameplay/res/icon_32.ico
  9. 0 0
      gameplay/res/icon_64.ico
  10. 二進制
      gameplay/res/icon_black.psd
  11. 二進制
      gameplay/res/icon_black128.ico
  12. 二進制
      gameplay/res/icon_black16.ico
  13. 二進制
      gameplay/res/icon_black32.ico
  14. 二進制
      gameplay/res/icon_black64.ico
  15. 二進制
      gameplay/res/icon_white_transparent.psd
  16. 二進制
      gameplay/res/icon_white_transparent128.ico
  17. 二進制
      gameplay/res/icon_white_transparent16.ico
  18. 二進制
      gameplay/res/icon_white_transparent32.ico
  19. 二進制
      gameplay/res/icon_white_transparent64.ico
  20. 13 0
      gameplay/src/Animation.cpp
  21. 12 0
      gameplay/src/Animation.h
  22. 2 2
      gameplay/src/AnimationClip.h
  23. 12 2
      gameplay/src/AnimationTarget.h
  24. 7 10
      gameplay/src/Base.h
  25. 19 3
      gameplay/src/CheckBox.h
  26. 9 2
      gameplay/src/Container.h
  27. 78 7
      gameplay/src/Control.h
  28. 1 1
      gameplay/src/Game.inl
  29. 11 0
      gameplay/src/Joint.h
  30. 18 1
      gameplay/src/Label.h
  31. 1 11
      gameplay/src/Model.cpp
  32. 19 5
      gameplay/src/Node.cpp
  33. 110 0
      gameplay/src/Node.h
  34. 3 0
      gameplay/src/ParticleEmitter.h
  35. 117 181
      gameplay/src/PhysicsCharacter.cpp
  36. 12 113
      gameplay/src/PhysicsCharacter.h
  37. 9 1
      gameplay/src/PhysicsCollisionObject.cpp
  38. 12 0
      gameplay/src/PhysicsCollisionObject.h
  39. 4 4
      gameplay/src/PhysicsCollisionShape.cpp
  40. 19 0
      gameplay/src/PhysicsCollisionShape.h
  41. 11 0
      gameplay/src/PhysicsConstraint.h
  42. 55 4
      gameplay/src/PhysicsController.h
  43. 1 1
      gameplay/src/PhysicsGhostObject.cpp
  44. 3 0
      gameplay/src/PhysicsGhostObject.h
  45. 2 2
      gameplay/src/PhysicsRigidBody.cpp
  46. 1 1
      gameplay/src/PhysicsRigidBody.h
  47. 1 2
      gameplay/src/PlatformQNX.cpp
  48. 15 0
      gameplay/src/RadioButton.h
  49. 19 0
      gameplay/src/RenderState.h
  50. 37 2
      gameplay/src/Scene.cpp
  51. 57 8
      gameplay/src/Scene.h
  52. 25 15
      gameplay/src/SceneLoader.cpp
  53. 3 2
      gameplay/src/SceneLoader.h
  54. 38 2
      gameplay/src/Slider.h
  55. 47 4
      gameplay/src/SpriteBatch.cpp
  56. 19 0
      gameplay/src/TextBox.h
  57. 31 31
      gameplay/src/Texture.cpp
  58. 3 3
      gameplay/src/Texture.h
  59. 79 2
      gameplay/src/Theme.h
  60. 38 1
      gameplay/src/Transform.h
  61. 7 7
      gameplay/src/VertexAttributeBinding.cpp
  62. 4 0
      gameplay/src/VerticalLayout.h

+ 2 - 1
.gitignore

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

+ 5 - 0
gameplay-api/gameplay.html

@@ -0,0 +1,5 @@
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Refresh" CONTENT="0; URL=html/index.html">
+</HEAD>
+</HTML>

+ 1 - 32
gameplay.doxyfile

@@ -689,38 +689,7 @@ INPUT_ENCODING         = UTF-8
 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py 
 # *.f90 *.f *.for *.vhd *.vhdl
 
-FILE_PATTERNS          = *.c \
-                         *.cc \
-                         *.cxx \
-                         *.cpp \
-                         *.c++ \
-                         *.d \
-                         *.java \
-                         *.ii \
-                         *.ixx \
-                         *.ipp \
-                         *.i++ \
-                         *.inl \
-                         *.h \
-                         *.hh \
-                         *.hxx \
-                         *.hpp \
-                         *.h++ \
-                         *.idl \
-                         *.odl \
-                         *.cs \
-                         *.php \
-                         *.php3 \
-                         *.inc \
-                         *.m \
-                         *.mm \
-                         *.dox \
-                         *.py \
-                         *.f90 \
-                         *.f \
-                         *.for \
-                         *.vhd \
-                         *.vhdl
+FILE_PATTERNS          = *.h
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories 
 # should be searched for input files as well. Possible values are YES and NO. 

+ 7 - 7
gameplay.sln

@@ -20,7 +20,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample03-character", "gamep
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay-encoder", "gameplay-encoder\gameplay-encoder.vcxproj", "{9D69B743-4872-4DD1-8E30-0087C64298D7}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-particles", "gameplay-samples\sample04-particles\sample04-particles.vcxproj", "{39EC1058-4E79-58E5-E826-D780487559BE}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-particles", "gameplay-samples\sample04-particles\sample04-particles.vcxproj", "{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}"
 	ProjectSection(ProjectDependencies) = postProject
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 	EndProjectSection
@@ -67,12 +67,12 @@ Global
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.DebugMem|Win32.Build.0 = Debug|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.Release|Win32.ActiveCfg = Release|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.Release|Win32.Build.0 = Release|Win32
-		{39EC1058-4E79-58E5-E826-D780487559BE}.Debug|Win32.ActiveCfg = Debug|Win32
-		{39EC1058-4E79-58E5-E826-D780487559BE}.Debug|Win32.Build.0 = Debug|Win32
-		{39EC1058-4E79-58E5-E826-D780487559BE}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
-		{39EC1058-4E79-58E5-E826-D780487559BE}.DebugMem|Win32.Build.0 = DebugMem|Win32
-		{39EC1058-4E79-58E5-E826-D780487559BE}.Release|Win32.ActiveCfg = Release|Win32
-		{39EC1058-4E79-58E5-E826-D780487559BE}.Release|Win32.Build.0 = Release|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|Win32.ActiveCfg = Debug|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Debug|Win32.Build.0 = Debug|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|Win32.ActiveCfg = Release|Win32
+		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|Win32.Build.0 = Release|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|Win32.ActiveCfg = Debug|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Debug|Win32.Build.0 = Debug|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.DebugMem|Win32.ActiveCfg = DebugMem|Win32

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


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


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


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


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


二進制
gameplay/res/icon_black.psd


二進制
gameplay/res/icon_black128.ico


二進制
gameplay/res/icon_black16.ico


二進制
gameplay/res/icon_black32.ico


二進制
gameplay/res/icon_black64.ico


二進制
gameplay/res/icon_white_transparent.psd


二進制
gameplay/res/icon_white_transparent128.ico


二進制
gameplay/res/icon_white_transparent16.ico


二進制
gameplay/res/icon_white_transparent32.ico


二進制
gameplay/res/icon_white_transparent64.ico


+ 13 - 0
gameplay/src/Animation.cpp

@@ -146,6 +146,19 @@ AnimationClip* Animation::getClip(const char* id)
     }
 }
 
+AnimationClip* Animation::getClip(unsigned int index) const
+{
+    if (_clips)
+        return _clips->at(index);
+
+    return NULL;
+}
+
+unsigned int Animation::getClipCount() const
+{
+    return _clips ? _clips->size() : 0;
+}
+
 void Animation::play(const char* clipId)
 {
     // If id is NULL, play the default clip.

+ 12 - 0
gameplay/src/Animation.h

@@ -66,6 +66,18 @@ public:
      * @return The AnimationClip with the specified ID; NULL if an AnimationClip with the given ID is not found.
      */
     AnimationClip* getClip(const char* clipId = NULL);
+
+    /**
+     * Returns the AnimationClip at the given index.
+     *
+     * @param index Index of the clip to return.
+     */
+    AnimationClip* getClip(unsigned int index) const;
+
+    /**
+     * Returns the number of animation clips in this animation.
+     */
+    unsigned int getClipCount() const;
     
     /**
      * Plays the AnimationClip with the specified name. 

+ 2 - 2
gameplay/src/AnimationClip.h

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

+ 12 - 2
gameplay/src/AnimationTarget.h

@@ -194,8 +194,18 @@ protected:
      */
     void cloneInto(AnimationTarget* target, NodeCloneContext &context) const;
 
-    TargetType _targetType;                     // The type of target this is.
-    unsigned char _animationPropertyBitFlag;    // Bit flag used to indicate which properties on the AnimationTarget are currently animating.
+    /**
+     * The target's type. 
+     *
+     * @see TargetType::SCALAR
+     * @see TargetType::TRANSFORM
+     */
+    TargetType _targetType;
+
+    /**
+     * Bit flag used to indicate which properties on the AnimationTarget are currently animating.
+     */ 
+    unsigned char _animationPropertyBitFlag;
 
 private:
 

+ 7 - 10
gameplay/src/Base.h

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

+ 19 - 3
gameplay/src/CheckBox.h

@@ -44,6 +44,11 @@ public:
      */
     bool isChecked();
 
+    /**
+     * Sets whether the checkbox is checked.
+     *
+     * @param checked TRUE if the checkbox is checked; FALSE if the checkbox is not checked.
+     */
     void setChecked(bool checked);
 
     /**
@@ -124,10 +129,21 @@ protected:
      * @param clip The container position this control is relative to.
      */
     void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
+
+    /**
+     * Whether this checkbox is currently checked.
+     */
+    bool _checked;
 
-    bool _checked;      // Whether this checkbox is currently checked.
-    Vector2 _imageSize;  // The size to draw the checkbox icon, if different from its size in the texture.
-    Theme::ThemeImage* _image;
+    /**
+     * 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;
 
 private:
 

+ 9 - 2
gameplay/src/Container.h

@@ -231,8 +231,15 @@ protected:
      */
     void addControls(Theme* theme, Properties* properties);
 
-    Layout* _layout;                    // This container's layout.
-    std::vector<Control*> _controls;    // List of controls within this container.
+    /**
+     * The container's layout.
+     */
+    Layout* _layout;
+
+    /**
+     * List of controls within the container.
+     */
+    std::vector<Control*> _controls;
 
 private:
 

+ 78 - 7
gameplay/src/Control.h

@@ -93,6 +93,10 @@ public:
     class Listener
     {
     public:
+
+        /**
+         * Defines the Listener's event types.
+         */
         enum EventType
         {
             /**
@@ -266,7 +270,7 @@ public:
     /**
      * Set this control to fit vertically within its parent container.
      *
-     * @param autoWidth Whether to size this control to fit vertically within its parent container.
+     * @param autoHeight Whether to size this control to fit vertically within its parent container.
      */
     void setAutoHeight(bool autoHeight);
 
@@ -777,6 +781,13 @@ protected:
      */
     static State getState(const char* state);
 
+    /**
+     * Get a Theme::ThemeImage from its ID, for a given state.
+     *
+     * @param id The ID of the image to retrieve
+     * @param state The state to get this image from.
+     * @return The requested Theme::ThemeImage, or NULL if none was found.
+     */
     Theme::ThemeImage* getImage(const char* id, State state);
 
     /**
@@ -786,23 +797,83 @@ protected:
      */
     void notifyListeners(Listener::EventType eventType);
 
+    /**
+     * Gets the Alignment by string.
+     *
+     * @param alignment The string representation of the Alignment type.
+     * @return The Alignment enum value corresponding to the given string.
+     */
     static Alignment getAlignment(const char* alignment);
 
+    /** 
+     * The Control's ID.
+     */ 
     std::string _id;
-    State _state;           // Determines overlay used during draw().
-    Rectangle _bounds;      // Position, relative to parent container's clipping window, and desired size.
-    Rectangle _clipBounds;  // The position and size of this control, relative to parent container's bounds, including border and padding, after clipping.
-    Rectangle _textBounds;  // The position and size of this control's text area, before clipping.  Used for text alignment.
-    Rectangle _clip;        // Clipping window of this control's content, after clipping.
+
+    /**
+     * Determines overlay used during draw().
+     */
+    State _state;
+
+    /**
+     * Position, relative to parent container's clipping window, and desired size.
+     */
+    Rectangle _bounds;
+    
+    /**
+     * The position and size of this control, relative to parent container's bounds, including border and padding, after clipping.
+     */
+    Rectangle _clipBounds;
+    
+    /**
+     * The position and size of this control's text area, before clipping.  Used for text alignment.
+     */
+    Rectangle _textBounds;
+    
+    /**
+     * Clipping window of this control's content, after clipping.
+     */
+    Rectangle _clip;
+    
+    /**
+     * Flag for whether the Control is dirty.
+     */
     bool _dirty;
+    
+    /**
+     * Flag for whether the Control consume's touch events.
+     */
     bool _consumeTouchEvents;
+    
+    /**
+     * The Control's Alignmnet
+     */
     Alignment _alignment;
+    
+    /**
+     * Whether the Control's width is auto-sized.
+     */
     bool _autoWidth;
+    
+    /**
+     * Whether the Control's height is auto-sized.
+     */
     bool _autoHeight;
+    
+    /**
+     * The Control's Theme::Style.
+     */
     Theme::Style* _style;
+    
+    /**
+     * Listeners map of EventType's to a list of Listeners.
+     */
     std::map<Listener::EventType, std::list<Listener*>*>* _listeners;
 
-    float _opacity;         // Current opacity.
+    /**
+     * The current opacity of the control.
+     */
+    float _opacity;
 
 private:
 

+ 1 - 1
gameplay/src/Game.inl

@@ -56,7 +56,7 @@ inline void Game::setMultiTouch(bool enabled)
     Platform::setMultiTouch(enabled);
 }
 
-inline bool isMultiTouch()
+inline bool Game::isMultiTouch() const
 {
     return Platform::isMultiTouch();
 }

+ 11 - 0
gameplay/src/Joint.h

@@ -97,8 +97,19 @@ private:
 
 protected:
 
+    /** 
+     * The Matrix representation of the Joint's bind pose.
+     */
     Matrix _bindPose;
+    
+    /** 
+     * Flag used to mark if the Joint's matrix is dirty.
+     */
     bool _jointMatrixDirty;
+    
+    /** 
+     * The number of MeshSkin's influencing the Joint.
+     */
     unsigned int _skinCount;
 };
 

+ 18 - 1
gameplay/src/Label.h

@@ -86,6 +86,12 @@ protected:
      */
     virtual void initialize(Theme::Style* style, Properties* properties);
 
+    /**
+     * Called when a label's properties change. Updates this label's internal rendering
+     * properties, such as its text viewport.
+     *
+     * @param clip The clipping rectangle of this label's parent container.
+     */
     void update(const Rectangle& clip);
 
     /**
@@ -95,8 +101,19 @@ protected:
      */
     void drawText(const Rectangle& clip);
 
-    std::string _text;      // The text displayed by this label.
+    /**
+     * The text displayed by this label.
+     */
+    std::string _text;
+
+    /**
+     * The font being used to display the label.
+     */
     Font* _font;
+    
+    /**
+     * The text color being used to display the label.
+     */
     Vector4 _textColor;
 
 private:

+ 1 - 11
gameplay/src/Model.cpp

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

+ 19 - 5
gameplay/src/Node.cpp

@@ -15,6 +15,7 @@
 // Node property flags
 #define NODE_FLAG_VISIBLE 1
 #define NODE_FLAG_TRANSPARENT 2
+#define NODE_FLAG_DYNAMIC 4
 
 namespace gameplay
 {
@@ -235,6 +236,19 @@ void Node::setTransparent(bool transparent)
         _nodeFlags &= ~NODE_FLAG_TRANSPARENT;
 }
 
+bool Node::isDynamic() const
+{
+    return ((_nodeFlags & NODE_FLAG_DYNAMIC) == NODE_FLAG_DYNAMIC);
+}
+
+void Node::setDynamic(bool dynamic)
+{
+    if (dynamic)
+        _nodeFlags |= NODE_FLAG_DYNAMIC;
+    else
+        _nodeFlags &= ~NODE_FLAG_DYNAMIC;
+}
+
 void* Node::getUserPointer() const
 {
     return (_userData ? _userData->pointer : NULL);
@@ -1004,10 +1018,10 @@ PhysicsCollisionObject* Node::setCollisionObject(Properties* properties)
     // Check if the properties is valid.
     if (!properties || 
         !(strcmp(properties->getNamespace(), "character") == 0 || 
-        strcmp(properties->getNamespace(), "ghost") == 0 || 
-        strcmp(properties->getNamespace(), "rigidbody") == 0))
+        strcmp(properties->getNamespace(), "ghostObject") == 0 || 
+        strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
-        WARN("Failed to load collision object from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
+        WARN("Failed to load collision object from properties object: must be non-null object and have namespace equal to \'character\', \'ghostObject\', or \'rigidBody\'.");
         return NULL;
     }
 
@@ -1015,11 +1029,11 @@ PhysicsCollisionObject* Node::setCollisionObject(Properties* properties)
     {
         _collisionObject = PhysicsCharacter::create(this, properties);
     }
-    else if (strcmp(properties->getNamespace(), "ghost") == 0)
+    else if (strcmp(properties->getNamespace(), "ghostObject") == 0)
     {
         _collisionObject = PhysicsGhostObject::create(this, properties);
     }
-    else if (strcmp(properties->getNamespace(), "rigidbody") == 0)
+    else if (strcmp(properties->getNamespace(), "rigidBody") == 0)
     {
         _collisionObject = PhysicsRigidBody::create(this, properties);
     }

+ 110 - 0
gameplay/src/Node.h

@@ -148,6 +148,26 @@ public:
      */
     void setTransparent(bool transparent);
 
+    /**
+     * Returns whether this node is dynamic.
+     *
+     * The dynamic propery can be used to flag nodes as being non-static.
+     * This can be useful for modifying behavior or rendering/material
+     * logic at runtime for static vs dynamic (moving) objects. An
+     * example would be determing whether to use static or  dyanmic
+     * lighting materials for node models during loading.
+     *
+     * @return Whether this node is dynamic (false by default).
+     */
+    bool isDynamic() const;
+
+    /**
+     * Sets whether this node is dynamic.
+     *
+     * @param dynamic Whether the node is dynamic.
+     */
+    void setDynamic(bool dynamic);
+
     /**
      * Returns the user pointer for this node.
      *
@@ -618,30 +638,120 @@ protected:
      */
     struct UserData
     {
+        /**
+         * Constructor.
+         */
         UserData() : pointer(NULL), cleanupCallback(NULL) {}
+
+        /**
+         * A pointer to custom user data.
+         */
         void* pointer;
+
+        /** 
+         * Cleanup callback.
+         */
         void (*cleanupCallback)(void*);
     };
 
+    /**
+     * The Scene this node belongs to.
+     */
     Scene* _scene;
+
+    /**
+     * The Node's ID.
+     */ 
     std::string _id;
+
+    /**
+     * Pointer to the Node's first child.
+     */
     Node* _firstChild;
+    
+    /**
+     * Pointer to the Node's next child.
+     */
     Node* _nextSibling;
+    
+    /**
+     * Pointer to the Node's previous sibling.
+     */
     Node* _prevSibling;
+
+    /**
+     * Pointer to the Node's parent.
+     */
     Node* _parent;
+
+    /**
+     * The number of children belonging to the Node.
+     */
     unsigned int _childCount;
+
+    /**
+     * Node property flags. 
+     */ 
     unsigned int _nodeFlags;
+
+    /**
+     * Pointer to the Camera attached to the Node.
+     */
     Camera* _camera;
+
+    /**
+     * Pointer to the Light attached to the Node.
+     */ 
     Light* _light;
+
+    /**
+     * Pointer to the Model attached to the Node.
+     */
     Model* _model;
+    
+    /**
+     * Pointer to the Form attached to the Node.
+     */
     Form* _form;
+    
+    /**
+     * Pointer to the AudioSource attached to the Node.
+     */
     AudioSource* _audioSource;
+    
+    /**
+     * Pointer to the ParticleEmitter attached to the Node.
+     */
     ParticleEmitter* _particleEmitter;
+    
+    /**
+     * Pointer to the PhysicsCollisionObject attached to the Node.
+     */
     PhysicsCollisionObject* _collisionObject;
+    
+    /**
+     * World Matrix representation of the Node.
+     */
     mutable Matrix _world;
+
+    /**
+     * Dirty bits flag for the Node.
+     */
     mutable int _dirtyBits;
+    
+    /**
+     * A flag indicating if the Node's hierarchy has changed.
+     */ 
     bool _notifyHierarchyChanged;
+
+    /**
+     * The Bounding Sphere containing the Node.
+     */
     mutable BoundingSphere _bounds;
+
+    /**
+     * Pointer to custom UserData and cleanup call back that can be stored in a Node.
+     */
     UserData* _userData;
 };
 

+ 3 - 0
gameplay/src/ParticleEmitter.h

@@ -142,6 +142,9 @@ class ParticleEmitter : public Ref
 
 public:
 
+    /**
+     * Defines the types of texture blending 
+     */
     enum TextureBlending
     {
         BLEND_OPAQUE,

+ 117 - 181
gameplay/src/PhysicsCharacter.cpp

@@ -17,11 +17,17 @@ class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexR
 {
 public:
 
+    /**
+     * @see btCollisionWorld::ClosestConvexResultCallback::ClosestConvexResultCallback
+     */
     ClosestNotMeConvexResultCallback(PhysicsCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
         : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), _me(me), _up(up), _minSlopeDot(minSlopeDot)
     {
     }
 
+    /**
+     * @see btCollisionWorld::ClosestConvexResultCallback::addSingleResult
+     */
     btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
     {
         PhysicsCollisionObject* object = reinterpret_cast<PhysicsCollisionObject*>(convexResult.m_hitCollisionObject->getUserPointer());
@@ -59,9 +65,9 @@ protected:
 
 PhysicsCharacter::PhysicsCharacter(Node* node, const PhysicsCollisionShape::Definition& shape, float mass)
     : PhysicsGhostObject(node, shape), _moveVelocity(0,0,0), _forwardVelocity(0.0f), _rightVelocity(0.0f),
-    _fallVelocity(0, 0, 0), _currentVelocity(0,0,0), _normalizedVelocity(0,0,0),
-    _colliding(false), _collisionNormal(0,0,0), _currentPosition(0,0,0),
-    _stepHeight(0.1f), _slopeAngle(0.0f), _cosSlopeAngle(0.0f), _physicsEnabled(true), _mass(mass)
+    _verticalVelocity(0, 0, 0), _currentVelocity(0,0,0), _normalizedVelocity(0,0,0),
+    _colliding(false), _collisionNormal(0,0,0), _currentPosition(0,0,0), _stepHeight(0.1f),
+    _slopeAngle(0.0f), _cosSlopeAngle(0.0f), _physicsEnabled(true), _mass(mass)
 {
     setMaxSlopeAngle(45.0f);
 
@@ -99,6 +105,8 @@ PhysicsCharacter* PhysicsCharacter::create(Node* node, Properties* properties)
     // Load the character's parameters.
     properties->rewind();
     float mass = 1.0f;
+    float maxStepHeight = 0.1f;
+    float maxSlopeAngle = 0.0f;
     const char* name = NULL;
     while ((name = properties->getNextProperty()) != NULL)
     {
@@ -106,10 +114,20 @@ PhysicsCharacter* PhysicsCharacter::create(Node* node, Properties* properties)
         {
             mass = properties->getFloat();
         }
+        else if (strcmp(name, "maxStepHeight") == 0)
+        {
+            maxStepHeight = properties->getFloat();
+        }
+        else if (strcmp(name, "maxSlopeAngle") == 0)
+        {
+            maxSlopeAngle = properties->getFloat();
+        }
     }
 
     // Create the physics character.
     PhysicsCharacter* character = new PhysicsCharacter(node, *shape, mass);
+    character->setMaxStepHeight(maxStepHeight);
+    character->setMaxSlopeAngle(maxSlopeAngle);
     SAFE_DELETE(shape);
 
     return character;
@@ -156,120 +174,6 @@ void PhysicsCharacter::setMaxSlopeAngle(float angle)
     _cosSlopeAngle = std::cos(MATH_DEG_TO_RAD(angle));
 }
 
-void PhysicsCharacter::addAnimation(const char* name, AnimationClip* clip, float moveSpeed)
-{
-    CharacterAnimation a;
-    a.name = name;
-    a.clip = clip;
-    a.moveSpeed = moveSpeed;
-    a.layer = 0;
-    a.playing = false;
-    a.animationFlags = ANIMATION_STOP;
-    a.prev = NULL;
-    _animations[name] = a;
-}
-
-AnimationClip* PhysicsCharacter::getAnimation(const char* name)
-{
-    if (name)
-    {
-        // Lookup the specified animation
-        std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
-        if (aitr != _animations.end())
-        {
-            return aitr->second.clip;
-        }
-    }
-    return NULL;
-}
-
-void PhysicsCharacter::play(const char* name, AnimationFlags flags, float speed, unsigned int blendDuration, unsigned int layer)
-{
-    CharacterAnimation* animation = NULL;
-    if (name)
-    {
-        // Lookup the specified animation
-        std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
-        if (aitr == _animations.end())
-            return; // invalid animation name
-
-        animation = &(aitr->second);
-
-        // Set animation flags
-        animation->clip->setRepeatCount(flags & ANIMATION_REPEAT ? AnimationClip::REPEAT_INDEFINITE : 1);
-        animation->clip->setSpeed(speed);
-        animation->animationFlags = flags;
-        animation->layer = layer;
-        animation->blendDuration = blendDuration;
-        animation->prev = NULL;
-
-        // If the animation is already marked playing, do nothing more
-        if (animation->playing)
-            return;
-    }
-
-    play(animation, layer);
-}
-
-void PhysicsCharacter::play(CharacterAnimation* animation, unsigned int layer)
-{
-    // Is there already an animation playing on this layer?
-    std::map<unsigned int, CharacterAnimation*>::iterator litr = _layers.find(layer);
-    CharacterAnimation* prevAnimation = (litr == _layers.end() ? NULL : litr->second);
-    if (prevAnimation && prevAnimation->playing)
-    {
-        // An animation is already playing on this layer
-        if (animation)
-        {
-            if (animation->animationFlags == ANIMATION_RESUME)
-                animation->prev = prevAnimation;
-
-            if (animation->blendDuration > 0L)
-            {
-                // Crossfade from current animation into the new one
-                prevAnimation->clip->crossFade(animation->clip, animation->blendDuration);
-            }
-            else
-            {
-                // Stop the previous animation (no blending)
-                prevAnimation->clip->stop();
-
-                // Play the new animation
-                animation->clip->play();
-            }
-        }
-        else
-        {
-            // No new animaton specified - stop current animation on this layer
-            prevAnimation->clip->stop();
-        }
-
-        prevAnimation->playing = false;
-    }
-    else if (animation)
-    {
-        // No animations currently playing - just play the new one
-        animation->clip->play();
-    }
-
-    // Update animaton and layers
-    if (animation)
-    {
-        animation->playing = true;
-
-        // Update layer to point to the new animation
-        if (litr != _layers.end())
-            litr->second = animation;
-        else
-            _layers[layer] = animation;
-    }
-    else if (litr != _layers.end())
-    {
-        // Remove layer sine we stopped the animation previously on it
-        _layers.erase(litr);
-    }
-}
-
 void PhysicsCharacter::setVelocity(const Vector3& velocity)
 {
     _moveVelocity.setValue(velocity.x, velocity.y, velocity.z);
@@ -305,9 +209,31 @@ void PhysicsCharacter::setRightVelocity(float velocity)
     _rightVelocity = velocity;
 }
 
+Vector3 PhysicsCharacter::getCurrentVelocity() const
+{
+    Vector3 v(_currentVelocity.x(), _currentVelocity.y(), _currentVelocity.z());
+    v.x += _verticalVelocity.x();
+    v.y += _verticalVelocity.y();
+    v.z += _verticalVelocity.z();
+    return v;
+}
+
 void PhysicsCharacter::jump(float height)
 {
-    // TODO
+    // TODO: Add support for different jump modes (i.e. double jump, changing direction in air, holding down jump button for extra height, etc)
+    if (!_verticalVelocity.isZero())
+        return;
+
+    // v = sqrt(v0^2 + 2 a s)
+    //  v0 == initial velocity (zero for jumping)
+    //  a == acceleration (inverse gravity)
+    //  s == linear displacement (height)
+    Vector3 jumpVelocity = -Game::getInstance()->getPhysicsController()->getGravity() * height * 2.0f;
+    jumpVelocity.set(
+        jumpVelocity.x == 0 ? 0 : std::sqrt(jumpVelocity.x),
+        jumpVelocity.y == 0 ? 0 : std::sqrt(jumpVelocity.y),
+        jumpVelocity.z == 0 ? 0 : std::sqrt(jumpVelocity.z));
+    _verticalVelocity += BV(jumpVelocity);
 }
 
 void PhysicsCharacter::updateCurrentVelocity()
@@ -403,58 +329,26 @@ void PhysicsCharacter::updateAction(btCollisionWorld* collisionWorld, btScalar d
 
 void PhysicsCharacter::stepUp(btCollisionWorld* collisionWorld, btScalar time)
 {
-    // Note: btKinematicCharacterController implements this by always just setting
-    // target position to currentPosition.y + stepHeight, and then checking for collisions.
-    // Don't let the character move up if it hits the ceiling (or something above).
-    // Do this WITHOUT using time in the calculation - this way you are always guarnateed
-    // to step over a step that is stepHeight high.
-    // 
-    // Note that stepDown() will be called right after this, so the character will move back
-    // down to collide with the ground so that he smoothly steps up stairs.
-    _currentPosition += btVector3(0, _stepHeight, 0);
-}
+    btVector3 targetPosition(_currentPosition);
 
-void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, float time)
-{
-    // Process currently playing movements+animations and determine final move location
-    float animationMoveSpeed = 0.0f;
-    unsigned int animationCount = 0;
-    for (std::map<unsigned int, CharacterAnimation*>::iterator itr = _layers.begin(); itr != _layers.end(); ++itr)
+    if (_verticalVelocity.isZero())
     {
-        CharacterAnimation* animation = itr->second;
-
-        // If the animation is not playing, ignore it
-        if (!animation->playing)
-            continue;
-
-        AnimationClip* clip = animation->clip;
-
-        // Did the clip finish playing (but we still have it marked playing)?
-        if (!clip->isPlaying())
-        {
-            // If the animaton was flaged the ANIMATION_RESUME bit, start the previously playing animation
-            if ((animation->animationFlags == ANIMATION_RESUME) && animation->prev)
-            {
-                play(animation->prev, animation->prev->layer);
-            }
-
-            animation->playing = false;
+        // Simply increase our poisiton by step height to enable us
+        // to smoothly move over steps.
+        targetPosition += btVector3(0, _stepHeight, 0);
+    }
 
-            continue;
-        }
+    // TODO: Convex sweep test to ensure we didn't hit anything during the step up.
 
-        animationMoveSpeed += animation->moveSpeed;
-        ++animationCount;
-    }
+    _currentPosition = targetPosition;
+}
 
+void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, float time)
+{
     updateCurrentVelocity();
 
     // Calculate final velocity
     btVector3 velocity(_currentVelocity);
-    if (animationCount > 0)
-    {
-        velocity *= animationMoveSpeed;
-    }
     velocity *= time; // since velocity is in meters per second
 
     if (velocity.isZero())
@@ -542,11 +436,12 @@ void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, fl
 
 void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
 {
-    // Contribute basic gravity to fall velocity.
+    // Contribute gravity to vertical velocity.
     btVector3 gravity = Game::getInstance()->getPhysicsController()->_world->getGravity();
-    _fallVelocity += (gravity * time);
+    _verticalVelocity += (gravity * time);
 
-    btVector3 targetPosition = _currentPosition + (_fallVelocity * time);
+    // Compute new position from vertical velocity.
+    btVector3 targetPosition = _currentPosition + (_verticalVelocity * time);
     targetPosition -= btVector3(0, _stepHeight, 0);
 
     // Perform a convex sweep test between current and target position
@@ -554,28 +449,69 @@ void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
     btTransform end;
     start.setIdentity();
     end.setIdentity();
-    start.setOrigin(_currentPosition);
-    end.setOrigin(targetPosition);
 
-    ClosestNotMeConvexResultCallback callback(this, btVector3(0, 1, 0), _cosSlopeAngle);
-    callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
-    callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
+    btScalar fraction = 1.0;
+    int maxIter = 10;
+    while (fraction > btScalar(0.01) && maxIter-- > 0)
+    {
+        start.setOrigin(_currentPosition);
+        end.setOrigin(targetPosition);
 
-    _ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+        btVector3 sweepDirNegative(_currentPosition - targetPosition);
 
-    if (callback.hasHit())
-    {
-        // Collision detected, fix it
-        _currentPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
+        ClosestNotMeConvexResultCallback callback(this, sweepDirNegative, 0.0);
+        callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
+        callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
 
-        // Zero out fall velocity when we hit an object
-        _fallVelocity.setZero();
-    }
-    else
-    {
-        // We can move here
-        _currentPosition = targetPosition;
+        _ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+
+        fraction -= callback.m_closestHitFraction;
+
+        if (callback.hasHit())
+        {
+            // Collision detected, fix it.
+            Vector3 normal(callback.m_hitNormalWorld.x(), callback.m_hitNormalWorld.y(), callback.m_hitNormalWorld.z());
+            normal.normalize();
+
+            float dot = normal.dot(Vector3::unitY());
+            if (dot > 1.0f - MATH_EPSILON)
+            {
+                targetPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
+
+                // Zero out fall velocity when we hit an object going straight down.
+                _verticalVelocity.setZero();
+                break;
+            }
+            else
+            {
+                PhysicsCollisionObject* o = Game::getInstance()->getPhysicsController()->getCollisionObject(callback.m_hitCollisionObject);
+                if (o->getType() == PhysicsCollisionObject::RIGID_BODY && o->isDynamic())
+                {
+                    PhysicsRigidBody* rb = static_cast<PhysicsRigidBody*>(o);
+                    normal.normalize();
+                    rb->applyImpulse(_mass * -normal * sqrt(BV(normal).dot(_verticalVelocity)));
+                }
+
+                updateTargetPositionFromCollision(targetPosition, BV(normal));
+            }
+        }
+        else
+        {
+            // Nothing is in the way.
+            break;
+        }
     }
+
+    // Calculate what the vertical velocity actually is.
+    // In cases where the character might not actually be able to move down,
+    // but isn't intersecting with an object straight down either, we don't
+    // want to keep increasing the vertical velocity until the character 
+    // randomly drops through the floor when it can finally move due to its
+    // vertical velocity having such a great magnitude.
+    if (!_verticalVelocity.isZero())
+        _verticalVelocity = ((targetPosition + btVector3(0.0, _stepHeight, 0.0)) - _currentPosition) / time;
+
+    _currentPosition = targetPosition;
 }
 
 /*

+ 12 - 113
gameplay/src/PhysicsCharacter.h

@@ -18,10 +18,6 @@ namespace gameplay
  * PhysicsCharacter class. This results in a more responsive and typical game
  * character than would be possible if trying to move a character by applying
  * physical simulation with forces.
- *
- * This class can also be used to control animations for a character. Animation
- * clips can be setup for typical character animations, such as walk, run, jump,
- * etc; and the controller will handle blending between these animations as needed.
  */
 class PhysicsCharacter : public PhysicsGhostObject, public btActionInterface
 {
@@ -29,27 +25,6 @@ class PhysicsCharacter : public PhysicsGhostObject, public btActionInterface
 
 public:
 
-    /**
-     * Flags for controlling how a character animation is played back.
-     */
-    enum AnimationFlags
-    {
-        /**
-         * Plays an animation once and then stops.
-         */
-        ANIMATION_STOP,
-
-        /**
-         * Play an animation once and then resumes the previous playing animation.
-         */
-        ANIMATION_RESUME,
-
-        /**
-         * Plays an animation and repeats it indefinitely.
-         */
-         ANIMATION_REPEAT
-    };
-
     /**
      * @see PhysicsCollisionObject#getType
      */
@@ -110,74 +85,13 @@ public:
      */
     void setMaxSlopeAngle(float angle);
 
-    /**
-     * Configures a new animation for this character.
-     *
-     * This method registers an animation for the character, with an associated movement speed.
-     * The moveSpeed specifies how fast the character moves while the animation is playing.
-     * The final velocity of the character is the product of the current move velocity and
-     * the currently playing animation(s) moveSpeed.
-     *
-     * @param name Name of the animation.
-     * @param animationClip Animation clip associated with the new character animation.
-     * @param moveSpeed Base movement speed (meters per second) associated with the animation.
-     */
-    void addAnimation(const char* name, AnimationClip* animationClip, float moveSpeed);
-
-    /**
-     * Returns the animation with the specified name.
-     *
-     * @return The specified animation clip.
-     */
-    AnimationClip* getAnimation(const char* name);
-
-    /**
-     * Plays the specified animation.
-     *
-     * There are some limiations and considerations that should be ponited out when
-     * playing animations:
-     * <li>You should avoid playing multiple animations concurrently that have the same target.
-     * For example, two animations targetting the character's joints should not be played 
-     * concurrently, but it is fine to play one animation that targets the joints and another
-     * that targets the character's Node.
-     * <li>When playing an animation that targets the transform of the character's Node
-     * (such as a motion path animation), the character's velocity vector should be set to
-     * Vector3::zero() so that the PhysicsCharacter stops applying motion directly
-     * and instead relies on the motion animation to control the character.
-     *
-     * The optional animation layer can be used to group animations on separate layers.
-     * Each animation layer can have at most one active animation. Playing multiple
-     * animations concurrently can be achieved by putting the different animations
-     * on separate layers. For example, a motion path animation that targets the
-     * character's Node can be put on one layer, while a running animation that targets
-     * a character's Joints can be put on a separate layer. This allows a character's
-     * movement to be animated at the same time as the run animation is playing.
-     *
-     * @param name Animation name, or NULL to stop all character animations on the given layer.
-     * @param flags Animation flags from the AnimationFlags enumeration.
-     * @param animationSpeed Optional animation speed (default is 1.0).
-     * @param blendDuration Optional number of milliseconds to crossfade between the
-     *      currently playing animation on the given layer and the new animation.
-     * @param layer Optional animation layer.
-     */
-    void play(const char* name, AnimationFlags flags, float animationSpeed = 1.0f, unsigned int blendDuration = 0, unsigned int layer = 0);
-
     /**
      * Sets the velocity of the character.
      *
      * Calling this function sets the velocity (speed and direction) for the character.
      * The velocity is maintained until this method is called again. The final velocity
-     * of the character is determined by product of the current velocity vector(s)
-     * and the current character animation's move speed. Therefore, specifying a
-     * normalized (unit-length) velocity vector results in the character speed being
-     * controled entirely by the current animation's velocity; whereas the speed of
-     * the character can be augmented by modifying the magnitude of the velocity vector.
-
-     * Note that a zero velocity vector and/or a zero animation move speed will
-     * result in no character movement (the character will be stationary). A zero
-     * velocity vector should be used when playing an animation that targets the
-     * character's transform directly (such as a motion path animation), since these
-     * animations will overwrite any transformations on the character's node.
+     * of the character is determined by product of the current velocity, right and
+     * forward vectors.
      *
      * @param velocity Movement velocity.
      */
@@ -219,9 +133,6 @@ public:
      * The forward velocity is defined by the character's current orientation
      * (it is the forward vector from the character's current world transform).
      *
-     * The specified velocity acts as a multiplier on the currently playing animation's
-     * velocity (or, if there is no animation playing, it directly impacts velocity).
-     *
      * Note that a negative velocity (i.e. -1.0f) will move the character backwards.
      *
      * @param velocity Optional velocity modifier.
@@ -234,9 +145,6 @@ public:
      * The right velocity is defined by the character's current orientation
      * (it is the right vector from the character's current world transform).
      *
-     * The specified velocity acts as a multiplier on the currently playing animation's
-     * velocity (or, if there is no animation playing, it directly impacts velocity).
-     *
      * Note that a negative velocity (i.e. -1.0f) will move the character left.
      *
      * @param velocity Optional velocity modifier.
@@ -244,9 +152,16 @@ public:
     void setRightVelocity(float velocity = 1.0f);
 
     /**
-     * Causes the character to jump with the specified initial upwards velocity.
+     * Returns the current velocity of the character.
      *
-     * @param velocity Initial jump velocity.
+     * @return The current velocity.
+     */
+    Vector3 getCurrentVelocity() const;
+
+    /**
+     * Causes the character to jump to the specified height.
+     *
+     * @param height The amount to jump.
      */
     void jump(float height);
 
@@ -269,18 +184,6 @@ protected:
 
 private:
 
-    struct CharacterAnimation
-    {
-        const char* name;
-        AnimationClip* clip;
-        float moveSpeed;
-        unsigned int layer;
-        bool playing;
-        AnimationFlags animationFlags;
-        unsigned int blendDuration;
-        CharacterAnimation* prev;
-    };
-
     /**
      * Creates a new PhysicsCharacter.
      *
@@ -311,8 +214,6 @@ private:
 
     void updateCurrentVelocity();
 
-    void play(CharacterAnimation* animation, unsigned int layer);
-
     void stepUp(btCollisionWorld* collisionWorld, btScalar time);
 
     void stepDown(btCollisionWorld* collisionWorld, btScalar time);
@@ -326,14 +227,12 @@ private:
     btVector3 _moveVelocity;
     float _forwardVelocity;
     float _rightVelocity;
-    btVector3 _fallVelocity;
+    btVector3 _verticalVelocity;
     btVector3 _currentVelocity;
     btVector3 _normalizedVelocity;
     bool _colliding;
     btVector3 _collisionNormal;
     btVector3 _currentPosition;
-    std::map<const char*, CharacterAnimation> _animations;
-    std::map<unsigned int, CharacterAnimation*> _layers;
     btManifoldArray _manifoldArray;
     float _stepHeight;
     float _slopeAngle;

+ 9 - 1
gameplay/src/PhysicsCollisionObject.cpp

@@ -6,9 +6,14 @@
 namespace gameplay
 {
 
-// Internal class used to implement the collidesWith(PhysicsCollisionObject*) function.
+/**
+ * Internal class used to implement the collidesWith(PhysicsCollisionObject*) function.
+ */
 struct CollidesWithCallback : public btCollisionWorld::ContactResultCallback
 {
+    /**
+     * Called with each contact. Needed to implement collidesWith(PhysicsCollisionObject*).
+     */
     btScalar addSingleResult(btManifoldPoint& cp, 
         const btCollisionObject* a, int partIdA, int indexA, 
         const btCollisionObject* b, int partIdB, int indexB)
@@ -17,6 +22,9 @@ struct CollidesWithCallback : public btCollisionWorld::ContactResultCallback
         return 0.0f;
     }
 
+    /**
+     * The result of the callback.
+     */
     bool result;
 };
 

+ 12 - 0
gameplay/src/PhysicsCollisionObject.h

@@ -181,6 +181,7 @@ public:
      * Removes a collision listener.
      *
      * @param listener The listener to remove.
+     * @param object Optional collision object used to filter the collision event.
      */
     void removeCollisionListener(CollisionListener* listener, PhysicsCollisionObject* object = NULL);
 
@@ -215,8 +216,19 @@ protected:
     PhysicsMotionState* getMotionState() const;
 
     // Common member variables
+    /**
+     * Pointer to Node contained by this collision object.
+     */ 
     Node* _node;
+
+    /** 
+     * The PhysicsCollisionObject's motion state.
+     */
     PhysicsMotionState* _motionState;
+    
+    /**
+     * The PhysicsCollisionObject's collision shape.
+     */
     PhysicsCollisionShape* _collisionShape;
 
 };

+ 4 - 4
gameplay/src/PhysicsCollisionShape.cpp

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

+ 19 - 0
gameplay/src/PhysicsCollisionShape.h

@@ -49,9 +49,28 @@ public:
 
     public:
 
+        /**
+         * Constructor.
+         */
         Definition();
+
+        /** 
+         * Constructs a new Defintion that is a copy of the specified Definition.
+         *
+         * @param definition The Definition to copy.
+         */ 
         Definition(const Definition& definition);
+
+        /**
+         * Assigns the specified Definition as the Definition.
+         *
+         * @param definition The Definition to assign to the Definition.
+         */
         Definition& operator=(const Definition& definition);
+        
+        /**
+         * Destructor.
+         */
         ~Definition();
 
     private:

+ 11 - 0
gameplay/src/PhysicsConstraint.h

@@ -102,8 +102,19 @@ protected:
      */
     static Vector3 offsetByCenterOfMass(const Node* node, const Vector3& v);
 
+    /**
+     * Pointer to the one rigid body bound by this constraint.
+     */
     PhysicsRigidBody* _a;
+    
+    /**
+     * Pointer to the other rigid body bound by this constraint.
+     */
     PhysicsRigidBody* _b;
+    
+    /**
+     * Pointer to the Bullet constraint.
+     */
     btTypedConstraint* _constraint;
 };
 

+ 55 - 4
gameplay/src/PhysicsController.h

@@ -95,6 +95,7 @@ public:
      * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
      *      body specified the constraint applies between it and the global physics world object.
      * @param b The second rigid body to constrain (optional).
+     * @return Pointer to the created PhysicsFixedConstraint object.
      */
     PhysicsFixedConstraint* createFixedConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
 
@@ -105,6 +106,7 @@ public:
      * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
      *      body specified the constraint applies between it and the global physics world object.
      * @param b The second rigid body to constrain (optional).
+     * @return Pointer to the created PhysicsGenericConstraint object.
      */
     PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
 
@@ -122,6 +124,7 @@ public:
      *      (in its local space) with respect to the constraint joint (optional).
      * @param translationOffsetB The translation offset for the second rigid body
      *      (in its local space) with respect to the constraint joint (optional).
+     * @return Pointer to the created PhysicsGenericConstraint object.
      */
     PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA, 
                                                       PhysicsRigidBody* b = NULL, const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
@@ -140,6 +143,7 @@ public:
      *      (in its local space) with respect to the constraint joint (optional).
      * @param translationOffsetB The translation offset for the second rigid body
      *      (in its local space) with respect to the constraint joint (optional).
+     * @return Pointer to the created PhysicsHingeConstraint object.
      */
     PhysicsHingeConstraint* createHingeConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
                                                   PhysicsRigidBody* b = NULL, const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
@@ -152,6 +156,7 @@ public:
      * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
      *      body specified the constraint applies between it and the global physics world object.
      * @param b The second rigid body to constrain (optional).
+     * @return Pointer to the created PhysicsSocketConstraint object.
      */
     PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
 
@@ -165,6 +170,7 @@ public:
      * @param b The second rigid body to constrain (optional).
      * @param translationOffsetB The translation offset for the second rigid body
      *      (in its local space) with respect to the constraint joint (optional).
+     * @return Pointer to the created PhysicsSocketConstraint object.
      */
     PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, const Vector3& translationOffsetA,
                                                     PhysicsRigidBody* b = NULL, const Vector3& translationOffsetB = Vector3());
@@ -177,6 +183,7 @@ public:
      * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
      *      body specified the constraint applies between it and the global physics world object.
      * @param b The second rigid body to constrain (optional).
+     * @return Pointer to the created PhysicsSpringConstraint object.
      */
     PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b);
 
@@ -194,6 +201,7 @@ public:
      *      (in its local space) with respect to the constraint joint (optional).
      * @param translationOffsetB The translation offset for the second rigid body
      *      (in its local space) with respect to the constraint joint (optional).
+     * @return Pointer to the created PhysicsSpringConstraint object.
      */
     PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,          
                                                     PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB);
@@ -224,7 +232,7 @@ public:
      * 
      * @param ray The ray to test intersection with.
      * @param distance How far along the given ray to test for intersections.
-     * @param result Optioanl pointer to a HitTest structure to store hit test result information in.
+     * @param result Optional pointer to a HitTest structure to store hit test result information in.
      * @return True if the ray test collided with a physics object, false otherwise.
      */
     bool rayTest(const Ray& ray, float distance, PhysicsController::HitResult* result = NULL);
@@ -237,6 +245,7 @@ public:
      *
      * @param object The collision object to test.
      * @param endPosition The end position of the sweep test, in world space.
+     * @param result Optional pointer to a HitTest structure to store hit test result information in.
      * @return True if the object intersects any other physics objects, false otherwise.
      */
     bool sweepTest(PhysicsCollisionObject* object, const Vector3& endPosition, PhysicsController::HitResult* result = NULL);
@@ -354,13 +363,55 @@ private:
     {
     public:
 
+        /** 
+         * DebugVertex.
+         */
         struct DebugVertex
         {
-            float x, y, z;
-            float r, g, b, a;
+            /**
+             * The x coordinate of the vertex.
+             */
+            float x;
+    
+            /**
+             * The y coordinate of the vertex.
+             */
+            float y;
+    
+            /**
+             * The z coordinate of the vertex.
+             */
+            float z;
+
+            /**
+             * The red color component of the vertex.
+             */
+            float r;
+    
+            /**
+             * The green color component of the vertex.
+             */
+            float g;
+    
+            /**
+             * The blue color component of the vertex.
+             */
+            float b;
+    
+            /**
+             * The alpha component of the vertex.
+             */
+            float a;
         };
 
-        DebugDrawer();        
+        /**
+         * Constructor.
+         */
+        DebugDrawer(); 
+
+        /** 
+         * Destructor.
+         */
         ~DebugDrawer();
         
         void begin(const Matrix& viewProjection);

+ 1 - 1
gameplay/src/PhysicsGhostObject.cpp

@@ -43,7 +43,7 @@ PhysicsGhostObject* PhysicsGhostObject::create(Node* node, Properties* propertie
 {
     // Check if the properties is valid and has a valid namespace.
     assert(properties);
-    if (!properties || !(strcmp(properties->getNamespace(), "ghost") == 0))
+    if (!properties || !(strcmp(properties->getNamespace(), "ghostObject") == 0))
     {
         WARN("Failed to load ghost object from properties object: must be non-null object and have namespace equal to \'ghost\'.");
         return NULL;

+ 3 - 0
gameplay/src/PhysicsGhostObject.h

@@ -62,6 +62,9 @@ protected:
      */
     static PhysicsGhostObject* create(Node* node, Properties* properties);
 
+    /**
+     * Pointer to the Bullet ghost collision object.
+     */
     btPairCachingGhostObject* _ghostObject;
 };
 

+ 2 - 2
gameplay/src/PhysicsRigidBody.cpp

@@ -145,9 +145,9 @@ PhysicsRigidBody* PhysicsRigidBody::create(Node* node, Properties* properties)
 {
     // Check if the properties is valid and has a valid namespace.
     assert(properties);
-    if (!properties || !(strcmp(properties->getNamespace(), "rigidbody") == 0))
+    if (!properties || !(strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
-        WARN("Failed to load rigid body from properties object: must be non-null object and have namespace equal to \'rigidbody\'.");
+        WARN("Failed to load rigid body from properties object: must be non-null object and have namespace equal to \'rigidBody\'.");
         return NULL;
     }
 

+ 1 - 1
gameplay/src/PhysicsRigidBody.h

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

+ 1 - 2
gameplay/src/PlatformQNX.cpp

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

+ 15 - 0
gameplay/src/RadioButton.h

@@ -131,9 +131,24 @@ protected:
      */
     static void clearSelected(const std::string& groupId);
 
+    /**
+     * The RadioButton's group ID.
+     */
     std::string _groupId;
+    
+    /**
+     * Whether the RadioButton is currently selected.
+     */
     bool _selected;
+    
+    /**
+     * The size at which the RadioButton's icon will be drawn.
+     */
     Vector2 _imageSize;
+
+    /**
+     * The ThemeImage to use for the RadioButton.
+     */ 
     Theme::ThemeImage* _image;
 
 private:

+ 19 - 0
gameplay/src/RenderState.h

@@ -357,10 +357,29 @@ private:
 
 protected:
 
+    /**
+     * Collection of MaterialParameter's to be applied to the gamplay::Effect.
+     */
     mutable std::vector<MaterialParameter*> _parameters;
+    
+    /**
+     * Map of IDs to AutoBindings.
+     */
     std::map<std::string, AutoBinding> _autoBindings;
+
+    /**
+     * The Node bound to the RenderState.
+     */
     Node* _nodeBinding;
+
+    /**
+     * The StateBlock of fixed-function render states that can be applied to the RenderState.
+     */
     mutable StateBlock* _state;
+
+    /**
+     * The RenderState's parent.
+     */
     RenderState* _parent;
 };
 

+ 37 - 2
gameplay/src/Scene.cpp

@@ -316,10 +316,45 @@ Material* createDebugMaterial()
     return material;
 }
 
+/**
+ * DebugVertex structure.
+ */
 struct DebugVertex
 {
-    float x, y, z;
-    float r, g, b, a;
+    /**
+     * The x coordinate of the vertex.
+     */
+    float x;
+
+    /**
+     * The y coordinate of the vertex.
+     */
+    float y;
+    
+    /**
+     * The z coordinate of the vertex.
+     */
+    float z;
+    
+    /** 
+     * The red color component of the vertex.
+     */
+    float r;
+
+    /** 
+     * The green color component of the vertex.
+     */
+    float g;
+    
+    /** 
+     * The blue color component of the vertex.
+     */
+    float b;
+    
+    /** 
+     * The alpha component of the vertex.
+     */
+    float a;
 };
 
 void drawDebugLine(MeshBatch* batch, const Vector3& point1, const Vector3& point2, const Vector3& color)

+ 57 - 8
gameplay/src/Scene.h

@@ -158,6 +158,21 @@ public:
      */
     void setAmbientColor(float red, float green, float blue);
 
+    /**
+     * Visits each node in the scene and calls the specified method pointer.
+     *
+     * Calling this method invokes the specified method pointer for each node
+     * in the scene hierarchy.
+     *
+     * The visitMethod parameter must be a pointer to a method that has a bool
+     * return type and accepts a single parameter of type Node*.
+     *
+     * @param instance The pointer to an instance of the object that contains visitMethod.
+     * @param visitMethod The pointer to the class method to call for each node in the scene.
+     */
+    template <class T>
+    void visit(T* instance, bool (T::*visitMethod)(Node*));
+
     /**
      * Visits each node in the scene and calls the specified method pointer.
      *
@@ -165,16 +180,16 @@ public:
      * in the scene hierarchy, passing the Node and the specified cookie value.
      * 
      * The visitMethod parameter must be a pointer to a method that has a bool
-     * return type and accepts two parameters: a Node pointer and a void* (cookie).
-     * The scene travesal continues while visitMethod return true. Returning false
-     * will cause the traversal to stop.
+     * return type and accepts two parameters: a Node pointer and a cookie of a
+     * user-specified type. The scene travesal continues while visitMethod return
+     * true. Returning false will cause the traversal to stop.
      *
      * @param instance The pointer to an instance of the object that contains visitMethod.
      * @param visitMethod The pointer to the class method to call for each node in the scene.
      * @param cookie An optional user-defined parameter that will be passed to each invocation of visitMethod.
      */
-    template <class T>
-    void visit(T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie = 0);
+    template <class T, class C>
+    void visit(T* instance, bool (T::*visitMethod)(Node*,C), C cookie);
 
     /**
      * Draws debugging information (bounding volumes, etc.) for the scene.
@@ -205,7 +220,13 @@ private:
      * Visits the given node and all of its children recursively.
      */
     template <class T>
-    bool visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie);
+    bool visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*));
+
+    /**
+     * Visits the given node and all of its children recursively.
+     */
+    template <class T, class C>
+    bool visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*,C), C cookie);
 
     std::string _id;
     Camera* _activeCamera;
@@ -218,7 +239,18 @@ private:
 };
 
 template <class T>
-void Scene::visit(T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie)
+void Scene::visit(T* instance, bool (T::*visitMethod)(Node*))
+{
+    for (Node* node = getFirstNode(); node != NULL; node = node->getNextSibling())
+    {
+        if (!visitNode(node, instance, visitMethod))
+            return;
+    }
+}
+
+
+template <class T, class C>
+void Scene::visit(T* instance, bool (T::*visitMethod)(Node*,C), C cookie)
 {
     for (Node* node = getFirstNode(); node != NULL; node = node->getNextSibling())
     {
@@ -228,7 +260,24 @@ void Scene::visit(T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie
 }
 
 template <class T>
-bool Scene::visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*,void*), void* cookie)
+bool Scene::visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*))
+{
+    // Invoke the visit method for this node.
+    if (!(instance->*visitMethod)(node))
+        return false;
+
+    // Recurse for all children.
+    for (Node* child = node->getFirstChild(); child != NULL; child = child->getNextSibling())
+    {
+        if (!visitNode(child, instance, visitMethod))
+            return false;
+    }
+
+    return true;
+}
+
+template <class T, class C>
+bool Scene::visitNode(Node* node, T* instance, bool (T::*visitMethod)(Node*,C), C cookie)
 {
     // Invoke the visit method for this node.
     if (!(instance->*visitMethod)(node, cookie))

+ 25 - 15
gameplay/src/SceneLoader.cpp

@@ -61,8 +61,9 @@ Scene* SceneLoader::load(const char* filePath)
         SceneNodeProperty::ROTATE |
         SceneNodeProperty::SCALE |
         SceneNodeProperty::TRANSLATE | 
-        SceneNodeProperty::TRANSPARENT);
-    applyNodeProperties(scene, sceneProperties, SceneNodeProperty::CHARACTER | SceneNodeProperty::GHOST | SceneNodeProperty::RIGIDBODY);
+        SceneNodeProperty::TRANSPARENT |
+        SceneNodeProperty::DYNAMIC);
+    applyNodeProperties(scene, sceneProperties, SceneNodeProperty::CHARACTER | SceneNodeProperty::GHOSTOBJECT | SceneNodeProperty::RIGIDBODY);
     createAnimations(scene);
 
     // Find the physics properties object.
@@ -195,7 +196,7 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
         snp._type == SceneNodeProperty::MATERIAL ||
         snp._type == SceneNodeProperty::PARTICLE ||
         snp._type == SceneNodeProperty::CHARACTER ||
-        snp._type == SceneNodeProperty::GHOST ||
+        snp._type == SceneNodeProperty::GHOSTOBJECT ||
         snp._type == SceneNodeProperty::RIGIDBODY)
     {
         // Check to make sure the referenced properties object was loaded properly.
@@ -250,7 +251,7 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             break;
         }
         case SceneNodeProperty::CHARACTER:
-        case SceneNodeProperty::GHOST:
+        case SceneNodeProperty::GHOSTOBJECT:
         case SceneNodeProperty::RIGIDBODY:
         {
             // Check to make sure the referenced properties object was loaded properly.
@@ -283,20 +284,20 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             {
                 WARN_VARG("Attempting to set a 'character' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
-            else if (snp._type == SceneNodeProperty::GHOST && strcmp(p->getNamespace(), "ghost") != 0)
+            else if (snp._type == SceneNodeProperty::GHOSTOBJECT && strcmp(p->getNamespace(), "ghostObject") != 0)
             {
-                WARN_VARG("Attempting to set a 'ghost' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
+                WARN_VARG("Attempting to set a 'ghostObject' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
-            else if (snp._type == SceneNodeProperty::RIGIDBODY && strcmp(p->getNamespace(), "rigidbody") != 0)
+            else if (snp._type == SceneNodeProperty::RIGIDBODY && strcmp(p->getNamespace(), "rigidBody") != 0)
             {
-                WARN_VARG("Attempting to set a 'rigidbody' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
+                WARN_VARG("Attempting to set a 'rigidBody' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
             else
             {
                 // If the scene file specifies a rigid body model, use it for creating the collision object.
                 Properties* np = sceneProperties->getNamespace(sceneNode._nodeID);
                 const char* name = NULL;
-                if (np && (name = np->getString("rigidbodymodel")))
+                if (np && (name = np->getString("rigidBodyModel")))
                 {
                     Node* modelNode = node->getScene()->findNode(name);
                     if (!modelNode)
@@ -307,14 +308,14 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
                             WARN_VARG("Node '%s' does not have a model; attempting to use its model for collision object creation.", name);
                         else
                         {
-                            // Temporarily set rigidbody model on model so it's used during collision object creation.
+                            // Temporarily set rigidBody model on model so it's used during collision object creation.
                             Model* model = node->getModel();
                             assert(model);
                         
                             // Up ref count to prevent node from releasing the model when we swap it.
                             model->addRef(); 
                         
-                            // Create collision object with new rigidbodymodel set.
+                            // Create collision object with new rigidBodyModel set.
                             node->setModel(modelNode->getModel());
                             node->setCollisionObject(p);
 
@@ -370,6 +371,11 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             node->setTransparent(true);
             break;
         }
+        case SceneNodeProperty::DYNAMIC:
+        {
+            node->setDynamic(true);
+            break;
+        }
         default:
             WARN_VARG("Unsupported node property type: %d.", snp._type);
             break;
@@ -554,15 +560,15 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::CHARACTER, ns->getString());
                 }
-                else if (strcmp(name, "ghost") == 0)
+                else if (strcmp(name, "ghostObject") == 0)
                 {
-                    addSceneNodeProperty(sceneNode, SceneNodeProperty::GHOST, ns->getString());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::GHOSTOBJECT, ns->getString());
                 }
-                else if (strcmp(name, "rigidbody") == 0)
+                else if (strcmp(name, "rigidBody") == 0)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::RIGIDBODY, ns->getString());
                 }
-                else if (strcmp(name, "rigidbodymodel") == 0)
+                else if (strcmp(name, "rigidBodyModel") == 0)
                 {
                     // Ignore this for now. We process this when we do rigid body creation.
                 }
@@ -582,6 +588,10 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::TRANSPARENT);
                 }
+                else if (strcmp(name, "dynamic") == 0)
+                {
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::DYNAMIC);
+                }
                 else
                 {
                     WARN_VARG("Unsupported node property: %s = %s", name, ns->getString());

+ 3 - 2
gameplay/src/SceneLoader.h

@@ -46,13 +46,14 @@ private:
             MATERIAL = 2,
             PARTICLE = 4,
             CHARACTER = 8,
-            GHOST = 16,
+            GHOSTOBJECT = 16,
             RIGIDBODY = 32,
             TRANSLATE = 64,
             ROTATE = 128,
             SCALE = 256,
             URL = 512,
-            TRANSPARENT = 1024
+            TRANSPARENT = 1024,
+            DYNAMIC = 2048
         };
 
         SceneNodeProperty(Type type, std::string file, std::string id, int index) : _type(type), _file(file), _id(id), _index(index) { }

+ 38 - 2
gameplay/src/Slider.h

@@ -149,16 +149,52 @@ protected:
      */
     void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
 
-    void update(const Rectangle& clip);
-
+    /**
+     * Called when a slider's properties change. Updates this slider's internal rendering
+     * properties, such as its text viewport.
+     *
+     * @param clip The clipping rectangle of this slider's parent container.
+     */
+    void update(const Rectangle& clip); 
+
+    /**
+     * The minimum value for the Slider.
+     */
     float _min;
+    
+    /**
+     * The maximum value for the Slider
+     */
     float _max;
+    
+    /**
+     * The Slider's step size.
+     */
     float _step;
+    
+    /**
+     * The Slider's current value.
+     */
     float _value;
 
+    /**
+     * The image for the minimum slider value.
+     */
     Theme::ThemeImage* _minImage;
+    
+    /**
+     * The image for the maximum slider value.
+     */
     Theme::ThemeImage* _maxImage;
+    
+    /**
+     * The image for the slider track.
+     */
     Theme::ThemeImage* _trackImage;
+    
+    /**
+     * The image for the slider marker.
+     */
     Theme::ThemeImage* _markerImage;
 
 private:

+ 47 - 4
gameplay/src/SpriteBatch.cpp

@@ -45,12 +45,55 @@
 namespace gameplay
 {
 
-// Sprite vertex structured used for batching
+/**
+ * Sprite vertex structure used for batching.
+ */
 struct SpriteVertex
 {
-    float x, y, z;
-    float u, v;
-    float r, g, b, a;
+    /**
+     * The x coordinate of the vertex.
+     */
+    float x;
+    
+    /**
+     * The y coordinate of the vertex.
+     */
+    float y;
+    
+    /**
+     * The z coordinate of the vertex.
+     */
+    float z;
+
+    /**
+     * The u component of the (u, v) texture coordinates for the vertex.
+     */
+    float u;
+    
+    /**
+     * The v component of the (u, v) texture coordinates for the vertex.
+     */
+    float v;
+
+    /**
+     * The red color component of the vertex.
+     */
+    float r;
+    
+    /**
+     * The green color component of the vertex.
+     */
+    float g;
+    
+    /**
+     * The blue color component of the vertex.
+     */
+    float b;
+    
+    /**
+     * The alpha component of the vertex.
+     */
+    float a;
 };
 
 // Shared sprite effects

+ 19 - 0
gameplay/src/TextBox.h

@@ -122,10 +122,29 @@ protected:
      */
     void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
 
+    /**
+     * The current position of the TextBox's caret.
+     */
     Vector2 _caretLocation;
+
+    /**
+     * The index into the TextBox's string that the caret is.
+     */
     unsigned int textIndex;
+    
+    /**
+     * The last character that was entered into the TextBox.
+     */
     int _lastKeypress;
+
+    /**
+     * The font size to be used in the TextBox.
+     */
     unsigned int _fontSize;
+    
+    /**
+     * The Theme::Image for the TextBox's caret.
+     */
     Theme::ThemeImage* _caretImage;
 
 private:

+ 31 - 31
gameplay/src/Texture.cpp

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

+ 3 - 3
gameplay/src/Texture.h

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

+ 79 - 2
gameplay/src/Theme.h

@@ -155,15 +155,44 @@ public:
      */
     struct UVs
     {
+        /**
+         * Constructor.
+         */
         UVs();
 
+        /**
+         * Constructor
+         *
+         * @param u1 u component of the first UV coordinate.
+         * @param v1 v component of the first UV coordinate.
+         * @param u2 u component of the second UV coordinate.
+         * @param v2 v component of the second UV coordinate.
+         */
         UVs(float u1, float v1, float u2, float v2);
 
+        /**
+         * Get's an empty UVs.
+         */
         static const UVs& empty();
 
+        /**
+         * u component of the first UV coordinate.
+         */
         float u1;
+        
+        /**
+         * v component of the first UV coordinate.
+         */
         float v1;
+        
+        /**
+         * u component of the second UV coordinate.
+         */
         float u2;
+        
+        /**
+         * v component of the second UV coordinate.
+         */
         float v2;
     };
 
@@ -171,17 +200,53 @@ public:
      * Struct representing margin, border, and padding areas by
      * the width or height of each side.
      */
-    typedef struct SideRegions
+    struct SideRegions
     {
+        /** 
+         * Constructor.
+         */
         SideRegions() : top(0), bottom(0), left(0), right(0) {}
 
+        /**
+         * Gets an empty SideRegion.
+         */
         static const SideRegions& empty();
 
+        /**
+         * The top of the SideRegion.
+         */
         float top;
+        
+        /**
+         * The bottom of the SideRegion.
+         */
         float bottom;
+        
+        /**
+         * The left side of the SideRegion.
+         */
         float left;
+        
+        /**
+         * The right side of the SideRegion.
+         */
         float right;
-    } Margin, Border, Padding;
+    };
+    
+    /** 
+     * Struct representing margin areas by the width or height of each side.
+     */
+    typedef SideRegions Margin;
+    
+    /** 
+     * Struct representing border areas by the width or height of each side.
+     */
+    typedef SideRegions Border;
+    
+    /** 
+     * Struct representing padding areas by the width or height of each side.
+     */
+    typedef SideRegions Padding;
 
     /**
      * Class representing an image within the theme's texture atlas.
@@ -195,12 +260,24 @@ public:
 
     public:
 
+        /**
+         * Gets the ID of the ThemeImage.
+         */
         const char* getId() const;
 
+        /**
+         * Gets the UV coordinates for the ThemeImage.
+         */
         const UVs& getUVs() const;
 
+        /** 
+         * Gets the Rectangle region of the ThemeImage.
+         */
         const Rectangle& getRegion() const;
 
+        /** 
+         * Gets the color of the ThemeImage in a Vector4.
+         */
         const Vector4& getColor() const;
 
     private:

+ 38 - 1
gameplay/src/Transform.h

@@ -709,7 +709,7 @@ public:
      * Adds a transform listener.
      *
      * @param listener The listener to add.
-     * @param cookie An optional long value that is passed to the specified listener when it is called..
+     * @param cookie An optional long value that is passed to the specified listener when it is called.
      */
     void addListener(Transform::Listener* listener, long cookie = 0);
 
@@ -735,12 +735,26 @@ public:
 
 protected:
 
+    /**
+     * Transform Listener.
+     */
     struct TransformListener
     {
+        /**
+         * Listener for Transform events.
+         */
         Listener* listener;
+
+        /**
+         * An optional long value that is specified to the Listener's callback.
+         */
         long cookie;
     };
 
+    /**
+     * Defines the matrix dirty bits for marking the translation, scale and rotation
+     * components of the Transform.
+     */
     enum MatrixDirtyBits
     {
         DIRTY_TRANSLATION = 0x01,
@@ -766,11 +780,34 @@ protected:
      */
     void cloneInto(Transform* transform, NodeCloneContext &context) const;
 
+    /**
+     * The scale component of the Transform.
+     */
     Vector3 _scale;
+
+    /** 
+     * The rotation component of the Transform.
+     */
     Quaternion _rotation;
+    
+    /** 
+     * The translation component of the Transform.
+     */
     Vector3 _translation;
+    
+    /** 
+     * The Matrix representation of the Transform.
+     */
     mutable Matrix _matrix;
+    
+    /** 
+     * Matrix dirty bits flag.
+     */
     mutable char _matrixDirtyBits;
+    
+    /** 
+     * List of TransformListener's on the Transform.
+     */
     std::list<TransformListener>* _listeners;
 
 private:

+ 7 - 7
gameplay/src/VertexAttributeBinding.cpp

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

+ 4 - 0
gameplay/src/VerticalLayout.h

@@ -69,6 +69,10 @@ protected:
      */
     void update(const Container* container);
 
+    /**
+     * Flag determining whether this layout will start laying out controls from the bottom of the container.
+     * The default is 'false' meaning controls will start at the top.
+     */
     bool _bottomToTop;
 
 private: