瀏覽代碼

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

Darryl Gough 12 年之前
父節點
當前提交
b3bb05228e
共有 37 個文件被更改,包括 657 次插入317 次删除
  1. 31 31
      gameplay.sln
  2. 1 1
      gameplay/gameplay.vcxproj
  3. 12 1
      gameplay/src/AIStateMachine.cpp
  4. 1 5
      gameplay/src/Container.cpp
  5. 2 2
      gameplay/src/Control.cpp
  6. 3 5
      gameplay/src/Form.cpp
  7. 1 3
      gameplay/src/Form.h
  8. 1 1
      gameplay/src/Game.cpp
  9. 1 3
      gameplay/src/Game.h
  10. 6 2
      gameplay/src/Gamepad.cpp
  11. 5 0
      gameplay/src/MaterialParameter.cpp
  12. 14 4
      gameplay/src/MaterialParameter.h
  13. 7 1
      gameplay/src/Node.cpp
  14. 5 4
      gameplay/src/Pass.cpp
  15. 13 5
      gameplay/src/Platform.cpp
  16. 154 68
      gameplay/src/RenderState.cpp
  17. 15 21
      gameplay/src/RenderState.h
  18. 1 0
      gameplay/src/Technique.cpp
  19. 1 33
      gameplay/src/lua/lua_Game.cpp
  20. 2 0
      gameplay/src/lua/lua_Global.cpp
  21. 76 0
      gameplay/src/lua/lua_ImageControl.cpp
  22. 2 0
      gameplay/src/lua/lua_ImageControl.h
  23. 14 3
      install.bat
  24. 1 0
      samples/browser/res/common/forms/formBasicControls.form
  25. 1 0
      samples/browser/res/common/forms/formFlowLayout.form
  26. 1 0
      samples/browser/res/common/forms/formScrolling.form
  27. 1 0
      samples/browser/res/common/forms/formSelect.form
  28. 1 0
      samples/browser/res/common/forms/formVerticalLayout.form
  29. 2 1
      samples/browser/res/common/forms/formZOrder.form
  30. 44 34
      samples/browser/src/FormsSample.cpp
  31. 1 1
      samples/browser/src/FormsSample.h
  32. 1 1
      samples/character/src/CharacterGame.cpp
  33. 4 1
      samples/particles/res/editor.form
  34. 4 1
      samples/racer/src/RacerGame.cpp
  35. 60 25
      template/template-CMakeLists.txt
  36. 46 6
      tools/encoder/src/FBXSceneEncoder.cpp
  37. 122 54
      tools/luagen/gameplay-luagen.doxyfile

+ 31 - 31
gameplay.sln

@@ -38,7 +38,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-particles", "samples
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample06-racer", "samples\racer\sample-racer.vcxproj", "{82522888-E09A-ED48-AD7D-247237B37B3A}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample-racer", "samples\racer\sample-racer.vcxproj", "{82522888-E09A-ED48-AD7D-247237B37B3A}"
 	ProjectSection(ProjectDependencies) = postProject
 		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
 	EndProjectSection
@@ -149,6 +149,36 @@ Global
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|Win32.Build.0 = Release|Win32
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|x64.ActiveCfg = Release|x64
 		{D672DC66-3CE0-4878-B0D2-813CA731012F}.Release|x64.Build.0 = Release|x64
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|Win32.ActiveCfg = Debug|Win32
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|Win32.Build.0 = Debug|Win32
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|x64.ActiveCfg = Debug|x64
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|x64.Build.0 = Debug|x64
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|Win32.Build.0 = DebugMem|Win32
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|x64.ActiveCfg = DebugMem|x64
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|x64.Build.0 = DebugMem|x64
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerry.Build.0 = Release|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|Win32.ActiveCfg = Release|Win32
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|Win32.Build.0 = Release|Win32
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|x64.ActiveCfg = Release|x64
+		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|x64.Build.0 = Release|x64
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
 		{9A515C8B-3320-4C5C-9754-211E91206C9D}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
@@ -269,36 +299,6 @@ Global
 		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|Win32.Build.0 = Release|Win32
 		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|x64.ActiveCfg = Release|x64
 		{CB5ABFAA-EA69-E439-5A4D-3B9359916C71}.Release|x64.Build.0 = Release|x64
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerrySimulator.ActiveCfg = Debug|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerrySimulator.Build.0 = Debug|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|BlackBerrySimulator.Deploy.0 = Debug|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|Win32.ActiveCfg = Debug|Win32
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|Win32.Build.0 = Debug|Win32
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|x64.ActiveCfg = Debug|x64
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Debug|x64.Build.0 = Debug|x64
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerry.ActiveCfg = DebugMem|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerry.Build.0 = DebugMem|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerry.Deploy.0 = DebugMem|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerrySimulator.ActiveCfg = DebugMem|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerrySimulator.Build.0 = DebugMem|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|BlackBerrySimulator.Deploy.0 = DebugMem|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|Win32.Build.0 = DebugMem|Win32
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|x64.ActiveCfg = DebugMem|x64
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.DebugMem|x64.Build.0 = DebugMem|x64
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerry.ActiveCfg = Release|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerry.Build.0 = Release|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerry.Deploy.0 = Release|BlackBerry
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerrySimulator.ActiveCfg = Release|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerrySimulator.Build.0 = Release|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|BlackBerrySimulator.Deploy.0 = Release|BlackBerrySimulator
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|Win32.ActiveCfg = Release|Win32
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|Win32.Build.0 = Release|Win32
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|x64.ActiveCfg = Release|x64
-		{04EAF3E5-0F9E-AF4D-53F9-269CE114211F}.Release|x64.Build.0 = Release|x64
 		{82522888-E09A-ED48-AD7D-247237B37B3A}.Debug|BlackBerry.ActiveCfg = Debug|BlackBerry
 		{82522888-E09A-ED48-AD7D-247237B37B3A}.Debug|BlackBerry.Build.0 = Debug|BlackBerry
 		{82522888-E09A-ED48-AD7D-247237B37B3A}.Debug|BlackBerry.Deploy.0 = Debug|BlackBerry

+ 1 - 1
gameplay/gameplay.vcxproj

@@ -900,7 +900,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>__BB10__;_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_BLACKBERRY_GAMEPAD;_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)src;..\external-deps\lua\include;..\external-deps\bullet\include;..\external-deps\openal\include\AL;..\external-deps\alut\include\AL;..\external-deps\oggvorbis\include;..\external-deps\glew\include;..\external-deps\libpng\include;..\external-deps\zlib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeTypeInfo>
       </RuntimeTypeInfo>

+ 12 - 1
gameplay/src/AIStateMachine.cpp

@@ -25,7 +25,18 @@ AIStateMachine::~AIStateMachine()
     {
         (*itr)->release();
     }
-    SAFE_RELEASE(AIState::_empty);
+
+    if (AIState::_empty)
+    {
+        if (AIState::_empty->getRefCount() == 1)
+        {
+            SAFE_RELEASE(AIState::_empty);
+        }
+        else
+        {
+            AIState::_empty->release();
+        }
+    }
 }
 
 AIAgent* AIStateMachine::getAgent() const

+ 1 - 5
gameplay/src/Container.cpp

@@ -1643,11 +1643,7 @@ bool Container::pointerEvent(bool mouse, char evt, int x, int y, int data)
     }
 
     release();
-    if (x > _clipBounds.x && x <= _clipBounds.x + _clipBounds.width &&
-        y > _clipBounds.y && y <= _clipBounds.y + _clipBounds.height)
-        return (_consumeInputEvents | eventConsumed);
-    else
-        return eventConsumed;
+    return (_consumeInputEvents | eventConsumed);
 }
 
 Container::Scroll Container::getScroll(const char* scroll)

+ 2 - 2
gameplay/src/Control.cpp

@@ -7,7 +7,7 @@ namespace gameplay
 
 Control::Control()
     : _id(""), _state(Control::NORMAL), _bounds(Rectangle::empty()), _clipBounds(Rectangle::empty()), _viewportClipBounds(Rectangle::empty()),
-    _clearBounds(Rectangle::empty()), _dirty(true), _consumeInputEvents(true), _alignment(ALIGN_TOP_LEFT), _isAlignmentSet(false), _autoWidth(false), _autoHeight(false), _listeners(NULL), _visible(true),
+    _clearBounds(Rectangle::empty()), _dirty(true), _consumeInputEvents(false), _alignment(ALIGN_TOP_LEFT), _isAlignmentSet(false), _autoWidth(false), _autoHeight(false), _listeners(NULL), _visible(true),
     _zIndex(-1), _contactIndex(INVALID_CONTACT_INDEX), _focusIndex(-1), _parent(NULL), _styleOverridden(false), _skin(NULL)
 {
     addScriptEvent("controlEvent", "<Control>[Control::Listener::EventType]");
@@ -41,7 +41,7 @@ void Control::initialize(Theme::Style* style, Properties* properties)
     _autoWidth = properties->getBool("autoWidth");
     _autoHeight = properties->getBool("autoHeight");
 
-    _consumeInputEvents = properties->getBool("consumeInputEvents", true);
+    _consumeInputEvents = properties->getBool("consumeInputEvents", false);
 
     _visible = properties->getBool("visible", true);
 

+ 3 - 5
gameplay/src/Form.cpp

@@ -151,7 +151,7 @@ Form* Form::create(const char* url)
     }
     form->initialize(style, formProperties);
 
-    form->_consumeInputEvents = formProperties->getBool("consumeInputEvents", true);
+    form->_consumeInputEvents = formProperties->getBool("consumeInputEvents", false);
 
     // Alignment
     if ((form->_alignment & Control::ALIGN_BOTTOM) == Control::ALIGN_BOTTOM)
@@ -722,7 +722,7 @@ bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelt
     return false;
 }
 
-bool Form::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
+void Form::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
 {
     for (size_t i = 0; i < __forms.size(); ++i)
     {
@@ -732,11 +732,9 @@ bool Form::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, uns
         if (form->isEnabled() && form->isVisible() && form->getState() == FOCUS)
         {
             if (form->gamepadEvent(evt, gamepad, analogIndex))
-                return true;
+                return;
         }
     }
-
-    return false;
 }
 
 bool Form::projectPoint(int x, int y, Vector3* point)

+ 1 - 3
gameplay/src/Form.h

@@ -222,11 +222,9 @@ private:
     /**
      * Propagate gamepad events to enabled forms.
      *
-     * @return True if the gamepad event is consumed, false otherwise.
-     *
      * @see Control::gamepadEvent
      */
-    static bool gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex);
+    static void gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex);
 
     /**
      * Get the next highest power of two of an integer.  Used when creating framebuffers.

+ 1 - 1
gameplay/src/Game.cpp

@@ -509,7 +509,7 @@ void Game::gestureTapEvent(int x, int y)
 {
 }
 
-void Game::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
+void Game::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
 {
 }
 

+ 1 - 3
gameplay/src/Game.h

@@ -445,13 +445,11 @@ public:
     /**
      * Gamepad callback on gamepad events.  Override to receive Gamepad::CONNECTED_EVENT 
      * and Gamepad::DISCONNECTED_EVENT, and store the Gamepad* in order to poll it from update().
-     * Or, handle all gamepad input through BUTTON, JOYSTICK and TRIGGER events.
      *
      * @param evt The gamepad event that occurred.
      * @param gamepad The gamepad that generated the event.
-     * @param analogIndex If this is a JOYSTICK_EVENT or TRIGGER_EVENT, the index of the joystick or trigger whose value changed.
      */
-    virtual void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex = 0);
+    virtual void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad);
 
     /**
      * Gets the current number of gamepads currently connected to the system.

+ 6 - 2
gameplay/src/Gamepad.cpp

@@ -140,12 +140,14 @@ void Gamepad::bindGamepadControls(Container* container)
         else if (std::strcmp("joystick", control->getType()) == 0)
         {
             Joystick* joystick = (Joystick*)control;
+            joystick->setConsumeInputEvents(true);
             _uiJoysticks[joystick->getIndex()] = joystick;
             _joystickCount++;
         }
         else if (std::strcmp("button", control->getType()) == 0)
         {
             Button* button = (Button*)control;
+            button->setConsumeInputEvents(true);
             _uiButtons[button->getDataBinding()] = button;
             _buttonCount++;
         }
@@ -328,7 +330,8 @@ unsigned int Gamepad::getJoystickCount() const
 
 void Gamepad::getJoystickValues(unsigned int joystickId, Vector2* outValue) const
 {
-    GP_ASSERT(joystickId < _joystickCount);
+    if (joystickId >= _joystickCount)
+        return;
 
     if (_form)
     {
@@ -356,7 +359,8 @@ unsigned int Gamepad::getTriggerCount() const
 
 float Gamepad::getTriggerValue(unsigned int triggerId) const
 {
-    GP_ASSERT(triggerId < _triggerCount);
+    if (triggerId >= _triggerCount)
+        return 0.0f;
 
     if (_form)
     {

+ 5 - 0
gameplay/src/MaterialParameter.cpp

@@ -668,4 +668,9 @@ void MaterialParameter::cloneInto(MaterialParameter* materialParameter) const
     this->AnimationTarget::cloneInto(materialParameter, context);
 }
 
+MaterialParameter::MethodBinding::MethodBinding(MaterialParameter* param) :
+    _parameter(param), _autoBinding(false)
+{
+}
+
 }

+ 14 - 4
gameplay/src/MaterialParameter.h

@@ -243,10 +243,19 @@ private:
      */
     class MethodBinding : public Ref
     {
+        friend class RenderState;
+
     public:
+
         virtual void setValue(Effect* effect) = 0;
 
     protected:
+
+        /**
+         * Constructor.
+         */
+        MethodBinding(MaterialParameter* param);
+
         /**
          * Destructor.
          */
@@ -256,6 +265,9 @@ private:
          * Hidden copy assignment operator.
          */
         MethodBinding& operator=(const MethodBinding&);
+
+        MaterialParameter* _parameter;
+        bool _autoBinding;
     };
 
     /**
@@ -269,7 +281,6 @@ private:
         MethodValueBinding(MaterialParameter* param, ClassType* instance, ValueMethod valueMethod);
         void setValue(Effect* effect);
     private:
-        MaterialParameter* _parameter;
         ClassType* _instance;
         ValueMethod _valueMethod;
 
@@ -287,7 +298,6 @@ private:
         MethodArrayBinding(MaterialParameter* param, ClassType* instance, ValueMethod valueMethod, CountMethod countMethod);
         void setValue(Effect* effect);
     private:
-        MaterialParameter* _parameter;
         ClassType* _instance;
         ValueMethod _valueMethod;
         CountMethod _countMethod;
@@ -363,7 +373,7 @@ void MaterialParameter::bindValue(ClassType* classInstance, ParameterType (Class
 
 template <class ClassType, class ParameterType>
 MaterialParameter::MethodValueBinding<ClassType, ParameterType>::MethodValueBinding(MaterialParameter* param, ClassType* instance, ValueMethod valueMethod) :
-    _parameter(param), _instance(instance), _valueMethod(valueMethod)
+    MethodBinding(param), _instance(instance), _valueMethod(valueMethod)
 {
 }
 
@@ -375,7 +385,7 @@ void MaterialParameter::MethodValueBinding<ClassType, ParameterType>::setValue(E
 
 template <class ClassType, class ParameterType>
 MaterialParameter::MethodArrayBinding<ClassType, ParameterType>::MethodArrayBinding(MaterialParameter* param, ClassType* instance, ValueMethod valueMethod, CountMethod countMethod) :
-    _parameter(param), _instance(instance), _valueMethod(valueMethod), _countMethod(countMethod)
+    MethodBinding(param), _instance(instance), _valueMethod(valueMethod), _countMethod(countMethod)
 {
 }
 

+ 7 - 1
gameplay/src/Node.cpp

@@ -980,11 +980,13 @@ Node* Node::cloneRecursive(NodeCloneContext &context) const
     Node* copy = cloneSingleNode(context);
     GP_ASSERT(copy);
 
+    // Find our current last child
     Node* lastChild = NULL;
     for (Node* child = getFirstChild(); child != NULL; child = child->getNextSibling())
     {
         lastChild = child;
     }
+
     // Loop through the nodes backwards because addChild adds the node to the front.
     for (Node* child = lastChild; child != NULL; child = child->getPreviousSibling())
     {
@@ -993,6 +995,7 @@ Node* Node::cloneRecursive(NodeCloneContext &context) const
         copy->addChild(childCopy);
         childCopy->release();
     }
+
     return copy;
 }
 
@@ -1029,7 +1032,10 @@ void Node::cloneInto(Node* node, NodeCloneContext &context) const
     }
     node->_world = _world;
     node->_bounds = _bounds;
-    node->_userData = _userData;
+
+    // Note: Do not clone _userData - we can't make any assumptions about its content and how it's managed,
+    // so it's the caller's responsibility to clone user data if needed.
+
     if (_tags)
     {
         node->_tags = new std::map<std::string, std::string>(_tags->begin(), _tags->end());

+ 5 - 4
gameplay/src/Pass.cpp

@@ -54,10 +54,10 @@ void Pass::setVertexAttributeBinding(VertexAttributeBinding* binding)
     }
 }
 
- VertexAttributeBinding* Pass::getVertexAttributeBinding() const
- {
-     return _vaBinding;
- }
+VertexAttributeBinding* Pass::getVertexAttributeBinding() const
+{
+    return _vaBinding;
+}
 
 void Pass::bind()
 {
@@ -92,6 +92,7 @@ Pass* Pass::clone(Technique* technique, NodeCloneContext &context) const
     effect->addRef();
     Pass* pass = new Pass(getId(), technique, effect);
     RenderState::cloneInto(pass, context);
+    pass->_parent = technique;
     return pass;
 }
 

+ 13 - 5
gameplay/src/Platform.cpp

@@ -57,11 +57,19 @@ void Platform::resizeEventInternal(unsigned int width, unsigned int height)
 
 void Platform::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
 {
-    if (!Form::gamepadEventInternal(evt, gamepad, analogIndex))
-    {
-        Game::getInstance()->gamepadEvent(evt, gamepad, analogIndex);
-        Game::getInstance()->getScriptController()->gamepadEvent(evt, gamepad, analogIndex);
-    }
+	switch(evt)
+	{
+	case Gamepad::CONNECTED_EVENT:
+	case Gamepad::DISCONNECTED_EVENT:
+		Game::getInstance()->gamepadEvent(evt, gamepad);
+        Game::getInstance()->getScriptController()->gamepadEvent(evt, gamepad);
+		break;
+	case Gamepad::BUTTON_EVENT:
+	case Gamepad::JOYSTICK_EVENT:
+	case Gamepad::TRIGGER_EVENT:
+		Form::gamepadEventInternal(evt, gamepad, analogIndex);
+		break;
+	}
 }
 
 void Platform::gamepadEventConnectedInternal(GamepadHandle handle,  unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,

+ 154 - 68
gameplay/src/RenderState.cpp

@@ -227,79 +227,148 @@ void RenderState::applyAutoBinding(const char* uniformName, const char* autoBind
     MaterialParameter* param = getParameter(uniformName);
     GP_ASSERT(param);
 
+    bool bound = false;
+
     // First attempt to resolve the binding using custom registered resolvers.
     if (_customAutoBindingResolvers.size() > 0)
     {
         for (size_t i = 0, count = _customAutoBindingResolvers.size(); i < count; ++i)
         {
             if (_customAutoBindingResolvers[i](autoBinding, _nodeBinding, param))
-                return; // handled by custom resolver
+            {
+                // Handled by custom auto binding resolver
+                bound = true;
+                break;
+            }
         }
     }
 
     // Perform built-in resolution
-    if (strcmp(autoBinding, "WORLD_MATRIX") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getWorldMatrix);
-    }
-    else if (strcmp(autoBinding, "VIEW_MATRIX") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getViewMatrix);
-    }
-    else if (strcmp(autoBinding, "PROJECTION_MATRIX") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getProjectionMatrix);
-    }
-    else if (strcmp(autoBinding, "WORLD_VIEW_MATRIX") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getWorldViewMatrix);
-    }
-    else if (strcmp(autoBinding, "VIEW_PROJECTION_MATRIX") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getViewProjectionMatrix);
-    }
-    else if (strcmp(autoBinding, "WORLD_VIEW_PROJECTION_MATRIX") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getWorldViewProjectionMatrix);
-    }
-    else if (strcmp(autoBinding, "INVERSE_TRANSPOSE_WORLD_MATRIX") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getInverseTransposeWorldMatrix);
-    }
-    else if (strcmp(autoBinding, "INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getInverseTransposeWorldViewMatrix);
-    }
-    else if (strcmp(autoBinding, "CAMERA_WORLD_POSITION") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getActiveCameraTranslationWorld);
-    }
-    else if (strcmp(autoBinding, "CAMERA_VIEW_POSITION") == 0)
-    {
-        param->bindValue(_nodeBinding, &Node::getActiveCameraTranslationView);
-    }
-    else if (strcmp(autoBinding, "MATRIX_PALETTE") == 0)
-    {
-        param->bindValue(this, &RenderState::autoBindingGetMatrixPalette, &RenderState::autoBindingGetMatrixPaletteSize);
-    }
-    else if (strcmp(autoBinding, "SCENE_AMBIENT_COLOR") == 0)
-    {
-        param->bindValue(this, &RenderState::autoBindingGetAmbientColor);
-    }
-    else if (strcmp(autoBinding, "SCENE_LIGHT_COLOR") == 0)
-    {
-        param->bindValue(this, &RenderState::autoBindingGetLightColor);
-    }
-    else if (strcmp(autoBinding, "SCENE_LIGHT_DIRECTION") == 0)
+    if (!bound)
     {
-        param->bindValue(this, &RenderState::autoBindingGetLightDirection);
+        bound = true;
+
+        if (strcmp(autoBinding, "WORLD_MATRIX") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetWorldMatrix);
+        }
+        else if (strcmp(autoBinding, "VIEW_MATRIX") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetViewMatrix);
+        }
+        else if (strcmp(autoBinding, "PROJECTION_MATRIX") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetProjectionMatrix);
+        }
+        else if (strcmp(autoBinding, "WORLD_VIEW_MATRIX") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetWorldViewMatrix);
+        }
+        else if (strcmp(autoBinding, "VIEW_PROJECTION_MATRIX") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetViewProjectionMatrix);
+        }
+        else if (strcmp(autoBinding, "WORLD_VIEW_PROJECTION_MATRIX") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetWorldViewProjectionMatrix);
+        }
+        else if (strcmp(autoBinding, "INVERSE_TRANSPOSE_WORLD_MATRIX") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetInverseTransposeWorldMatrix);
+        }
+        else if (strcmp(autoBinding, "INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetInverseTransposeWorldViewMatrix);
+        }
+        else if (strcmp(autoBinding, "CAMERA_WORLD_POSITION") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetCameraWorldPosition);
+        }
+        else if (strcmp(autoBinding, "CAMERA_VIEW_POSITION") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetCameraViewPosition);
+        }
+        else if (strcmp(autoBinding, "MATRIX_PALETTE") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetMatrixPalette, &RenderState::autoBindingGetMatrixPaletteSize);
+        }
+        else if (strcmp(autoBinding, "SCENE_AMBIENT_COLOR") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetAmbientColor);
+        }
+        else if (strcmp(autoBinding, "SCENE_LIGHT_COLOR") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetLightColor);
+        }
+        else if (strcmp(autoBinding, "SCENE_LIGHT_DIRECTION") == 0)
+        {
+            param->bindValue(this, &RenderState::autoBindingGetLightDirection);
+        }
+        else
+        {
+            bound = false;
+            GP_WARN("Unsupported auto binding type (%d).", autoBinding);
+        }
     }
-    else
+
+    if (bound)
     {
-        GP_WARN("Unsupported auto binding type (%d).", autoBinding);
+        // Mark parameter as an auto binding
+        if (param->_type == MaterialParameter::METHOD && param->_value.method)
+            param->_value.method->_autoBinding = true;
     }
 }
 
+const Matrix& RenderState::autoBindingGetWorldMatrix() const
+{
+    return _nodeBinding ? _nodeBinding->getWorldMatrix() : Matrix::identity();
+}
+
+const Matrix& RenderState::autoBindingGetViewMatrix() const
+{
+    return _nodeBinding ? _nodeBinding->getViewMatrix() : Matrix::identity();
+}
+
+const Matrix& RenderState::autoBindingGetProjectionMatrix() const
+{
+    return _nodeBinding ? _nodeBinding->getProjectionMatrix() : Matrix::identity();
+}
+
+const Matrix& RenderState::autoBindingGetWorldViewMatrix() const
+{
+    return _nodeBinding ? _nodeBinding->getWorldViewMatrix() : Matrix::identity();
+}
+
+const Matrix& RenderState::autoBindingGetViewProjectionMatrix() const
+{
+    return _nodeBinding ? _nodeBinding->getViewProjectionMatrix() : Matrix::identity();
+}
+
+const Matrix& RenderState::autoBindingGetWorldViewProjectionMatrix() const
+{
+    return _nodeBinding ? _nodeBinding->getWorldViewProjectionMatrix() : Matrix::identity();
+}
+
+const Matrix& RenderState::autoBindingGetInverseTransposeWorldMatrix() const
+{
+    return _nodeBinding ? _nodeBinding->getInverseTransposeWorldMatrix() : Matrix::identity();
+}
+
+const Matrix& RenderState::autoBindingGetInverseTransposeWorldViewMatrix() const
+{
+    return _nodeBinding ? _nodeBinding->getInverseTransposeWorldViewMatrix() : Matrix::identity();
+}
+
+Vector3 RenderState::autoBindingGetCameraWorldPosition() const
+{
+    return _nodeBinding ? _nodeBinding->getActiveCameraTranslationWorld() : Vector3::zero();
+}
+
+Vector3 RenderState::autoBindingGetCameraViewPosition() const
+{
+    return _nodeBinding ? _nodeBinding->getActiveCameraTranslationView() : Vector3::zero();
+}
+
 const Vector4* RenderState::autoBindingGetMatrixPalette() const
 {
     Model* model = _nodeBinding ? _nodeBinding->getModel() : NULL;
@@ -307,6 +376,13 @@ const Vector4* RenderState::autoBindingGetMatrixPalette() const
     return skin ? skin->getMatrixPalette() : NULL;
 }
 
+unsigned int RenderState::autoBindingGetMatrixPaletteSize() const
+{
+    Model* model = _nodeBinding ? _nodeBinding->getModel() : NULL;
+    MeshSkin* skin = model ? model->getSkin() : NULL;
+    return skin ? skin->getMatrixPaletteSize() : 0;
+}
+
 const Vector3& RenderState::autoBindingGetAmbientColor() const
 {
     Scene* scene = _nodeBinding ? _nodeBinding->getScene() : NULL;
@@ -326,13 +402,6 @@ const Vector3& RenderState::autoBindingGetLightDirection() const
     return scene ? scene->getLightDirection() : down;
 }
 
-unsigned int RenderState::autoBindingGetMatrixPaletteSize() const
-{
-    Model* model = _nodeBinding ? _nodeBinding->getModel() : NULL;
-    MeshSkin* skin = model ? model->getSkin() : NULL;
-    return skin ? skin->getMatrixPaletteSize() : 0;
-}
-
 void RenderState::bind(Pass* pass)
 {
     GP_ASSERT(pass);
@@ -406,6 +475,11 @@ void RenderState::cloneInto(RenderState* renderState, NodeCloneContext& context)
         const MaterialParameter* param = *it;
         GP_ASSERT(param);
 
+        // If this parameter is a method binding auto binding, don't clone it - it will get setup automatically
+        // via the cloned auto bindings instead.
+        if (param->_type == MaterialParameter::METHOD && param->_value.method && param->_value.method->_autoBinding)
+            continue;
+
         MaterialParameter* paramCopy = new MaterialParameter(param->getName());
         param->cloneInto(paramCopy);
 
@@ -415,11 +489,9 @@ void RenderState::cloneInto(RenderState* renderState, NodeCloneContext& context)
     // Clone our state block
     if (_state)
     {
-        // StateBlock contains only simple primitive data, so use the default assignment
-        // operator to do a memberwise copy.
-        *renderState->getStateBlock() = *_state;
+        _state->cloneInto(renderState->getStateBlock());
     }
-    
+
     // Notes:
     // 1. _nodeBinding should not be set here, it should be set by the caller.
     // 2. _parent should not be set here, since it's set in the constructor of Technique and Pass.
@@ -572,6 +644,20 @@ void RenderState::StateBlock::enableDepthWrite()
     }
 }
 
+void RenderState::StateBlock::cloneInto(StateBlock* state)
+{
+    GP_ASSERT(state);
+
+    state->_cullFaceEnabled = _cullFaceEnabled;
+    state->_depthTestEnabled = _depthTestEnabled;
+    state->_depthWriteEnabled = _depthWriteEnabled;
+    state->_depthFunction = _depthFunction;
+    state->_blendEnabled = _blendEnabled;
+    state->_blendSrc = _blendSrc;
+    state->_blendDst = _blendDst;
+    state->_bits = _bits;
+}
+
 static bool parseBoolean(const char* value)
 {
     GP_ASSERT(value);

+ 15 - 21
gameplay/src/RenderState.h

@@ -287,6 +287,8 @@ public:
 
         static void enableDepthWrite();
 
+        void cloneInto(StateBlock* state);
+
         // States
         bool _cullFaceEnabled;
         bool _depthTestEnabled;
@@ -476,31 +478,23 @@ private:
      */
     RenderState& operator=(const RenderState&);
 
-    /**
-     * Internal auto binding handler.
-     */
+    // Internal auto binding handler methods.
+    const Matrix& autoBindingGetWorldMatrix() const;
+    const Matrix& autoBindingGetViewMatrix() const;
+    const Matrix& autoBindingGetProjectionMatrix() const;
+    const Matrix& autoBindingGetWorldViewMatrix() const;
+    const Matrix& autoBindingGetViewProjectionMatrix() const;
+    const Matrix& autoBindingGetWorldViewProjectionMatrix() const;
+    const Matrix& autoBindingGetInverseTransposeWorldMatrix() const;
+    const Matrix& autoBindingGetInverseTransposeWorldViewMatrix() const;
+    Vector3 autoBindingGetCameraWorldPosition() const;
+    Vector3 autoBindingGetCameraViewPosition() const;
+    const Vector4* autoBindingGetMatrixPalette() const;
+    unsigned int autoBindingGetMatrixPaletteSize() const;
     const Vector3& autoBindingGetAmbientColor() const;
-
-    /**
-     * Internal auto binding handler.
-     */
     const Vector3& autoBindingGetLightColor() const;
-
-    /**
-     * Internal auto binding handler.
-     */
     const Vector3& autoBindingGetLightDirection() const;
 
-    /**
-     * Internal auto binding handler.
-     */
-    const Vector4* autoBindingGetMatrixPalette() const;
-
-    /**
-     * Internal auto binding handler.
-     */
-    unsigned int autoBindingGetMatrixPaletteSize() const;
-
 protected:
 
     /**

+ 1 - 0
gameplay/src/Technique.cpp

@@ -65,6 +65,7 @@ Technique* Technique::clone(Material* material, NodeCloneContext &context) const
         technique->_passes.push_back(passCopy);
     }
     RenderState::cloneInto(technique, context);
+    technique->_parent = material;
     return technique;
 }
 

+ 1 - 33
gameplay/src/lua/lua_Game.cpp

@@ -404,41 +404,9 @@ int lua_Game_gamepadEvent(lua_State* state)
             lua_error(state);
             break;
         }
-        case 4:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL) &&
-                (lua_type(state, 3) == LUA_TUSERDATA || lua_type(state, 3) == LUA_TTABLE || lua_type(state, 3) == LUA_TNIL) &&
-                lua_type(state, 4) == LUA_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                Gamepad::GamepadEvent param1 = (Gamepad::GamepadEvent)lua_enumFromString_GamepadGamepadEvent(luaL_checkstring(state, 2));
-
-                // Get parameter 2 off the stack.
-                bool param2Valid;
-                gameplay::ScriptUtil::LuaArray<Gamepad> param2 = gameplay::ScriptUtil::getObjectPointer<Gamepad>(3, "Gamepad", false, &param2Valid);
-                if (!param2Valid)
-                {
-                    lua_pushstring(state, "Failed to convert parameter 2 to type 'Gamepad'.");
-                    lua_error(state);
-                }
-
-                // Get parameter 3 off the stack.
-                unsigned int param3 = (unsigned int)luaL_checkunsigned(state, 4);
-
-                Game* instance = getInstance(state);
-                instance->gamepadEvent(param1, param2, param3);
-                
-                return 0;
-            }
-
-            lua_pushstring(state, "lua_Game_gamepadEvent - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 3 or 4).");
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
             lua_error(state);
             break;
         }

+ 2 - 0
gameplay/src/lua/lua_Global.cpp

@@ -22,6 +22,7 @@ void luaRegister_lua_Global()
     gameplay::ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "TextBox");
     gameplay::ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Transform");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Button", "CheckBox");
+    gameplay::ScriptUtil::setGlobalHierarchyPair("Button", "ImageControl");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Button", "RadioButton");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Container", "Form");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Control", "Button");
@@ -36,6 +37,7 @@ void luaRegister_lua_Global()
     gameplay::ScriptUtil::setGlobalHierarchyPair("Control", "TextBox");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Label", "Button");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Label", "CheckBox");
+    gameplay::ScriptUtil::setGlobalHierarchyPair("Label", "ImageControl");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Label", "RadioButton");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Label", "Slider");
     gameplay::ScriptUtil::setGlobalHierarchyPair("Label", "TextBox");

+ 76 - 0
gameplay/src/lua/lua_ImageControl.cpp

@@ -4,9 +4,12 @@
 #include "Animation.h"
 #include "AnimationTarget.h"
 #include "Base.h"
+#include "Button.h"
 #include "Control.h"
 #include "Game.h"
+#include "Gamepad.h"
 #include "ImageControl.h"
+#include "Label.h"
 #include "Node.h"
 #include "Ref.h"
 #include "ScriptController.h"
@@ -64,6 +67,7 @@ void luaRegister_ImageControl()
         {"getSkinRegion", lua_ImageControl_getSkinRegion},
         {"getState", lua_ImageControl_getState},
         {"getStyle", lua_ImageControl_getStyle},
+        {"getText", lua_ImageControl_getText},
         {"getTextAlignment", lua_ImageControl_getTextAlignment},
         {"getTextColor", lua_ImageControl_getTextColor},
         {"getTextRightToLeft", lua_ImageControl_getTextRightToLeft},
@@ -106,6 +110,7 @@ void luaRegister_ImageControl()
         {"setSkinRegion", lua_ImageControl_setSkinRegion},
         {"setState", lua_ImageControl_setState},
         {"setStyle", lua_ImageControl_setStyle},
+        {"setText", lua_ImageControl_setText},
         {"setTextAlignment", lua_ImageControl_setTextAlignment},
         {"setTextColor", lua_ImageControl_setTextColor},
         {"setTextRightToLeft", lua_ImageControl_setTextRightToLeft},
@@ -2261,6 +2266,41 @@ int lua_ImageControl_getStyle(lua_State* state)
     return 0;
 }
 
+int lua_ImageControl_getText(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
+            {
+                ImageControl* instance = getInstance(state);
+                const char* result = instance->getText();
+
+                // Push the return value onto the stack.
+                lua_pushstring(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_ImageControl_getText - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_ImageControl_getTextAlignment(lua_State* state)
 {
     // Get the number of parameters.
@@ -4309,6 +4349,42 @@ int lua_ImageControl_setStyle(lua_State* state)
     return 0;
 }
 
+int lua_ImageControl_setText(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = gameplay::ScriptUtil::getString(2, false);
+
+                ImageControl* instance = getInstance(state);
+                instance->setText(param1);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_ImageControl_setText - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_ImageControl_setTextAlignment(lua_State* state)
 {
     // Get the number of parameters.

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

@@ -46,6 +46,7 @@ int lua_ImageControl_getSkinColor(lua_State* state);
 int lua_ImageControl_getSkinRegion(lua_State* state);
 int lua_ImageControl_getState(lua_State* state);
 int lua_ImageControl_getStyle(lua_State* state);
+int lua_ImageControl_getText(lua_State* state);
 int lua_ImageControl_getTextAlignment(lua_State* state);
 int lua_ImageControl_getTextColor(lua_State* state);
 int lua_ImageControl_getTextRightToLeft(lua_State* state);
@@ -88,6 +89,7 @@ int lua_ImageControl_setSkinColor(lua_State* state);
 int lua_ImageControl_setSkinRegion(lua_State* state);
 int lua_ImageControl_setState(lua_State* state);
 int lua_ImageControl_setStyle(lua_State* state);
+int lua_ImageControl_setText(lua_State* state);
 int lua_ImageControl_setTextAlignment(lua_State* state);
 int lua_ImageControl_setTextColor(lua_State* state);
 int lua_ImageControl_setTextRightToLeft(lua_State* state);

+ 14 - 3
install.bat

@@ -55,13 +55,16 @@ cd %~dp0
 >> temp.cs ECHO         done = true;
 >> temp.cs ECHO     }
 >> temp.cs ECHO }
-> temp1.vbs ECHO Dim strFileURL, strHDLocation
+> temp1.vbs ECHO WScript.Echo "Downloading using a fallback method. This might take a few minutes."
+>> temp1.vbs ECHO Dim strFileURL, strHDLocation
 >> temp1.vbs ECHO strFileURL = WScript.Arguments(0)
 >> temp1.vbs ECHO strHDLocation = WScript.Arguments(1)
 >> temp1.vbs ECHO Set objXMLHTTP = CreateObject("MSXML2.XMLHTTP")
 >> temp1.vbs ECHO objXMLHTTP.open "GET", strFileURL, false
+>> temp1.vbs ECHO WScript.Echo "Sending request..."
 >> temp1.vbs ECHO objXMLHTTP.send()
 >> temp1.vbs ECHO If objXMLHTTP.Status = 200 Then
+>> temp1.vbs ECHO WScript.Echo "Got response. Processing body..."
 >> temp1.vbs ECHO Set objADOStream = CreateObject("ADODB.Stream")
 >> temp1.vbs ECHO objADOStream.Open
 >> temp1.vbs ECHO objADOStream.Type = 1
@@ -70,14 +73,22 @@ cd %~dp0
 >> temp1.vbs ECHO Set objFSO = Createobject("Scripting.FileSystemObject")
 >> temp1.vbs ECHO If objFSO.Fileexists(strHDLocation) Then objFSO.DeleteFile strHDLocation
 >> temp1.vbs ECHO Set objFSO = Nothing
+>> temp1.vbs ECHO WScript.Echo "Saving result to a file..."
 >> temp1.vbs ECHO objADOStream.SaveToFile strHDLocation
 >> temp1.vbs ECHO objADOStream.Close
 >> temp1.vbs ECHO Set objADOStream = Nothing
+>> temp1.vbs ECHO WScript.Echo "Success."
 >> temp1.vbs ECHO End if
 >> temp1.vbs ECHO Set objXMLHTTP = Nothing
 
-if not exist %windir%\Microsoft.NET\Framework\v2.0.50727\NUL goto USE_VBS_AS_FALLBACK
-%windir%\Microsoft.NET\Framework\v2.0.50727\csc temp.cs
+if exist %windir%\Microsoft.NET\Framework\v2.0.50727\NUL (
+    %windir%\Microsoft.NET\Framework\v2.0.50727\csc temp.cs
+) else (
+if exist %windir%\Microsoft.NET\Framework\v4.0.30319\NUL (
+    %windir%\Microsoft.NET\Framework\v4.0.30319\csc temp.cs
+) else (
+    goto USE_VBS_AS_FALLBACK
+))
 temp.exe
 del temp.exe
 goto :EXTRACT

+ 1 - 0
samples/browser/res/common/forms/formBasicControls.form

@@ -4,6 +4,7 @@ form basicControls
     layout = LAYOUT_ABSOLUTE
     style = basic
     size = 600, 600
+	consumeInputEvents = true
     	
 	label title
 	{

+ 1 - 0
samples/browser/res/common/forms/formFlowLayout.form

@@ -5,6 +5,7 @@ form flowLayout
     style = basic
     size = 600, 600
     scroll = SCROLL_BOTH
+	consumeInputEvents = true
 
     label label1
     {

+ 1 - 0
samples/browser/res/common/forms/formScrolling.form

@@ -6,6 +6,7 @@ form scrolling
     size = 600, 600
     scroll = SCROLL_BOTH
     scrollBarsAutoHide = true
+	consumeInputEvents = true
 
     label label1
     {

+ 1 - 0
samples/browser/res/common/forms/formSelect.form

@@ -6,6 +6,7 @@ form formSelect
     alignment = ALIGN_TOP_LEFT
     width = 200
     autoHeight = true
+	consumeInputEvents = true
 
 	radioButton form0
 	{

+ 1 - 0
samples/browser/res/common/forms/formVerticalLayout.form

@@ -5,6 +5,7 @@ form verticalLayout
     style = basic
     size = 600, 600
     scroll = SCROLL_BOTH
+	consumeInputEvents = true
 
     label label2
     {

+ 2 - 1
samples/browser/res/common/forms/formZOrder.form

@@ -4,7 +4,8 @@ form zOrder
     style = basic
     size = 600, 600
     scroll = SCROLL_BOTH
-
+	consumeInputEvents = true
+	
     label label1
     {
         style = basic

+ 44 - 34
samples/browser/src/FormsSample.cpp

@@ -7,6 +7,7 @@
 // Input bit-flags (powers of 2)
 #define KEY_A_MASK (1 << 0)
 #define KEY_B_MASK (1 << 1)
+#define KEY_SELECT_MASK (1 << 2)
 
 const static unsigned int __formsCount = 5;
 
@@ -185,6 +186,47 @@ void FormsSample::update(float elapsedTime)
     bool aDown = (_keyFlags & KEY_A_MASK);
     bool bDown = (_keyFlags & KEY_B_MASK);
 
+	// If no form is in focus, then we poll the gamepad for movement input.
+	if (_activeForm->getState() == Control::NORMAL &&
+        _formSelect->getState() == Control::NORMAL)
+    {
+        if (_gamepad->isButtonDown(Gamepad::BUTTON_A))
+            _keyFlags |= KEY_A_MASK;
+        else
+            _keyFlags &= ~KEY_A_MASK;
+
+        if (_gamepad->isButtonDown(Gamepad::BUTTON_B))
+            _keyFlags |= KEY_B_MASK;
+        else
+            _keyFlags &= ~KEY_B_MASK;
+
+        _gamepad->getJoystickValues(0, &_joysticks[0]);
+        _gamepad->getJoystickValues(1, &_joysticks[1]);
+    }
+
+    // We'll use a physical gamepad's MENU1 button as the "back" button.
+    if (!(_keyFlags & KEY_SELECT_MASK) && _gamepad->isButtonDown(Gamepad::BUTTON_MENU1))
+    {
+        _keyFlags |= KEY_SELECT_MASK;
+        if (_formSelect->getState() == Control::FOCUS)
+        {
+            _formSelect->setState(Control::NORMAL);
+        }
+        else if (_activeForm->getState() == Control::FOCUS)
+        {
+            _activeForm->setState(Control::NORMAL);
+            _formSelect->setState(Control::FOCUS);
+        }
+        else
+        {
+            _formSelect->setState(Control::FOCUS);
+        }
+    }
+    else if ((_keyFlags & KEY_SELECT_MASK) && !_gamepad->isButtonDown(Gamepad::BUTTON_MENU1))
+    {
+        _keyFlags &= ~KEY_SELECT_MASK;  
+    }
+
     if (_gamepad->isVirtual())
     {
         aDown |= _gamepad->isButtonDown(Gamepad::BUTTON_A);
@@ -375,8 +417,8 @@ void FormsSample::controlEvent(Control* control, EventType evt)
         control->createAnimationFromTo("opacityButton", Form::ANIMATE_OPACITY, from, to, Curve::LINEAR, 1000)->getClip()->play();
     }
 }
-
-void FormsSample::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
+
+void FormsSample::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
 {
     switch(evt)
     {
@@ -388,37 +430,5 @@ void FormsSample::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsi
         if (_gamepad && _gamepad->isVirtual())
             _gamepad->getForm()->setEnabled(true);
         break;
-    case Gamepad::BUTTON_EVENT:
-        if (_gamepad->isButtonDown(Gamepad::BUTTON_A))
-            _keyFlags |= KEY_A_MASK;
-        else
-            _keyFlags &= ~KEY_A_MASK;
-
-        if (_gamepad->isButtonDown(Gamepad::BUTTON_B))
-            _keyFlags |= KEY_B_MASK;
-        else
-            _keyFlags &= ~KEY_B_MASK;
-
-        // We'll use a physical gamepad's MENU1 button as the "back" button.
-        if (_gamepad->isButtonDown(Gamepad::BUTTON_MENU1))
-        {
-            if (_formSelect->getState() == Control::FOCUS)
-            {
-                _formSelect->setState(Control::NORMAL);
-            }
-            else if (_activeForm->getState() == Control::FOCUS)
-            {
-                _activeForm->setState(Control::NORMAL);
-                _formSelect->setState(Control::FOCUS);
-            }
-            else
-            {
-                _formSelect->setState(Control::FOCUS);
-            }
-        }
-        break;
-    case Gamepad::JOYSTICK_EVENT:
-        gamepad->getJoystickValues(analogIndex, &_joysticks[analogIndex]);
-        break;
     }
 }

+ 1 - 1
samples/browser/src/FormsSample.h

@@ -11,7 +11,7 @@ public:
     
     FormsSample();
 
-    void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex = 0);
+    void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad);
 
 protected:
 

+ 1 - 1
samples/character/src/CharacterGame.cpp

@@ -602,7 +602,7 @@ void CharacterGame::animationEvent(AnimationClip* clip, AnimationClip::Listener:
 
 void CharacterGame::clone()
 {
-    Node* clone = _scene->findNode("boyRotation")->clone();
+    Node* clone = _scene->findNode("boycharacter")->clone();
     Animation* cloneAnimation = clone->getAnimation();
 
     // Find the current clip and have the clone play that clip repeatedly.

+ 4 - 1
samples/particles/res/editor.form

@@ -10,6 +10,7 @@ form particleEditor
         layout = LAYOUT_VERTICAL
         position = 0, 0
         size = 160, 220
+        consumeInputEvents = true
 
         label title
         {
@@ -56,6 +57,7 @@ form particleEditor
         position = 0, 220
         layout = LAYOUT_VERTICAL
         size = 160, 210
+        consumeInputEvents = true
 
         // Burst emission
         button emit
@@ -108,6 +110,7 @@ form particleEditor
         style = noBorder
         size = 160, 50
         position = 0, 430
+        consumeInputEvents = true
 
         button zoomIn
         {
@@ -132,6 +135,7 @@ form particleEditor
         layout = LAYOUT_VERTICAL
         scroll = SCROLL_VERTICAL
         scrollBarsAutoHide = false
+        consumeInputEvents = true
 
         // Particle Size
         label titleSize
@@ -155,7 +159,6 @@ form particleEditor
             valueTextVisible = true
             valueTextAlignment = ALIGN_BOTTOM_HCENTER
             valueTextPrecision = 2
-            consumeInputEvents = false
         }
 
         slider startMax : startMin

+ 4 - 1
samples/racer/src/RacerGame.cpp

@@ -534,7 +534,10 @@ void RacerGame::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
                 _virtualGamepadClip->play();
             }
             _gamepad = _physicalGamepad;
-            _virtualGamepad->getForm()->setEnabled(false);
+			if (_virtualGamepad)
+			{
+				_virtualGamepad->getForm()->setEnabled(false);
+			}
         }
         else if (_virtualGamepad)
         {

+ 60 - 25
template/template-CMakeLists.txt

@@ -12,25 +12,52 @@ endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
 set(GAMEPLAY_SRC_PATH "GAMEPLAY_PATH") 
 set(GAMEPLAY_EXT_LIBS_PATH "${GAMEPLAY_SRC_PATH}/external-deps")
 
-set(TARGET_OS "LINUX")
-set(TARGET_OS_DIR "linux")
-
-set(GAME_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/bin/${TARGET_OS_DIR}")
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+    ADD_DEFINITIONS(-D__linux__)
+    SET(TARGET_OS "LINUX")
+    SET(TARGET_OS_DIR "linux")
+ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows")
+    IF(MSVC)
+        ADD_DEFINITIONS(-DMSVC)
+    ENDIF(MSVC)
+    ADD_DEFINITIONS(-DWIN32)
+    ADD_DEFINITIONS(-D_WINDOWS)
+    SET(TARGET_OS "WINDOWS")
+    SET(TARGET_OS_DIR "windows")
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+set(GAME_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin/${TARGET_OS_DIR}")
 
 macro (append_gameplay_lib listToAppend)
     set(libName gameplay)
-    find_library(FOUND_LIB_${libName} ${libName} HINTS
-        "${GAMEPLAY_SRC_PATH}/cmake/gameplay" "${GAMEPLAY_SRC_PATH}/build/gameplay" "${GAMEPLAY_SRC_PATH}/gameplay/src")
-    set(${listToAppend} ${${listToAppend}} ${FOUND_LIB_${libName}})
+    IF (TARGET_OS STREQUAL "WINDOWS")
+		FIND_LIBRARY(${libName}_LIBRARY_RELEASE
+			NAMES ${libName}
+			PATHS "${GAMEPLAY_SRC_PATH}/gameplay/${TARGET_OS_DIR}/${ARCH_DIR}/Release"
+		)
+
+		FIND_LIBRARY(${libName}_LIBRARY_DEBUG
+			NAMES ${libName}
+			PATHS "${GAMEPLAY_SRC_PATH}/gameplay/${TARGET_OS_DIR}/${ARCH_DIR}/Debug"
+		)
+		SET(FOUND_LIB_${libName}
+			debug ${${libName}_LIBRARY_DEBUG}
+			optimized ${${libName}_LIBRARY_RELEASE}
+		)
+	ELSE (TARGET_OS STREQUAL "WINDOWS")
+		find_library(FOUND_LIB_${libName} ${libName} HINTS
+			"${GAMEPLAY_SRC_PATH}/cmake/gameplay" "${GAMEPLAY_SRC_PATH}/build/gameplay" "${GAMEPLAY_SRC_PATH}/gameplay/src")
+	ENDIF (TARGET_OS STREQUAL "WINDOWS")
+	set(${listToAppend} ${${listToAppend}} ${FOUND_LIB_${libName}})
 endmacro(append_gameplay_lib)
 
 macro (append_gameplay_ext_lib listToAppend libName libDirName)
     IF("${libDirName}" STREQUAL "")
-        find_library(FOUND_LIB_${libName} ${libName})
+		find_library(FOUND_LIB_${libName} NAMES ${libName} ${ARGN})
     ELSE("${libDirName}" STREQUAL "")
         set(pathToSearch
             "${GAMEPLAY_EXT_LIBS_PATH}/${libDirName}/lib/${TARGET_OS_DIR}/${ARCH_DIR}")
-        find_library(FOUND_LIB_${libName} ${libName} HINTS ${pathToSearch})
+		find_library(FOUND_LIB_${libName} NAMES ${libName} ${ARGN} HINTS ${pathToSearch})
     ENDIF("${libDirName}" STREQUAL "")
 
     set(${listToAppend} ${${listToAppend}} ${FOUND_LIB_${libName}})
@@ -67,28 +94,35 @@ include_directories(
     ${GAMEPLAY_SRC_PATH}/external-deps/oggvorbis/include
     ${GAMEPLAY_SRC_PATH}/external-deps/zlib/include
     ${GAMEPLAY_SRC_PATH}/external-deps/openal/include
+	${GAMEPLAY_SRC_PATH}/external-deps/openal/include/AL
     ${GAMEPLAY_SRC_PATH}/external-deps/glew/include
 )
 
 append_gameplay_lib(GAMEPLAY_LIBRARIES)
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "m" "" )
+append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "GLEW" "glew" "glew32")
 append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "lua" "lua")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "png" "libpng")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "z" "zlib")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "vorbis" "oggvorbis")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "ogg" "oggvorbis")
+append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "png" "libpng" "libpng14")
 append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "BulletDynamics" "bullet")
 append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "BulletCollision" "bullet")
 append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "LinearMath" "bullet")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "openal" "openal")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "GLEW" "glew")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "GL" "")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "rt" "" )
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "dl" "")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "X11" "")
-append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "pthread" "" )
-
-add_definitions(-D__linux__)
+append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "openal" "openal" "openal32")
+append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "vorbis" "oggvorbis" "libvorbis")
+append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "ogg" "oggvorbis" "libogg")
+append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "z" "zlib" "zlib")
+
+IF (TARGET_OS STREQUAL "LINUX")
+	append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "GL" "")
+	append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "m" "" )
+	append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "X11" "")
+	append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "dl" "")
+	append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "rt" "" )
+	append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "pthread" "" )
+ELSEIF (TARGET_OS STREQUAL "WINDOWS")
+	set(GAMEPLAY_LIBRARIES ${GAMEPLAY_LIBRARIES} "OpenGL32")
+	set(GAMEPLAY_LIBRARIES ${GAMEPLAY_LIBRARIES} "GLU32")
+	append_gameplay_ext_lib(GAMEPLAY_LIBRARIES "vorbisfile" "oggvorbis" "libvorbisfile")
+	ADD_DEFINITIONS(-D_ITERATOR_DEBUG_LEVEL=0)
+ENDIF (TARGET_OS STREQUAL "LINUX")
 
 source_group(res FILES ${GAME_RES} ${GAMEPLAY_RES} ${GAME_RES_SHADERS} ${GAME_RES_SHADERS_LIB})
 source_group(src FILES ${GAME_SRC})
@@ -99,6 +133,7 @@ set(GAME_SRC
 )
 
 add_executable(${GAME_NAME}
+	WIN32
     ${GAME_SRC}
 )
 
@@ -113,5 +148,5 @@ set_target_properties(${GAME_NAME} PROPERTIES
 #TODO: Copy res files to the bin dir, it is done that way so we can make post
 #processing to the the res files in the future like zipping or preparation to
 #per platfom format.
-copy_files(CopyRes * "${CMAKE_SOURCE_DIR}/res" "${GAME_OUTPUT_DIR}/res" 1)
-copy_files(CopyConfig *.config "${CMAKE_SOURCE_DIR}" "${GAME_OUTPUT_DIR}" 0)
+copy_files(CopyRes * "${CMAKE_SOURCE_DIR}/res" "$<TARGET_FILE_DIR:${GAME_NAME}>/res" 1)
+copy_files(CopyConfig *.config "${CMAKE_SOURCE_DIR}" "$<TARGET_FILE_DIR:${GAME_NAME}>" 0)

+ 46 - 6
tools/encoder/src/FBXSceneEncoder.cpp

@@ -531,19 +531,59 @@ void FBXSceneEncoder::print(const char* str)
 void FBXSceneEncoder::transformNode(FbxNode* fbxNode, Node* node)
 {
     FbxAMatrix matrix;
+    float m[16];
+    
     if (fbxNode->GetCamera() || fbxNode->GetLight())
     {
-        // TODO: Why is this necessary for Camera and Light?
-        matrix.SetTRS(fbxNode->LclTranslation.Get(), fbxNode->LclRotation.Get(), fbxNode->LclScaling.Get());
+        FbxAMatrix rotateAdjust;
+        
+        if(fbxNode->GetLight())
+        {
+            /*
+             * according to the fbx-documentation the light's forward vector
+             * points along a node's negative Y axis.
+             * so we have to rotate it by 90° around the X-axis to correct it.
+             */
+            if(fbxNode->RotationActive.Get())
+            {
+                const FbxVector4& postRotation = fbxNode->PostRotation.Get();
+                fbxNode->SetPostRotation(FbxNode::eSourcePivot, FbxVector4(postRotation.mData[0] + 90.0,
+                                                                           postRotation.mData[1],
+                                                                           postRotation.mData[2])
+                                         );
+            }
+            else
+            {
+                // if the rotation is deactivated we have to rotate it anyway to get the correct transformation in the end
+                rotateAdjust.SetR(FbxVector4(-90.0, 0.0, 0.0));
+            }
+            
+            matrix = fbxNode->EvaluateLocalTransform() * rotateAdjust;
+        }
+        else if(fbxNode->GetCamera())
+        {
+            // TODO: use the EvaluateLocalTransform() function for the transformations for the camera
+            /*
+             * the current implementation ignores pre- and postrotation among others (usually happens with fbx-export from blender)
+             *
+             * Some info for a future implementation:
+             * according to the fbx-documentation the camera's forward vector
+             * points along a node's positive X axis.
+             * so we have to correct it if we use the EvaluateLocalTransform-function
+             * just rotating it by 90° around the Y axis (similar to above) doesn't work
+             */
+            matrix.SetTRS(fbxNode->LclTranslation.Get(), fbxNode->LclRotation.Get(), fbxNode->LclScaling.Get());
+        }
+        
+        copyMatrix(matrix, m);
+        node->setTransformMatrix(m);
     }
     else
     {
         matrix = fbxNode->EvaluateLocalTransform();
+        copyMatrix(matrix, m);
+        node->setTransformMatrix(m);
     }
-
-    float m[16];
-    copyMatrix(matrix, m);
-    node->setTransformMatrix(m);
 }
 
 Material* FBXSceneEncoder::getBaseMaterial(const char* id)

+ 122 - 54
tools/luagen/gameplay-luagen.doxyfile

@@ -1,4 +1,4 @@
-# Doxyfile 1.8.0
+# Doxyfile 1.8.3.1
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project
@@ -136,7 +136,9 @@ FULL_PATH_NAMES        = YES
 # only done if one of the specified strings matches the left-hand part of 
 # the path. The tag can be used to show relative paths in the file list. 
 # If left blank the directory from which doxygen is run is used as the 
-# path to strip.
+# path to strip. Note that you specify absolute paths here, but also 
+# relative paths, which will be relative from the directory where doxygen is 
+# started.
 
 STRIP_FROM_PATH        = 
 
@@ -239,14 +241,15 @@ OPTIMIZE_FOR_FORTRAN   = NO
 OPTIMIZE_OUTPUT_VHDL   = NO
 
 # Doxygen selects the parser to use depending on the extension of the files it 
-# parses. With this tag you can assign which parser to use for a given extension. 
-# Doxygen has a built-in mapping, but you can override or extend it using this 
-# tag. The format is ext=language, where ext is a file extension, and language 
-# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, 
-# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make 
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C 
-# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions 
-# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+# parses. With this tag you can assign which parser to use for a given 
+# extension. Doxygen has a built-in mapping, but you can override or extend it 
+# using this tag. The format is ext=language, where ext is a file extension, 
+# and language is one of the parsers supported by doxygen: IDL, Java, 
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, 
+# C++. For instance to make doxygen treat .inc files as Fortran files (default 
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note 
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the 
+# files are not read by doxygen.
 
 EXTENSION_MAPPING      = 
 
@@ -259,6 +262,13 @@ EXTENSION_MAPPING      =
 
 MARKDOWN_SUPPORT       = YES
 
+# When enabled doxygen tries to link words that correspond to documented classes, 
+# or namespaces to their corresponding documentation. Such a link can be 
+# prevented in individual cases by by putting a % sign in front of the word or 
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT       = YES
+
 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
 # to include (a tag file for) the STL sources as input, then you should 
 # set this tag to YES in order to let doxygen match functions declarations and 
@@ -279,10 +289,10 @@ CPP_CLI_SUPPORT        = NO
 
 SIP_SUPPORT            = NO
 
-# For Microsoft's IDL there are propget and propput attributes to indicate getter 
-# and setter methods for a property. Setting this option to YES (the default) 
-# will make doxygen replace the get and set methods by a property in the 
-# documentation. This will only work if the methods are indeed getting or 
+# For Microsoft's IDL there are propget and propput attributes to indicate 
+# getter and setter methods for a property. Setting this option to YES (the 
+# default) will make doxygen replace the get and set methods by a property in 
+# the documentation. This will only work if the methods are indeed getting or 
 # setting a simple type. If this is not the case, or you want to show the 
 # methods anyway, you should set this option to NO.
 
@@ -372,7 +382,7 @@ EXTRACT_ALL            = NO
 
 EXTRACT_PRIVATE        = NO
 
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal 
 # scope will be included in the documentation.
 
 EXTRACT_PACKAGE        = NO
@@ -544,7 +554,8 @@ GENERATE_BUGLIST       = YES
 GENERATE_DEPRECATEDLIST= YES
 
 # The ENABLED_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif.
+# documentation sections, marked by \if section-label ... \endif 
+# and \cond section-label ... \endcond blocks.
 
 ENABLED_SECTIONS       = 
 
@@ -564,12 +575,6 @@ MAX_INITIALIZER_LINES  = 30
 
 SHOW_USED_FILES        = NO
 
-# If the sources in your project are distributed over multiple directories 
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES       = NO
-
 # Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
 # This will remove the Files entry from the Quick Index and from the 
 # Folder Tree View (if specified). The default is YES.
@@ -594,7 +599,7 @@ FILE_VERSION_FILTER    =
 
 # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed 
 # by doxygen. The layout file controls the global structure of the generated 
-# output files in an output format independent way. The create the layout file 
+# output files in an output format independent way. To create the layout file 
 # that represents doxygen's defaults, run doxygen with the -l option. 
 # You can optionally specify a file name after the option, if omitted 
 # DoxygenLayout.xml will be used as the name of the layout file.
@@ -607,7 +612,8 @@ LAYOUT_FILE            =
 # requires the bibtex tool to be installed. See also 
 # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style 
 # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this 
-# feature you need bibtex and perl available in the search path.
+# feature you need bibtex and perl available in the search path. Do not use 
+# file names with spaces, bibtex cannot handle them.
 
 CITE_BIB_FILES         = 
 
@@ -671,7 +677,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = ../gameplay/src
+INPUT                  = ../../gameplay/src
 
 # This tag can be used to specify the character encoding of the source files 
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
@@ -787,6 +793,13 @@ FILTER_SOURCE_FILES    = NO
 
 FILTER_SOURCE_PATTERNS = 
 
+# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that 
+# is part of the input, its contents will be placed on the main page (index.html). 
+# This can be useful if you have a project on for instance GitHub and want reuse 
+# the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = 
+
 #---------------------------------------------------------------------------
 # configuration options related to source browsing
 #---------------------------------------------------------------------------
@@ -805,7 +818,7 @@ INLINE_SOURCES         = NO
 
 # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
 # doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible.
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
 
 STRIP_CODE_COMMENTS    = YES
 
@@ -907,13 +920,23 @@ HTML_FOOTER            =
 
 # The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
 # style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
-# style sheet in the HTML output directory as well, or it will be erased!
+# fine-tune the look of the HTML output. If left blank doxygen will 
+# generate a default style sheet. Note that it is recommended to use 
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this 
+# tag will in the future become obsolete.
 
 HTML_STYLESHEET        = 
 
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional 
+# user-defined cascading style sheet that is included after the standard 
+# style sheets created by doxygen. Using this option one can overrule 
+# certain style aspects. This is preferred over using HTML_STYLESHEET 
+# since it does not replace the standard style sheet and is therefor more 
+# robust against future updates. Doxygen will copy the style sheet file to 
+# the output directory.
+
+HTML_EXTRA_STYLESHEET  = 
+
 # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or 
 # other source files which should be copied to the HTML output directory. Note 
 # that these files will be copied to the base HTML output directory. Use the 
@@ -954,20 +977,23 @@ HTML_COLORSTYLE_GAMMA  = 80
 
 HTML_TIMESTAMP         = YES
 
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS     = YES
-
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
 # documentation will contain sections that can be hidden and shown after the 
-# page has loaded. For this to work a browser that supports 
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+# page has loaded.
 
 HTML_DYNAMIC_SECTIONS  = NO
 
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of 
+# entries shown in the various tree structured indices initially; the user 
+# can expand and collapse entries dynamically later on. Doxygen will expand 
+# the tree to such a level that at most the specified number of entries are 
+# visible (unless a fully collapsed tree already exceeds this amount). 
+# So setting the number of entries 1 will produce a full collapsed tree by 
+# default. 0 is a special value representing an infinite number of entries 
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
 # If the GENERATE_DOCSET tag is set to YES, additional index files 
 # will be generated that can be used as input for Apple's Xcode 3 
 # integrated development environment, introduced with OSX 10.5 (Leopard). 
@@ -995,9 +1021,9 @@ DOCSET_FEEDNAME        = "Doxygen generated docs"
 
 DOCSET_BUNDLE_ID       = org.doxygen.Project
 
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify 
-# the documentation publisher. This should be a reverse domain-name style 
-# string, e.g. com.mycompany.MyDocSet.documentation.
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely 
+# identify the documentation publisher. This should be a reverse domain-name 
+# style string, e.g. com.mycompany.MyDocSet.documentation.
 
 DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
 
@@ -1146,11 +1172,6 @@ GENERATE_TREEVIEW      = NO
 
 ENUM_VALUES_PER_LINE   = 4
 
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES       = NO
-
 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
 # used to set the initial width (in pixels) of the frame in which the tree 
 # is shown.
@@ -1187,6 +1208,13 @@ FORMULA_TRANSPARENT    = YES
 
 USE_MATHJAX            = NO
 
+# When MathJax is enabled you can set the default output format to be used for 
+# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and 
+# SVG. The default value is HTML-CSS, which is slower, but has the best 
+# compatibility.
+
+MATHJAX_FORMAT         = HTML-CSS
+
 # When MathJax is enabled you need to specify the location relative to the 
 # HTML output directory using the MATHJAX_RELPATH option. The destination 
 # directory should contain the MathJax.js script. For instance, if the mathjax 
@@ -1214,15 +1242,55 @@ MATHJAX_EXTENSIONS     =
 SEARCHENGINE           = YES
 
 # When the SERVER_BASED_SEARCH tag is enabled the search engine will be 
-# implemented using a PHP enabled web server instead of at the web client 
-# using Javascript. Doxygen will generate the search PHP script and index 
-# file to put on the web server. The advantage of the server 
-# based approach is that it scales better to large projects and allows 
-# full text search. The disadvantages are that it is more difficult to setup 
-# and does not have live searching capabilities.
+# implemented using a web server instead of a web client using Javascript. 
+# There are two flavours of web server based search depending on the 
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for 
+# searching and an index file used by the script. When EXTERNAL_SEARCH is 
+# enabled the indexing and searching needs to be provided by external tools. 
+# See the manual for details.
 
 SERVER_BASED_SEARCH    = NO
 
+# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP 
+# script for searching. Instead the search results are written to an XML file 
+# which needs to be processed by an external indexer. Doxygen will invoke an 
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain 
+# the search results. Doxygen ships with an example indexer (doxyindexer) and 
+# search engine (doxysearch.cgi) which are based on the open source search engine 
+# library Xapian. See the manual for configuration details.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server 
+# which will returned the search results when EXTERNAL_SEARCH is enabled. 
+# Doxygen ships with an example search engine (doxysearch) which is based on 
+# the open source search engine library Xapian. See the manual for configuration 
+# details.
+
+SEARCHENGINE_URL       = 
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed 
+# search data is written to a file for indexing by an external tool. With the 
+# SEARCHDATA_FILE tag the name of this file can be specified.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the 
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is 
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple 
+# projects and redirect the results back to the right project.
+
+EXTERNAL_SEARCH_ID     = 
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen 
+# projects other than the one defined by this configuration file, but that are 
+# all added to the same external search index. Each project needs to have a 
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id 
+# of to a relative location where the documentation can be found. 
+# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
+
+EXTRA_SEARCH_MAPPINGS  = 
+
 #---------------------------------------------------------------------------
 # configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
@@ -1713,7 +1781,7 @@ CALLER_GRAPH           = NO
 
 GRAPHICAL_HIERARCHY    = YES
 
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES 
 # then doxygen will show the dependencies a directory has on other directories 
 # in a graphical way. The dependency relations are determined by the #include 
 # relations between the files in the directories.