Przeglądaj źródła

Big changes to the Gamepad class.
Adding gamepad support to BB10.
Updating the gamepad support in Win32 to work with the new Gamepad API.
Modifying various tests and samples that make use of gamepads so they continue to work.
Adds a little fix to the Lua generator for when Doxygen doesn't put an includeElement in a file's XML.
Clamps a percentage in AnimationClip that was causing crashes when animations were triggered while an app was minimized (e.g. when RacerGame::GamepadEvent was called while on the Bluetooth settings screen in BB10).

Adam Blake 13 lat temu
rodzic
commit
979c8e2e9d
41 zmienionych plików z 1162 dodań i 1721 usunięć
  1. 5 0
      gameplay-luagen/src/Generator.cpp
  2. 9 7
      gameplay/.cproject
  3. 11 5
      gameplay/gameplay.vcxproj
  4. 18 6
      gameplay/gameplay.vcxproj.filters
  5. 2 0
      gameplay/src/AnimationClip.cpp
  6. 11 1
      gameplay/src/Base.h
  7. 5 0
      gameplay/src/Container.cpp
  8. 1 1
      gameplay/src/Font.cpp
  9. 17 42
      gameplay/src/Game.cpp
  10. 0 41
      gameplay/src/Game.h
  11. 0 20
      gameplay/src/Game.inl
  12. 222 96
      gameplay/src/Gamepad.cpp
  13. 129 50
      gameplay/src/Gamepad.h
  14. 45 0
      gameplay/src/GamepadButton.cpp
  15. 43 0
      gameplay/src/GamepadButton.h
  16. 1 0
      gameplay/src/Joystick.cpp
  17. 3 0
      gameplay/src/Joystick.h
  18. 5 0
      gameplay/src/Joystick.inl
  19. 1 100
      gameplay/src/Platform.h
  20. 1 56
      gameplay/src/PlatformAndroid.cpp
  21. 195 59
      gameplay/src/PlatformBlackBerry.cpp
  22. 1 132
      gameplay/src/PlatformMacOSX.mm
  23. 108 312
      gameplay/src/PlatformWindows.cpp
  24. 1 57
      gameplay/src/PlatformiOS.mm
  25. 1 0
      gameplay/src/gameplay.h
  26. 1 0
      gameplay/src/lua/lua_Container.cpp
  27. 1 0
      gameplay/src/lua/lua_Form.cpp
  28. 0 121
      gameplay/src/lua/lua_Game.cpp
  29. 0 3
      gameplay/src/lua/lua_Game.h
  30. 205 63
      gameplay/src/lua/lua_Gamepad.cpp
  31. 9 5
      gameplay/src/lua/lua_Gamepad.h
  32. 0 33
      gameplay/src/lua/lua_GamepadButtonState.cpp
  33. 0 15
      gameplay/src/lua/lua_GamepadButtonState.h
  34. 29 5
      gameplay/src/lua/lua_Global.cpp
  35. 1 1
      gameplay/src/lua/lua_Global.h
  36. 36 0
      gameplay/src/lua/lua_Joystick.cpp
  37. 1 0
      gameplay/src/lua/lua_Joystick.h
  38. 41 478
      gameplay/src/lua/lua_Platform.cpp
  39. 1 12
      gameplay/src/lua/lua_Platform.h
  40. 1 0
      gameplay/src/lua/lua_all_bindings.cpp
  41. 1 0
      gameplay/src/lua/lua_all_bindings.h

+ 5 - 0
gameplay-luagen/src/Generator.cpp

@@ -443,6 +443,11 @@ void Generator::getClass(XMLElement* classNode, const string& name)
             if (_classes.find(parentClassName) != _classes.end())
                 classBinding.include = _classes[parentClassName].include;
         }
+        else
+        {
+            // Attempt to guess the name of the header.
+            classBinding.include = classBinding.classname + ".h";
+        }
     }
 
     // Track whether the class has any pure virtual functions.

+ 9 - 7
gameplay/.cproject

@@ -20,9 +20,10 @@
 							<builder buildPath="${workspace_loc:/gameplay/Device-Debug}" id="org.eclipse.cdt.build.core.internal.builder.159190287" keepEnvironmentInBuildfile="false" name="CDT Internal Builder" superClass="org.eclipse.cdt.build.core.internal.builder"/>
 							<tool id="com.qnx.qcc.tool.compiler.96907942" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
 								<option id="com.qnx.qcc.option.compile.debug.1765481355" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/>
-								<option id="com.qnx.qcc.option.compiler.security.311918799" name="Enhanced Security (-fstack-protector-all)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.security.311918799" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.defines.1481323494" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
+									<listOptionValue builtIn="false" value="__BB10__"/>
 									<listOptionValue builtIn="false" value="BT_USE_NEON"/>
 								</option>
 								<option id="com.qnx.qcc.option.compiler.includePath.2133604142" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath">
@@ -42,6 +43,7 @@
 							</tool>
 							<tool id="com.qnx.qcc.tool.assembler.1988140188" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler">
 								<option id="com.qnx.qcc.option.assembler.debug.1929307156" name="Debug (-g)" superClass="com.qnx.qcc.option.assembler.debug" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.assembler.defines.1866459653" name="Defines (-D)" superClass="com.qnx.qcc.option.assembler.defines" valueType="definedSymbols"/>
 								<inputType id="com.qnx.qcc.inputType.assembler.1944074393" superClass="com.qnx.qcc.inputType.assembler"/>
 							</tool>
 							<tool id="com.qnx.qcc.tool.linker.85592747" name="QCC Linker" superClass="com.qnx.qcc.tool.linker">
@@ -82,7 +84,7 @@
 							<builder buildPath="${workspace_loc:/gameplay/Device-Release}" id="cdt.managedbuild.target.gnu.builder.base.1199322737" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
 							<tool id="com.qnx.qcc.tool.compiler.1345567866" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
 								<option id="com.qnx.qcc.option.compiler.optlevel.1056793982" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.1" valueType="enumerated"/>
-								<option id="com.qnx.qcc.option.compiler.security.324540233" name="Enhanced Security (-fstack-protector-all)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.security.324540233" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.defines.398688299" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
 									<listOptionValue builtIn="false" value="BT_USE_NEON"/>
@@ -143,7 +145,7 @@
 							<tool id="com.qnx.qcc.tool.compiler.1281156842" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
 								<option id="com.qnx.qcc.option.compile.debug.626405189" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.profile2.1207899085" name="Build for Profiling (Function Instrumentation) (-finstrument-functions)" superClass="com.qnx.qcc.option.compiler.profile2" value="true" valueType="boolean"/>
-								<option id="com.qnx.qcc.option.compiler.security.1649809766" name="Enhanced Security (-fstack-protector-all)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.security.1649809766" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.defines.276653249" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
 									<listOptionValue builtIn="false" value="BY_USE_NEON"/>
@@ -207,7 +209,7 @@
 							<tool id="com.qnx.qcc.tool.compiler.306557636" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
 								<option id="com.qnx.qcc.option.compile.debug.168813234" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.coverage.1032644527" name="Build for Code Coverage (-Wc,-ftest-coverage -Wc,-fprofile-arcs)" superClass="com.qnx.qcc.option.compiler.coverage" value="true" valueType="boolean"/>
-								<option id="com.qnx.qcc.option.compiler.security.1227516972" name="Enhanced Security (-fstack-protector-all)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.security.1227516972" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.defines.374283024" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
 									<listOptionValue builtIn="false" value="BT_USE_NEON"/>
@@ -269,7 +271,7 @@
 							<builder buildPath="${workspace_loc:/gameplay/Simulator}" id="cdt.managedbuild.target.gnu.builder.base.10075032" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
 							<tool id="com.qnx.qcc.tool.compiler.1004416224" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
 								<option id="com.qnx.qcc.option.compile.debug.1122485646" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/>
-								<option id="com.qnx.qcc.option.compiler.security.1671403331" name="Enhanced Security (-fstack-protector-all)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.security.1671403331" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.defines.1863269886" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
 								</option>
@@ -328,7 +330,7 @@
 							<tool id="com.qnx.qcc.tool.compiler.417488704" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
 								<option id="com.qnx.qcc.option.compile.debug.1290366598" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.profile2.216911941" name="Build for Profiling (Function Instrumentation) (-finstrument-functions)" superClass="com.qnx.qcc.option.compiler.profile2" value="true" valueType="boolean"/>
-								<option id="com.qnx.qcc.option.compiler.security.1329750381" name="Enhanced Security (-fstack-protector-all)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.security.1329750381" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.defines.1679396285" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
 								</option>
@@ -388,7 +390,7 @@
 							<tool id="com.qnx.qcc.tool.compiler.563072865" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler">
 								<option id="com.qnx.qcc.option.compile.debug.1789973550" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.coverage.1289221781" name="Build for Code Coverage (-Wc,-ftest-coverage -Wc,-fprofile-arcs)" superClass="com.qnx.qcc.option.compiler.coverage" value="true" valueType="boolean"/>
-								<option id="com.qnx.qcc.option.compiler.security.1296061040" name="Enhanced Security (-fstack-protector-all)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
+								<option id="com.qnx.qcc.option.compiler.security.1296061040" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/>
 								<option id="com.qnx.qcc.option.compiler.defines.1925901823" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols">
 									<listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/>
 								</option>

+ 11 - 5
gameplay/gameplay.vcxproj

@@ -85,6 +85,7 @@
     <ClCompile Include="src\Frustum.cpp" />
     <ClCompile Include="src\Game.cpp" />
     <ClCompile Include="src\Gamepad.cpp" />
+    <ClCompile Include="src\GamepadButton.cpp" />
     <ClCompile Include="src\gameplay-main-android.cpp" />
     <ClCompile Include="src\gameplay-main-blackberry.cpp" />
     <ClCompile Include="src\gameplay-main-linux.cpp" />
@@ -149,7 +150,8 @@
     <ClCompile Include="src\lua\lua_Game.cpp" />
     <ClCompile Include="src\lua\lua_GameClearFlags.cpp" />
     <ClCompile Include="src\lua\lua_Gamepad.cpp" />
-    <ClCompile Include="src\lua\lua_GamepadButtonState.cpp" />
+    <ClCompile Include="src\lua\lua_GamepadButton.cpp" />
+    <ClCompile Include="src\lua\lua_GamepadButtonMapping.cpp" />
     <ClCompile Include="src\lua\lua_GamepadGamepadEvent.cpp" />
     <ClCompile Include="src\lua\lua_GameState.cpp" />
     <ClCompile Include="src\lua\lua_Gesture.cpp" />
@@ -355,6 +357,7 @@
     <ClInclude Include="src\Frustum.h" />
     <ClInclude Include="src\Game.h" />
     <ClInclude Include="src\Gamepad.h" />
+    <ClInclude Include="src\GamepadButton.h" />
     <ClInclude Include="src\gameplay.h" />
     <ClInclude Include="src\Gesture.h" />
     <ClInclude Include="src\Image.h" />
@@ -418,7 +421,8 @@
     <ClInclude Include="src\lua\lua_Game.h" />
     <ClInclude Include="src\lua\lua_GameClearFlags.h" />
     <ClInclude Include="src\lua\lua_Gamepad.h" />
-    <ClInclude Include="src\lua\lua_GamepadButtonState.h" />
+    <ClInclude Include="src\lua\lua_GamepadButton.h" />
+    <ClInclude Include="src\lua\lua_GamepadButtonMapping.h" />
     <ClInclude Include="src\lua\lua_GamepadGamepadEvent.h" />
     <ClInclude Include="src\lua\lua_GameState.h" />
     <ClInclude Include="src\lua\lua_Gesture.h" />
@@ -871,7 +875,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>__BB10__;_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>
@@ -906,7 +910,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_XINPUT;_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(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>true</RuntimeTypeInfo>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -918,6 +922,8 @@
     <Lib>
       <Verbose>
       </Verbose>
+      <AdditionalDependencies>XInput.lib</AdditionalDependencies>
+      <AdditionalLibraryDirectories>C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86</AdditionalLibraryDirectories>
     </Lib>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugMem|x64'">
@@ -946,7 +952,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>__BB10__;_ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;GAMEPLAY_MEM_LEAK_DETECTION;%(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>true</RuntimeTypeInfo>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>

+ 18 - 6
gameplay/gameplay.vcxproj.filters

@@ -660,9 +660,6 @@
     <ClCompile Include="src\lua\lua_GameClearFlags.cpp">
       <Filter>lua</Filter>
     </ClCompile>
-    <ClCompile Include="src\lua\lua_GamepadButtonState.cpp">
-      <Filter>lua</Filter>
-    </ClCompile>
     <ClCompile Include="src\lua\lua_GamepadGamepadEvent.cpp">
       <Filter>lua</Filter>
     </ClCompile>
@@ -819,6 +816,15 @@
     <ClCompile Include="src\lua\lua_Logger.cpp">
       <Filter>lua</Filter>
     </ClCompile>
+    <ClCompile Include="src\lua\lua_GamepadButton.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
+    <ClCompile Include="src\lua\lua_GamepadButtonMapping.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
+    <ClCompile Include="src\GamepadButton.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -1469,9 +1475,6 @@
     <ClInclude Include="src\lua\lua_GameClearFlags.h">
       <Filter>lua</Filter>
     </ClInclude>
-    <ClInclude Include="src\lua\lua_GamepadButtonState.h">
-      <Filter>lua</Filter>
-    </ClInclude>
     <ClInclude Include="src\lua\lua_GamepadGamepadEvent.h">
       <Filter>lua</Filter>
     </ClInclude>
@@ -1625,6 +1628,15 @@
     <ClInclude Include="src\Stream.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="src\lua\lua_GamepadButton.h">
+      <Filter>lua</Filter>
+    </ClInclude>
+    <ClInclude Include="src\lua\lua_GamepadButtonMapping.h">
+      <Filter>lua</Filter>
+    </ClInclude>
+    <ClInclude Include="src\GamepadButton.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="src\Game.inl">

+ 2 - 0
gameplay/src/AnimationClip.cpp

@@ -449,6 +449,8 @@ bool AnimationClip::update(float elapsedTime)
     // then prevent a divide by zero and set percentComplete = 1.
     float percentComplete = _animation->_duration == 0 ? 1 : ((float)_startTime + currentTime) / (float)_animation->_duration;
     
+    percentComplete = MATH_CLAMP(percentComplete, 0.0f, 1.0f);
+
     if (isClipStateBitSet(CLIP_IS_FADING_OUT_BIT))
     {
         GP_ASSERT(_crossFadeToClip);

+ 11 - 1
gameplay/src/Base.h

@@ -187,9 +187,10 @@ using std::va_list;
 
 // Graphics (OpenGL)
 #ifdef __QNX__
-#include <EGL/egl.h>
+    #include <EGL/egl.h>
     #include <GLES2/gl2.h>
     #include <GLES2/gl2ext.h>
+    #include <screen/screen.h>
     extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray;
     extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
     extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays;
@@ -275,6 +276,15 @@ typedef GLuint TextureHandle;
 typedef GLuint FrameBufferHandle;
 /** Render buffer handle. */
 typedef GLuint RenderBufferHandle;
+
+/** Gamepad handle definitions vary by platform. */
+#ifdef __QNX__
+    typedef screen_device_t GamepadHandle;
+#elif USE_XINPUT
+    typedef unsigned long GamepadHandle;
+#else
+    typedef unsigned int GamepadHandle;
+#endif
 }
 
 /**

+ 5 - 0
gameplay/src/Container.cpp

@@ -6,6 +6,7 @@
 #include "VerticalLayout.h"
 #include "Label.h"
 #include "Button.h"
+#include "GamepadButton.h"
 #include "CheckBox.h"
 #include "RadioButton.h"
 #include "Slider.h"
@@ -141,6 +142,10 @@ void Container::addControls(Theme* theme, Properties* properties)
         {
             control = Button::create(controlStyle, controlSpace);
         }
+        else if (controlName == "GAMEPADBUTTON")
+        {
+            control = GamepadButton::create(controlStyle, controlSpace);
+        }
         else if (controlName == "CHECKBOX")
         {
             control = CheckBox::create(controlStyle, controlSpace);

+ 1 - 1
gameplay/src/Font.cpp

@@ -401,7 +401,7 @@ Font::Text* Font::createText(const char* text, const Rectangle& area, const Vect
                 size_t tokenLength = strcspn(token, "\n");
 
                 if (tokenLength > 0)
-                {                
+                {
                     // Get first token of next line.
                     token += tokenLength;
                 }

+ 17 - 42
gameplay/src/Game.cpp

@@ -24,11 +24,10 @@ Game::Game()
       _clearDepth(1.0f), _clearStencil(0), _properties(NULL),
       _animationController(NULL), _audioController(NULL),
       _physicsController(NULL), _aiController(NULL), _audioListener(NULL),
-      _gamepads(NULL), _timeEvents(NULL), _scriptController(NULL), _scriptListeners(NULL)
+      _timeEvents(NULL), _scriptController(NULL), _scriptListeners(NULL)
 {
     GP_ASSERT(__gameInstance == NULL);
     __gameInstance = this;
-    _gamepads = new std::vector<Gamepad*>;
     _timeEvents = new std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >();
 }
 
@@ -112,9 +111,6 @@ bool Game::startup()
     RenderState::initialize();
     FrameBuffer::initialize();
 
-    // Load any gamepads, ui or physical.
-    loadGamepads();
-
     _animationController = new AnimationController();
     _animationController->initialize();
 
@@ -130,6 +126,9 @@ bool Game::startup()
     _scriptController = new ScriptController();
     _scriptController->initialize();
 
+    // Load any gamepads, ui or physical.
+    loadGamepads();
+
     // Set the script callback functions.
     if (_properties)
     {
@@ -183,16 +182,17 @@ void Game::shutdown()
         Platform::signalShutdown();
         finalize();
 
-
-        std::vector<Gamepad*>::iterator itr = _gamepads->begin();
-        std::vector<Gamepad*>::iterator end = _gamepads->end();
-        while (itr != end)
+        std::vector<Gamepad*>* gamepads = Gamepad::getGamepads();
+        std::vector<Gamepad*>::iterator it = gamepads->begin();
+        do
         {
-            SAFE_DELETE(*itr);
-            itr++;
-        }
-        _gamepads->clear();
-        SAFE_DELETE(_gamepads);
+            Gamepad* g = *it;
+            if (g)
+            {
+                SAFE_DELETE(g);
+                it = gamepads->erase(it);
+            }
+        } while (it != gamepads->end());
 
         _scriptController->finalizeGame();
 
@@ -273,7 +273,6 @@ void Game::frame()
         initialize();
         _scriptController->initializeGame();
         _initialized = true;
-        triggerGamepadEvents(); // Now that the game has been initialized, trigger any gamepad attached events.
     }
 
     if (_state == Game::RUNNING)
@@ -576,41 +575,17 @@ void Game::loadGamepads()
     // Load virtual gamepads.
     if (_properties)
     {
-        // Check if there is a virtual keyboard included in the .config file.
-        // If there is, try to create it and assign it to "player one".
+        // Check if there are any virtual gamepads included in the .config file.
+        // If there are, create and initialize them.
         Properties* gamepadProperties = _properties->getNamespace("gamepads", true);
-        unsigned int gamepadCount = 0;
         if (gamepadProperties && gamepadProperties->exists("form"))
         {
             const char* gamepadFormPath = gamepadProperties->getString("form");
             GP_ASSERT(gamepadFormPath);
-            Gamepad* gamepad = new Gamepad(gamepadCount, gamepadFormPath);
+            Gamepad* gamepad = Gamepad::add(gamepadFormPath);
             GP_ASSERT(gamepad);
-
-            _gamepads->push_back(gamepad);
-            gamepadCount++;
         }
     }
-
-    // Checks for any physical gamepads
-    getGamepadCount();
-}
-
-unsigned int Game::createGamepad(const char* id, unsigned int handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount)
-{
-    Gamepad* gamepad = new Gamepad(id, handle, buttonCount, joystickCount, triggerCount);
-    GP_ASSERT(gamepad);
-    _gamepads->push_back(gamepad);
-    return (unsigned int)(_gamepads->size() - 1);
-}
-
-void Game::triggerGamepadEvents()
-{
-    for (std::vector<Gamepad*>::iterator itr = _gamepads->begin(); itr != _gamepads->end(); itr++)
-    {
-        if ((*itr)->isConnected())
-            gamepadEvent(Gamepad::CONNECTED_EVENT, (*itr));
-    }
 }
 
 }

+ 0 - 41
gameplay/src/Game.h

@@ -440,28 +440,6 @@ public:
      */
     virtual void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad);
 
-    /**
-     * Gets the number of gamepad's that can be used in the game. Includes gamepads not connected.
-     * 
-     * @return The number of gamepad's that can be used in the game.
-     */
-    inline unsigned int getGamepadCount() const;
-
-    /**
-     * Gets the number of physical gamepad's attached/connected to the game.
-     * Can be called to detects if any gamepads have been attached or detached.
-     * 
-     * @return The number of gamepads attached to the Platform.
-     */
-    inline unsigned int getGamepadsConnected();
-
-    /**
-     * Gets the gamepad at the specified index.
-     *
-     * @param index The index to get the gamepad for: 0 <= index <= Game::getGamepadCount()
-     */
-    inline Gamepad* getGamepad(unsigned int index) const;
-
     /**
      * Sets multi-touch is to be enabled/disabled. Default is disabled.
      *
@@ -654,24 +632,6 @@ private:
      */
     void loadGamepads();
 
-    /** 
-     * Creates a Gamepad object from a .form file.
-     *
-     * @param gamepadId The gamepad id (typically equal to the corresponding player's number).
-     * @param gamepadFormPath The path to the .form file.
-     */
-    Gamepad* createGamepad(const char* gamepadId, const char* gamepadFormPath);
-
-    /**
-     * Creates a Gamepad object for a physical gamepad.
-     */
-    unsigned int createGamepad(const char* id, unsigned int handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount);
-
-    /**
-     * Triggers any Gamepad::CONNECTED_EVENTS after initialization.
-     */
-    void triggerGamepadEvents();
-
     bool _initialized;                          // If game has initialized yet.
     State _state;                               // The game state.
     unsigned int _pausedCount;                  // Number of times pause() has been called.
@@ -692,7 +652,6 @@ private:
     PhysicsController* _physicsController;      // Controls the simulation of a physics scene and entities.
     AIController* _aiController;                // Controls AI simulation.
     AudioListener* _audioListener;              // The audio listener in 3D space.
-    std::vector<Gamepad*>* _gamepads;           // The connected gamepads.
     std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >* _timeEvents;     // Contains the scheduled time events.
     ScriptController* _scriptController;            // Controls the scripting engine.
     std::vector<ScriptListener*>* _scriptListeners; // Lua script listeners.

+ 0 - 20
gameplay/src/Game.inl

@@ -121,26 +121,6 @@ inline void Game::displayKeyboard(bool display)
     Platform::displayKeyboard(display);
 }
 
-inline unsigned int Game::getGamepadCount() const
-{
-    return (unsigned int)_gamepads->size();
-}
-
-inline unsigned int Game::getGamepadsConnected()
-{
-    return Platform::getGamepadsConnected();
-}
-
-inline Gamepad* Game::getGamepad(unsigned int index) const
-{
-    GP_ASSERT(index < _gamepads->size());
-
-    if (!_gamepads->empty())
-        return _gamepads->at(index);
-    else
-        return NULL;
-}
-
 inline bool Game::launchURL(const char* url) const
 {
     return Platform::launchURL(url);

+ 222 - 96
gameplay/src/Gamepad.cpp

@@ -1,30 +1,101 @@
 #include "Base.h"
 #include "Gamepad.h"
 #include "Game.h"
+#include "GamepadButton.h"
 
 namespace gameplay
 {
 
-Gamepad::Gamepad(unsigned int handle, const char* formPath)
-    : _id(""), _handle(handle), _buttonCount(0), _joystickCount(0), _triggerCount(0), _gamepadForm(NULL),
-      _uiJoysticks(NULL), _uiButtons(NULL)
+static std::vector<Gamepad*> __gamepads;
+
+unsigned int Gamepad::getIndexFromMapping(Gamepad::ButtonMapping mapping)
+{
+    // Determine which bit is set in the mapping.
+    unsigned int index = 0;
+    bool done = false;
+    do
+    {
+        if (mapping == (1 << index))
+            done = true;
+        else
+            ++index;
+    } while (!done);
+    GP_ASSERT(index < 20);
+
+    return index;
+}
+
+Gamepad::Gamepad(const char* formPath)
+    : _id(""), _handle(0), _buttonCount(0), _joystickCount(0), _triggerCount(0), _form(NULL)
 {
     GP_ASSERT(formPath);
+    _form = Form::create(formPath);
+    GP_ASSERT(_form);
+    _form->setConsumeInputEvents(false);
+    _id = _form->getId();
+    bindGamepadControls(_form);
+}
+
+Gamepad::Gamepad(const char* id, GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
+                 unsigned int vendorId, unsigned int productId, char* vendorString, char* productString)
+    : _id(id), _handle(handle), _vendorId(vendorId), _productId(productId), _vendorString(vendorString), _productString(productString),
+      _buttonCount(buttonCount), _joystickCount(joystickCount), _triggerCount(triggerCount), _form(NULL)
+{
+}
 
-    _gamepadForm = Form::create(formPath);
-    GP_ASSERT(_gamepadForm);
+Gamepad* Gamepad::add(const char* id, GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
+    unsigned int vendorId, unsigned int productId, char* vendorString, char* productString)
+{
+    Gamepad* gamepad = new Gamepad(id, handle, buttonCount, joystickCount, triggerCount, vendorId, productId, vendorString, productString);
 
-    _gamepadForm->setConsumeInputEvents(false);
+    __gamepads.push_back(gamepad);
+    Game::getInstance()->gamepadEvent(CONNECTED_EVENT, gamepad);
+    return gamepad;
+}
 
-    _id = _gamepadForm->getId();
+Gamepad* Gamepad::add(const char* formPath)
+{
+    Gamepad* gamepad = new Gamepad(formPath);
 
-    bindGamepadControls(_gamepadForm);
+    __gamepads.push_back(gamepad);
+    Game::getInstance()->gamepadEvent(CONNECTED_EVENT, gamepad);
+    return gamepad;
 }
 
-Gamepad::Gamepad(const char* id, unsigned int handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount)
-    : _id(id), _handle(handle), _buttonCount(buttonCount), _joystickCount(joystickCount), _triggerCount(triggerCount),
-      _gamepadForm(NULL), _uiJoysticks(NULL), _uiButtons(NULL)
+void Gamepad::remove(GamepadHandle handle)
 {
+    std::vector<Gamepad*>::iterator it = __gamepads.begin();
+    do
+    {
+        Gamepad* gamepad = *it;
+        if (gamepad->_handle == handle)
+        {
+            Game::getInstance()->gamepadEvent(DISCONNECTED_EVENT, gamepad);
+            it = __gamepads.erase(it);
+        }
+        else
+        {
+        	it++;
+        }
+    } while (it != __gamepads.end());
+}
+
+void Gamepad::remove(Gamepad* gamepad)
+{
+    std::vector<Gamepad*>::iterator it = __gamepads.begin();
+    do
+    {
+        Gamepad* g = *it;
+        if (g == gamepad)
+        {
+            Game::getInstance()->gamepadEvent(DISCONNECTED_EVENT, g);
+            it = __gamepads.erase(it);
+        }
+        else
+        {
+        	it++;
+        }
+    } while (it != __gamepads.end());
 }
 
 void Gamepad::bindGamepadControls(Container* container)
@@ -43,20 +114,15 @@ void Gamepad::bindGamepadControls(Container* container)
         }
         else if (std::strcmp("joystick", control->getType()) == 0)
         {
-            control->addRef();
-            if (!_uiJoysticks)
-                _uiJoysticks = new std::vector<Joystick*>;
-
-            _uiJoysticks->push_back((Joystick*) control);
+            Joystick* joystick = (Joystick*)control;
+            _uiJoysticks[joystick->getIndex()] = joystick;
             _joystickCount++;
         }
-        else if (std::strcmp("button", control->getType()) == 0)
+        else if (std::strcmp("gamepadButton", control->getType()) == 0)
         {
-            control->addRef();
-            if (!_uiButtons)
-                _uiButtons = new std::vector<Button*>;
-
-            _uiButtons->push_back((Button*) control);
+            GamepadButton* button = (GamepadButton*)control;
+            unsigned int index = getIndexFromMapping(button->getMapping());
+            _uiButtons[index] = button;
             _buttonCount++;
         }   
     }
@@ -64,30 +130,77 @@ void Gamepad::bindGamepadControls(Container* container)
 
 Gamepad::~Gamepad()
 {
-    if (_gamepadForm)
-    {
-        if (_uiJoysticks)
-        {
-            for (std::vector<Joystick*>::iterator itr = _uiJoysticks->begin(); itr != _uiJoysticks->end(); itr++)
-            {
-                SAFE_RELEASE((*itr));
-            }
-            _uiJoysticks->clear();
-            SAFE_DELETE(_uiJoysticks);
-        }
+    if (_form)
+    {        
+        SAFE_RELEASE(_form);
+    }
+}
 
-        if (_uiButtons)
+Gamepad* Gamepad::getGamepad(GamepadHandle handle)
+{
+    std::vector<Gamepad*>::const_iterator it;
+    for (it = __gamepads.begin(); it != __gamepads.end(); it++)
+    {
+        Gamepad* gamepad = *it;
+        if (!gamepad->isVirtual() && gamepad->_handle == handle)
         {
-            for (std::vector<Button*>::iterator itr = _uiButtons->begin(); itr!= _uiButtons->end(); itr++)
-            {
-                SAFE_RELEASE((*itr));
-            }
-            _uiButtons->clear();
-            SAFE_DELETE(_uiButtons);
+            return gamepad;
         }
-        
-        SAFE_RELEASE(_gamepadForm);
     }
+
+    return NULL;
+}
+
+std::vector<Gamepad*>* Gamepad::getGamepads()
+{
+    return &__gamepads;
+}
+
+Gamepad::ButtonMapping Gamepad::getButtonMappingFromString(const char* string)
+{
+    if (strcmp(string, "A") == 0 || strcmp(string, "BUTTON_A") == 0)
+        return BUTTON_A;
+    else if (strcmp(string, "B") == 0 || strcmp(string, "BUTTON_B") == 0)
+        return BUTTON_B;
+    else if (strcmp(string, "C") == 0 || strcmp(string, "BUTTON_C") == 0)
+        return BUTTON_C;
+    else if (strcmp(string, "X") == 0 || strcmp(string, "BUTTON_X") == 0)
+        return BUTTON_X;
+    else if (strcmp(string, "Y") == 0 || strcmp(string, "BUTTON_Y") == 0)
+        return BUTTON_Y;
+    else if (strcmp(string, "Z") == 0 || strcmp(string, "BUTTON_Z") == 0)
+        return BUTTON_Z;
+    else if (strcmp(string, "MENU1") == 0 || strcmp(string, "BUTTON_MENU1") == 0)
+        return BUTTON_MENU1;
+    else if (strcmp(string, "MENU2") == 0 || strcmp(string, "BUTTON_MENU2") == 0)
+        return BUTTON_MENU2;
+    else if (strcmp(string, "MENU3") == 0 || strcmp(string, "BUTTON_MENU3") == 0)
+        return BUTTON_MENU3;
+    else if (strcmp(string, "MENU4") == 0 || strcmp(string, "BUTTON_MENU4") == 0)
+        return BUTTON_MENU4;
+    else if (strcmp(string, "L1") == 0 || strcmp(string, "BUTTON_L1") == 0)
+        return BUTTON_L1;
+    else if (strcmp(string, "L2") == 0 || strcmp(string, "BUTTON_L2") == 0)
+        return BUTTON_L2;
+    else if (strcmp(string, "L3") == 0 || strcmp(string, "BUTTON_L3") == 0)
+        return BUTTON_L3;
+    else if (strcmp(string, "R1") == 0 || strcmp(string, "BUTTON_R1") == 0)
+        return BUTTON_R1;
+    else if (strcmp(string, "R2") == 0 || strcmp(string, "BUTTON_R2") == 0)
+        return BUTTON_R2;
+    else if (strcmp(string, "R3") == 0 || strcmp(string, "BUTTON_R3") == 0)
+        return BUTTON_R3;
+    else if (strcmp(string, "UP") == 0 || strcmp(string, "BUTTON_UP") == 0)
+        return BUTTON_UP;
+    else if (strcmp(string, "DOWN") == 0 || strcmp(string, "BUTTON_DOWN") == 0)
+        return BUTTON_DOWN;
+    else if (strcmp(string, "LEFT") == 0 || strcmp(string, "BUTTON_LEFT") == 0)
+        return BUTTON_LEFT;
+    else if (strcmp(string, "RIGHT") == 0 || strcmp(string, "BUTTON_RIGHT") == 0)
+        return BUTTON_RIGHT;
+
+    GP_WARN("Unknown GamepadButton string.");
+    return BUTTON_A;
 }
 
 const char* Gamepad::getId() const
@@ -95,23 +208,43 @@ const char* Gamepad::getId() const
     return _id.c_str();
 }
 
+const unsigned int Gamepad::getVendorId() const
+{
+    return _vendorId;
+}
+
+const unsigned int Gamepad::getProductId() const
+{
+    return _productId;
+}
+
+const char* Gamepad::getVendorString() const
+{
+    return _vendorString.c_str();
+}
+
+const char* Gamepad::getProductString() const
+{
+    return _productString.c_str();
+}
+
 void Gamepad::update(float elapsedTime)
 {
-    if (_gamepadForm && _gamepadForm->isEnabled())
+    if (_form && _form->isEnabled())
     {
-        _gamepadForm->update(elapsedTime);
+        _form->update(elapsedTime);
     }
     else
     {
-        isConnected();
+        Platform::pollGamepadState(this);
     }
 }
 
 void Gamepad::draw()
 {
-    if (_gamepadForm && _gamepadForm->isEnabled())
+    if (_form && _form->isEnabled())
     {
-        _gamepadForm->draw();
+        _form->draw();
     }
 }
 
@@ -120,19 +253,30 @@ unsigned int Gamepad::getButtonCount() const
     return _buttonCount;
 }
 
-Gamepad::ButtonState Gamepad::getButtonState(unsigned int buttonId) const
+bool Gamepad::isButtonDown(ButtonMapping mapping) const
 {
-    GP_ASSERT(buttonId < _buttonCount);
-
-    if (_gamepadForm)
+    if (_form)
     {
-        if (_uiButtons)
-            return _uiButtons->at(buttonId)->getState() == Control::ACTIVE ? BUTTON_PRESSED : BUTTON_RELEASED;
+        unsigned int index = getIndexFromMapping(mapping);
+        if (index < _buttonCount)
+        {
+            GamepadButton* button = _uiButtons[index];
+            if (button)
+            {
+                return (button->getState() == Control::ACTIVE);
+            }
+        }
         else
-            return BUTTON_RELEASED;
+        {
+            return false;
+        }
     }
-    else
-        return Platform::getGamepadButtonState(_handle, buttonId) ? BUTTON_PRESSED : BUTTON_RELEASED;
+    else if (_buttons & mapping)
+    {
+        return true;
+    }
+
+    return false;
 }
 
 unsigned int Gamepad::getJoystickCount() const
@@ -140,32 +284,16 @@ unsigned int Gamepad::getJoystickCount() const
     return _joystickCount;
 }
 
-bool Gamepad::isJoystickActive(unsigned int joystickId) const
+void Gamepad::getJoystickValues(unsigned int joystickId, Vector2* outValue) const
 {
     GP_ASSERT(joystickId < _joystickCount);
 
-    if (_gamepadForm)
+    if (_form)
     {
-        if (_uiJoysticks)
-            return !_uiJoysticks->at(joystickId)->getValue().isZero();
-        else
-            return false;
-    }
-    else
-    {
-        return Platform::isGamepadJoystickActive(_handle, joystickId);
-    }
-}
-
-void Gamepad::getJoystickAxisValues(unsigned int joystickId, Vector2* outValue) const
-{
-    GP_ASSERT(joystickId < _joystickCount);
-
-    if (_gamepadForm)
-    {
-        if (_uiJoysticks)
+        Joystick* joystick = _uiJoysticks[joystickId];
+        if (joystick)
         {
-            const Vector2& value = _uiJoysticks->at(joystickId)->getValue();
+            const Vector2& value = joystick->getValue();
             outValue->set(value.x, value.y);
         }
         else
@@ -175,40 +303,38 @@ void Gamepad::getJoystickAxisValues(unsigned int joystickId, Vector2* outValue)
     }
     else
     {
-        Platform::getGamepadJoystickAxisValues(_handle, joystickId, outValue);
+        outValue->set(_joysticks[joystickId]);
     }
 }
 
-float Gamepad::getJoystickAxisX(unsigned int joystickId) const
+unsigned int Gamepad::getTriggerCount() const
 {
-    return Platform::getGamepadJoystickAxisX(_handle, joystickId);
+    return _triggerCount;
 }
 
-float Gamepad::getJoystickAxisY(unsigned int joystickId) const
+float Gamepad::getTriggerValue(unsigned int triggerId) const
 {
-    return Platform::getGamepadJoystickAxisY(_handle, joystickId);
+    GP_ASSERT(triggerId < _triggerCount);
+
+    if (_form)
+    {
+        // Triggers are currently not available for virtual gamepads.
+        return 0.0f;
+    }
+    else
+    {
+        return _triggers[triggerId];
+    }
 }
 
 bool Gamepad::isVirtual() const
 {
-    return _gamepadForm;
+    return _form;
 }
 
 Form* Gamepad::getForm() const
 {
-    return _gamepadForm;
-}
-
-bool Gamepad::isConnected() const
-{
-    if (_gamepadForm)
-    {
-        return true;
-    }
-    else
-    {
-        return Platform::isGamepadConnected(_handle);
-    }
+    return _form;
 }
 
 }

+ 129 - 50
gameplay/src/Gamepad.h

@@ -2,12 +2,14 @@
 #define GAMEPAD_H_
 
 #include "Form.h"
-#include "Button.h"
 #include "Joystick.h"
 
 namespace gameplay
 {
 
+class Platform;
+class GamepadButton;
+
 /**
  * Defines an interface for handling gamepad input.
  */
@@ -15,6 +17,7 @@ class Gamepad
 {
     friend class Platform;
     friend class Game;
+    friend class GamepadButton;
     friend class Control;
 
 public:
@@ -29,35 +32,88 @@ public:
     };
 
     /**
-     * Gamepad button states.
+     * Gamepad buttons.
      */
-    enum ButtonState
+    enum ButtonMapping
     {
-        BUTTON_PRESSED = gameplay::Control::Listener::PRESS, 
-        BUTTON_RELEASED = gameplay::Control::Listener::RELEASE
+        BUTTON_A       = (1 << 0),
+        BUTTON_B       = (1 << 1),
+        BUTTON_C       = (1 << 2),
+        BUTTON_X       = (1 << 3),
+        BUTTON_Y       = (1 << 4),
+        BUTTON_Z       = (1 << 5),
+        BUTTON_MENU1   = (1 << 6),
+        BUTTON_MENU2   = (1 << 7),
+        BUTTON_MENU3   = (1 << 8),
+        BUTTON_MENU4   = (1 << 9),
+        BUTTON_L1      = (1 << 10),
+        BUTTON_L2      = (1 << 11),
+        BUTTON_L3      = (1 << 12),
+        BUTTON_R1      = (1 << 13),
+        BUTTON_R2      = (1 << 14),
+        BUTTON_R3      = (1 << 15),
+        BUTTON_UP      = (1 << 16),
+        BUTTON_DOWN    = (1 << 17),
+        BUTTON_LEFT    = (1 << 18),
+        BUTTON_RIGHT   = (1 << 19)
     };
 
     /**
-     * Gets the Gamepad's ID.
+     * Get all connected gamepads.
+     *
+     * @return A vector of all connected gamepads.
+     */
+    static std::vector<Gamepad*>* getGamepads();
+
+    /**
+     * Get this gamepad's ID as a string.
      *
-     * @return the Gamepad's ID.
+     * @return This gamepad's ID as a string.
      */
     const char* getId() const;
 
     /**
-     * Gets the number of button on the gamepad.
+     * Get this gamepad's vendor ID.
+     *
+     * @return This gamepad's vendor ID.
+     */
+    const unsigned int getVendorId() const;
+
+    /**
+     * Get this gamepad's product ID.
      *
-     * @return the number of buttons on the gamepad.
+     * @return This gamepad's product ID.
+     */
+    const unsigned int getProductId() const;
+
+    /**
+     * Get this gamepad's vendor name.
+     *
+     * @return This gamepad's vendor name.
+     */
+    const char* getVendorString() const;
+
+    /**
+     * Get this gamepad's product name.
+     *
+     * @return This gamepad's product name.
+     */
+    const char* getProductString() const;
+
+    /**
+     * Gets the number of buttons on this gamepad.
+     *
+     * @return The number of buttons on this gamepad.
      */
     unsigned int getButtonCount() const;
 
     /** 
-     * Gets the current state of the specified button.
+     * Gets whether the given button is currently pressed down.
      *
-     * @param buttonId The index of the button on the gamepad to get the state for.
-     * @return whether the button is currently pressed or not.
+     * @param button The enum of the button on the gamepad to get the state for.
+     * @return Whether the button is currently pressed or not.
      */
-    ButtonState getButtonState(unsigned int buttonId) const;
+    bool isButtonDown(ButtonMapping button) const;
     
     /**
      * Gets the number of joysticks on the gamepad.
@@ -66,57 +122,54 @@ public:
      */
     unsigned int getJoystickCount() const;
 
-    /**
-     * Gets whether the specified joystick's state is active or not.
-     * 
-     * @param joystickId The index of the joystick on the gamepad to get state for.
-     * @return Whether the given joystick is active or not.
-     */
-    bool isJoystickActive(unsigned int joystickId) const;
-
     /**
      * Returns the specified joystick's value as a Vector2.
      *
      * @param joystickId The index of the joystick to get the value for.
-     * @param outValues The current x-axis and y-axis value displacement of the joystick.
+     * @param outValues The current x-axis and y-axis values of the joystick.
      */
-    void getJoystickAxisValues(unsigned int joystickId, Vector2* outValues) const;
+    void getJoystickValues(unsigned int joystickId, Vector2* outValues) const;
 
     /**
-     * Returns the specified joystick's x-axis value.
+     * Returns the number of analog triggers (as opposed to digital shoulder buttons)
+     * on this gamepad.
      *
-     * @param joystickId The index of the joystick to get the x-axis value for.
-     * @return The current value of the joystick's x-axis value.
+     * @return The number of analog triggers on this gamepad.
      */
-    float getJoystickAxisX(unsigned int joystickId) const;
-    
+    unsigned int getTriggerCount() const;
+
     /**
-     * Returns the specified joystick's y-axis value.
-     * 
-     * @param joystickId The index of the joystick to get the y-axis value for.
-     * @return The current value of the joystick's y-axis value.
+     * Returns the value of an analog trigger on this gamepad.  This value will be a
+     * number between 0 and 1, where 0 means the trigger is in its resting (unpressed)
+     * state and 1 means the trigger has been completely pressed down.
+     *
+     * @param triggerId The trigger to query.
+     * @return The value of the given trigger.
      */
-    float getJoystickAxisY(unsigned int joystickId) const;
+    float getTriggerValue(unsigned int triggerId) const;
 
     /**
      * Returns whether the gamepad is currently represented with a UI form or not.
      *
      * @return true if the gamepad is currently represented by a UI form; false if the gamepad is
-     *      not represented by a UI form
+     *         not represented by a UI form.
      */
     bool isVirtual() const;
 
     /**
      * Gets the Form used to represent this gamepad.
      *
-     * Note: What if the user decides to add gamepad controls (joysticks, buttons) to the gamepad form? How do we handle new/deleted controls?
-     *
      * @return the Form used to represent this gamepad. NULL if the gamepad is not represented with a Form.
      */
     Form* getForm() const;
 
     /**
-     * Updates the gamepad.
+     * Updates the gamepad's state.  For a virtual gamepad, this results in calling update()
+     * on the gamepad's form.  For physical gamepads, this polls the gamepad's state
+     * at the platform level.  Either way, this should be called once a frame before
+     * getting and using a gamepad's current state.
+     *
+     * @param elapsedTime The elapsed game time.
      */
     void update(float elapsedTime);
 
@@ -130,10 +183,9 @@ private:
     /**
      * Constructs a gamepad from the specified .form file.
      *
-     * @param handle The gamepad handle
      * @param formPath The path the the .form file.
      */ 
-    Gamepad(unsigned int handle, const char* formPath);
+    Gamepad(const char* formPath);
 
     /**
      * Constructs a physical gamepad.
@@ -144,13 +196,33 @@ private:
      * @param joystickCount the number of joysticks on the gamepad.
      * @param triggerCount the number of triggers on the gamepad.
      */
-    Gamepad(const char* id, unsigned int handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount);
+    Gamepad(const char* id, GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
+            unsigned int vendorId, unsigned int productId, char* vendorString, char* productString);
 
     /**
      * Copy constructor.
      */
     Gamepad(const Gamepad& copy);
 
+    /**
+     * Used by platforms to add gamepads to the set available to games.
+     */
+    static Gamepad* add(const char* id, GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
+                        unsigned int vendorId, unsigned int productId, char* vendorString, char* productString);
+
+    /**
+     * Used by Game::loadGamepads() to add virtual gamepads from a game's config file.
+     */
+    static Gamepad* add(const char* formPath);
+
+    static void remove(GamepadHandle handle);
+
+    static void remove(Gamepad* gamepad);
+
+    static Gamepad* getGamepad(GamepadHandle handle);
+
+    static ButtonMapping getButtonMappingFromString(const char* string);
+
     /** 
      * Destructor.
      */
@@ -161,21 +233,28 @@ private:
      */
     void bindGamepadControls(Container* container);
 
-    /**
-     * Gets whether the Gamepad is currently connected to the Platform.
-     */
-    bool isConnected() const;
-        
-    std::string _id;              // ID of the Gamepad
-    unsigned int _handle;         // The handle of the Gamepad.
+    static unsigned int getIndexFromMapping(Gamepad::ButtonMapping mapping);
+
+    std::string _id;
+    GamepadHandle _handle;        // The handle of the Gamepad.
+    unsigned int _vendorId;
+    unsigned int _productId;
+    std::string _vendorString;
+    std::string _productString;
+
     unsigned int _buttonCount;    // Number of buttons.
     unsigned int _joystickCount;  // Number of joysticks.
     unsigned int _triggerCount;   // Number of triggers.
     
     // Data needed for virtual gamepads.
-    Form* _gamepadForm;
-    std::vector<Joystick*>* _uiJoysticks;
-    std::vector<Button*>* _uiButtons;
+    Form* _form;
+    Joystick* _uiJoysticks[2];
+    GamepadButton* _uiButtons[20];
+
+    // Current gamepad state.
+    unsigned int _buttons;
+    Vector2 _joysticks[2];
+    float _triggers[2];
 };
 
 }

+ 45 - 0
gameplay/src/GamepadButton.cpp

@@ -0,0 +1,45 @@
+#include "Base.h"
+#include "GamepadButton.h"
+
+namespace gameplay
+{
+
+GamepadButton::GamepadButton()
+{
+}
+
+GamepadButton::~GamepadButton()
+{
+}
+
+GamepadButton* GamepadButton::create(const char* id, Theme::Style* style)
+{
+    GamepadButton* button = new GamepadButton();
+
+    button->_id = id;
+    button->_style = style;
+
+    return button;
+}
+
+GamepadButton* GamepadButton::create(Theme::Style* style, Properties* properties)
+{
+    GamepadButton* button = new GamepadButton();
+    button->initialize(style, properties);
+
+    button->_mapping = Gamepad::getButtonMappingFromString(properties->getString("mapping"));
+
+    return button;
+}
+
+const char* GamepadButton::getType() const
+{
+    return "gamepadButton";
+}
+
+const Gamepad::ButtonMapping GamepadButton::getMapping() const
+{
+    return _mapping;
+}
+
+}

+ 43 - 0
gameplay/src/GamepadButton.h

@@ -0,0 +1,43 @@
+#ifndef GAMEPADBUTTON_H_
+#define GAMEPADBUTTON_H_
+
+#include "Button.h"
+#include "Theme.h"
+#include "Properties.h"
+#include "Gamepad.h"
+
+namespace gameplay
+{
+
+class GamepadButton : public Button
+{
+    friend class Container;
+    friend class Gamepad;
+
+public:
+    static GamepadButton* create(const char* id, Theme::Style* style);
+
+protected:
+    /**
+     * Constructor.
+     */
+    GamepadButton();
+
+    /**
+     * Destructor.
+     */
+    virtual ~GamepadButton();
+
+    static GamepadButton* create(Theme::Style* style, Properties* properties);
+
+    const char* getType() const;
+
+    const Gamepad::ButtonMapping getMapping() const;
+
+private:
+    Gamepad::ButtonMapping _mapping;
+};
+
+}
+
+#endif

+ 1 - 0
gameplay/src/Joystick.cpp

@@ -32,6 +32,7 @@ Joystick* Joystick::create(Theme::Style* style, Properties* properties)
 {
     Joystick* joystick = new Joystick();
     joystick->initialize(style, properties);
+    joystick->_index = properties->getInt("index");
     return joystick;
 }
 

+ 3 - 0
gameplay/src/Joystick.h

@@ -113,6 +113,8 @@ public:
      */
     const char* getType() const;
 
+    inline const unsigned int getIndex() const;
+
 protected:
     
     /**
@@ -176,6 +178,7 @@ private:
     Vector2 _displacement;
     Vector2* _innerSize;
     Vector2* _outerSize;
+    unsigned int _index;
 };
 
 }

+ 5 - 0
gameplay/src/Joystick.inl

@@ -46,4 +46,9 @@ inline bool Joystick::isRelative() const
     return _relative;
 }
 
+inline const unsigned int Joystick::getIndex() const
+{
+    return _index;
+}
+
 }

+ 1 - 100
gameplay/src/Platform.h

@@ -221,107 +221,8 @@ public:
      * @param evt The gesture event to register to start recognizing events for.
      */
     static bool isGestureRegistered(Gesture::GestureEvent evt);
-    
-    /** 
-     * Gets the number of gamepad devices connected to the Platform.
-     *
-     * Note: Calling this method also checks if any gamepads have been attached to or detached from the Platform 
-     *
-     * @return the number of gamepads connected to the Platform.
-     */
-    static unsigned int getGamepadsConnected();
-
-    /**
-     * Gets whether the specified gamepad is connected to the Platform.
-     *
-     * @param gamepadHandle the handle to the gamepad.
-     */
-    static bool isGamepadConnected(unsigned int gamepadHandle);
-
-    /**
-     * Gets the specified gamepad's ID.
-     *
-     * @param gamepadHandle the handle to the gamepad.
-     * @return the ID of the specified gamepad.
-     */
-    static const char* getGamepadId(unsigned int gamepadHandle);
 
-    /**
-     * Gets the number of buttons on the specified gamepad.
-     * 
-     * @param gamepadHandle handle to the gamepad to get the number of buttons for.
-     * @return the number of buttons on the gamepad.
-     */
-    static unsigned int getGamepadButtonCount(unsigned int gamepadHandle);
-
-    /**
-     * Gets the button state for the specified gamepad and button index.
-     *
-     * @param gamepadHandle handle to the gamepad to query the button state for.
-     * @param buttonIndex the index to the button to retrieve the state for.
-     */
-    static bool getGamepadButtonState(unsigned int gamepadHandle, unsigned int buttonIndex);
-
-    /**
-     * Gets the number of joysticks on the specified gamepad.
-     * 
-     * @param gamepadHandle handle to the gamepad to get the number of joysticks for.
-     * @return the number of joysticks supported on the gamepad.
-     */
-    static unsigned int getGamepadJoystickCount(unsigned int gamepadHandle);
-
-    /** 
-     * Returns whether the joystick on the specified gamepad is active.
-     *
-     * @param gamepadHandle The handle to the gamepad.
-     * @param joystickIndex The index of the joystick.
-     * @return true if the joystick is active; false if the joystick is inactive.
-     */
-    static bool isGamepadJoystickActive(unsigned int gamepadHandle, unsigned int joystickIndex);
-
-    /**
-     * Gets the value of the joystick's x-axis on the specified joystick.
-     *
-     * @param gamepadHandle The handle to the gamepad.
-     * @param joystickIndex The index of the joystick.
-     * @return the value of the joystick's x-axis.
-     */
-    static float getGamepadJoystickAxisX(unsigned int gamepadHandle, unsigned int joystickIndex);
-
-    /**
-     * Gets the value of the joystick's x-axis on the specified joystick.
-     *
-     * @param gamepadHandle The handle to the gamepad.
-     * @param joystickIndex The index of the joystick.
-     * @return the value of the joystick's x-axis.
-     */
-    static float getGamepadJoystickAxisY(unsigned int gamepadHandle, unsigned int joystickIndex);
-
-    /**
-     * Gets the values for the specified gamepad and joystick index.
-     *
-     * @param gamepadHandle handle to the gamepad to query the joystick value for.
-     * @param joystickIndex the index to the joystick to retrieve the value for.
-     * @param outValue will be populated with the current value of the specified joystick.
-     */
-    static void getGamepadJoystickAxisValues(unsigned int gamepadHandle, unsigned int joystickIndex, Vector2* outValue);
-
-    /**
-     * Gets the number of triggers on the specified gamepad.
-     *
-     * @param gamepadHandle handle to the gamepad to get the number of triggers for.
-     * @return the number of triggers supported on the gamepad.
-     */ 
-    static unsigned int getGamepadTriggerCount(unsigned int gamepadHandle);
-
-    /**
-     * Gets the value for the specified gamepad and trigger index.
-     *
-     * @param gamepadHandle handle to the gamepad to query the trigger value for.
-     * @param triggerIndex the index to the trigger to retrieve the value for.
-     * @return the value of the specified trigger.
-     */
-    static float getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int triggerIndex);
+    static void pollGamepadState(Gamepad* gamepad);
 
     /**
      * Touch callback on touch events. This method handles passing the touch event to the form or to the game.

+ 1 - 56
gameplay/src/PlatformAndroid.cpp

@@ -1299,63 +1299,8 @@ bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
     return __gestureEventsProcessed.test(evt);
 }
 
-unsigned int Platform::getGamepadsConnected()
+void Platform::pollGamepadState(Gamepad* gamepad)
 {
-    return 0;
-}
-
-bool Platform::isGamepadConnected(unsigned int gamepadHandle)
-{
-    return false;
-}
-
-const char* Platform::getGamepadId(unsigned int gamepadHandle)
-{
-    return NULL;
-}
-
-unsigned int Platform::getGamepadButtonCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-bool Platform::getGamepadButtonState(unsigned int gamepadHandle, unsigned int buttonIndex)
-{
-    return false;
-}
-
-unsigned int Platform::getGamepadJoystickCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-bool Platform::isGamepadJoystickActive(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return false;
-}
-
-float Platform::getGamepadJoystickAxisX(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return 0.0f;
-}
-
-float Platform::getGamepadJoystickAxisY(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return 0.0f;
-}
-
-void Platform::getGamepadJoystickAxisValues(unsigned int gamepadHandle, unsigned int joystickIndex, Vector2* outValue)
-{
-}
-
-unsigned int Platform::getGamepadTriggerCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int triggerIndex)
-{
-    return 0.0f;
 }
 
 bool Platform::launchURL(const char *url)

+ 195 - 59
gameplay/src/PlatformBlackBerry.cpp

@@ -491,6 +491,137 @@ void gesture_callback(gesture_base_t* gesture, mtouch_event_t* event, void* para
     }
 }
 
+#ifdef __BB10__
+
+static const int __VIDs[] = {
+    0x1038
+};
+
+static const int __PIDs[] = {
+    0x1412
+};
+
+static const char* __vendorStrings[] =
+{
+    "SteelSeries"
+};
+
+static const char* __productStrings[] =
+{
+    "FREE"
+};
+
+static const unsigned int __knownGamepads = 1;
+
+void loadGamepad(GamepadHandle handle, int* buttonCount, int* joystickCount, int* productId, int* vendorId, char* id, char* productString, char* vendorString)
+{
+    screen_get_device_property_iv(handle, SCREEN_PROPERTY_BUTTON_COUNT, buttonCount);
+    screen_get_device_property_cv(handle, SCREEN_PROPERTY_ID_STRING, 128, id);
+    screen_get_device_property_cv(handle, SCREEN_PROPERTY_PRODUCT, 64, productString);
+    screen_get_device_property_cv(handle, SCREEN_PROPERTY_VENDOR, 64, vendorString);
+
+    // Check for the existence of analog sticks.
+    int analogs[3];
+    if (!screen_get_device_property_iv(handle, SCREEN_PROPERTY_ANALOG0, analogs))
+    {
+    	++(*joystickCount);
+    }
+
+    if (!screen_get_device_property_iv(handle, SCREEN_PROPERTY_ANALOG1, analogs))
+    {
+    	++(*joystickCount);
+    }
+
+    // ID string format: A-BBBB-CCCC-D.D
+    // A is the device's index
+    // BBBB is the device's Vendor ID (in hexadecimal)
+    // CCCC is the device's Product ID (also in hexadecimal)
+    // D.D is the device's version number
+    char* token = strtok(id, "-");
+    token = strtok(NULL, "-");
+    if (token)
+    {
+	    *vendorId = strtol(token, NULL, 16);
+    }
+
+    token = strtok(NULL, "-");
+    if (token)
+    {
+        *productId = strtol(token, NULL, 16);
+    }
+
+    // For gamepads unknown to BB10,
+    // check VID and PID against gamepads known to gameplay.
+    if (strlen(productString) == 0 || strlen(vendorString) == 0)
+    {
+        for (unsigned int i = 0; i < __knownGamepads; ++i)
+        {
+            if (__VIDs[i] == *vendorId && __PIDs[i] == *productId)
+            {
+            	strcpy(vendorString, __vendorStrings[i]);
+                strcpy(productString, __productStrings[i]);
+            }
+        }
+    }
+
+    fprintf(stderr, "Vendor: %s, Product: %s", vendorString, productString);
+}
+
+void Platform::pollGamepadState(Gamepad* gamepad)
+{
+    screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_BUTTONS, (int*)&gamepad->_buttons);
+
+    unsigned int i;
+    for (i = 0; i < gamepad->_joystickCount; ++i)
+    {
+        GP_ASSERT(i < 2);
+
+        int analog[3];
+        switch (i)
+        {
+        case 0:
+            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG0, analog);
+            break;
+        case 1:
+            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG1, analog);
+            break;
+        }
+        
+        // So far we've tested two gamepads with analog sticks on BlackBerry:
+        // the SteelSeries FREE, and the iControlPad.
+        // Both return values between -128 and +127, with the y axis starting from
+        // the top at -128.
+        // 1 / 128 == 0.0078125
+        float x = (float)analog[0] * 0.0078125f;
+        float y = -(float)analog[1] * 0.0078125f;
+        gamepad->_joysticks[i].set(x, y);        
+    }
+
+    for (i = 0; i < gamepad->_triggerCount; ++i)
+    {
+        GP_ASSERT(i < 2);
+
+        int analog[3];
+        switch (i)
+        {
+        case 0:
+            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG0, analog);
+            break;
+        case 1:
+            screen_get_device_property_iv(gamepad->_handle, SCREEN_PROPERTY_ANALOG1, analog);
+            break;
+        }
+
+        float value = (float)analog[2] * 0.0078125f;
+        gamepad->_triggers[i] = value;
+    }
+}
+#else
+void Platform::getGamepadButtonValues(GamepadHandle handle, unsigned int* out) { }
+void Platform::getGamepadJoystickValues(GamepadHandle handle, unsigned int joystickIndex, Vector2* outValue) { }
+void Platform::getGamepadTriggerValue(GamepadHandle handle, unsigned int triggerIndex, float* out) { }
+#endif
+
 Platform::Platform(Game* game)
     : _game(game)
 {
@@ -545,6 +676,8 @@ Platform* Platform::create(Game* game, void* attachToWindow)
     FileSystem::setResourcePath("./app/native/");
     Platform* platform = new Platform(game);
 
+    screen_device_t* screenDevs;
+
     // Query game config
     int samples = 0;
     Properties* config = Game::getInstance()->getConfig()->getNamespace("window", true);
@@ -832,6 +965,31 @@ Platform* Platform::create(Game* game, void* attachToWindow)
         glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");
     }
 
+    // Discover gamepad devices.
+    int count;
+    screen_get_context_property_iv(__screenContext, SCREEN_PROPERTY_DEVICE_COUNT, &count);
+    screenDevs = (screen_device_t*)calloc(count, sizeof(screen_device_t));
+    screen_get_context_property_pv(__screenContext, SCREEN_PROPERTY_DEVICES, (void**)screenDevs);
+
+	for (int i = 0; i < count; i++) {
+	    int type;
+        screen_get_device_property_iv(screenDevs[i], SCREEN_PROPERTY_TYPE, &type);
+
+        if (type == SCREEN_EVENT_GAMEPAD || type == SCREEN_EVENT_JOYSTICK)
+        {
+            int buttonCount = 0;
+            int joystickCount = 0;
+            int productId;
+            int vendorId;
+            char id[128];
+            char productString[64];
+            char vendorString[64];
+            loadGamepad(screenDevs[i], &buttonCount, &joystickCount, &productId, &vendorId, id, productString, vendorString);
+            Gamepad::add(id, screenDevs[i], buttonCount, joystickCount, 0, vendorId, productId, vendorString, productString);
+        }
+	}
+	free(screenDevs);
+
     return platform;
 
 error:
@@ -1055,6 +1213,43 @@ int Platform::enterMessagePump()
                         }
                         break;
                     }
+#ifdef __BB10__
+                    case SCREEN_EVENT_DEVICE:
+                    {
+                        // A device was attached or removed.
+                        screen_device_t device;
+                        int attached;
+
+                        screen_get_event_property_pv(__screenEvent, SCREEN_PROPERTY_DEVICE, (void**)&device);
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_ATTACHED, &attached);
+
+                        if (attached)
+                        {
+                            int type;
+                            screen_get_device_property_iv(device, SCREEN_PROPERTY_TYPE, &type);
+                            if (type == SCREEN_EVENT_GAMEPAD || type == SCREEN_EVENT_JOYSTICK)
+                            {
+                                int buttonCount = 0;
+                                int joystickCount = 0;
+                                int productId;
+                                int vendorId;
+                                char id[128];
+                                char productString[64];
+                                char vendorString[64];
+                                loadGamepad(device, &buttonCount, &joystickCount, &productId, &vendorId, id, productString, vendorString);
+                                Gamepad::add(id, device, buttonCount, joystickCount, 0, vendorId, productId, vendorString, productString);
+                            }
+                        }
+                        else
+                        {
+                            Gamepad::remove(device);
+                        }
+
+                        break;
+                    }
+#endif
+                    default:
+                        break;
                 }
             }
             else if (domain == navigator_get_domain())
@@ -1365,65 +1560,6 @@ bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
     return __gestureEventsProcessed.test(evt);
 }
 
-unsigned int Platform::getGamepadsConnected()
-{
-    return 0;
-}
-
-bool Platform::isGamepadConnected(unsigned int gamepadHandle)
-{
-    return false;
-}
-
-const char* Platform::getGamepadId(unsigned int gamepadHandle)
-{
-    return NULL;
-}
-
-unsigned int Platform::getGamepadButtonCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-bool Platform::getGamepadButtonState(unsigned int gamepadHandle, unsigned int buttonIndex)
-{
-    return false;
-}
-
-unsigned int Platform::getGamepadJoystickCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-bool Platform::isGamepadJoystickActive(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return false;
-}
-
-float Platform::getGamepadJoystickAxisX(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return 0.0f;
-}
-
-float Platform::getGamepadJoystickAxisY(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return 0.0f;
-}
-
-void Platform::getGamepadJoystickAxisValues(unsigned int gamepadHandle, unsigned int joystickIndex, Vector2* outValues)
-{
-}
-
-unsigned int Platform::getGamepadTriggerCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int triggerIndex)
-{
-    return 0.0f;
-}
-
 bool Platform::launchURL(const char* url)
 {
     if (url == NULL || *url == '\0')

+ 1 - 132
gameplay/src/PlatformMacOSX.mm

@@ -1726,139 +1726,8 @@ bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
      return [__view isGestureRegistered:evt];
 }
 
-unsigned int Platform::getGamepadsConnected()
+void Platform::pollGamepadState(Gamepad* gamepad)
 {
-    Game* game = Game::getInstance();
-    
-    if(game->isInitialized())
-    {
-        // Locate any newly connected devices
-        for(OSXGamepad* gamepad in __gamepads)
-        {
-            NSNumber* locationID = [gamepad locationID];
-            if([__activeGamepads objectForKey:locationID] == NULL)
-            {
-                unsigned int handle = game->createGamepad([[gamepad identifierName] cStringUsingEncoding:NSASCIIStringEncoding],
-                                                          [locationID unsignedIntValue],
-                                                          [gamepad numberOfButtons],
-                                                          [gamepad numberOfSticks],
-                                                          [gamepad numberOfTriggerButtons]);
-                NSNumber* handleObj = [NSNumber numberWithUnsignedInt:handle];
-                [__activeGamepads setObject:handleObj forKey:locationID];
-                game->gamepadEvent(Gamepad::CONNECTED_EVENT, game->getGamepad(handle));
-            }
-        }
-        
-        // Detect any disconnected gamepads
-        NSMutableArray* deadGamepads = [NSMutableArray array];
-        for(NSNumber* locationID in __activeGamepads)
-        {
-            OSXGamepad* gamepad = gamepadForLocationID(locationID);
-            if(gamepad == NULL)
-            {
-                NSNumber* gameHandle = [__activeGamepads objectForKey:locationID];
-                game->gamepadEvent(Gamepad::DISCONNECTED_EVENT, game->getGamepad([gameHandle unsignedIntValue]));
-                [deadGamepads addObject:locationID];
-            }
-        }
-        [__activeGamepads removeObjectsForKeys:deadGamepads];
-    }
-    return [__gamepads count];
-}
-
-bool Platform::isGamepadConnected(unsigned int gamepadHandle)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    return (gamepad != NULL);
-}
-
-const char* Platform::getGamepadId(unsigned int gamepadHandle)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    if(gamepad)
-    {
-        return [[gamepad productName] cStringUsingEncoding:NSASCIIStringEncoding];
-    }
-    return NULL;
-}
-
-unsigned int Platform::getGamepadButtonCount(unsigned int gamepadHandle)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    if(gamepad)
-    {
-        return [gamepad numberOfButtons];
-    }
-    return 0;
-}
-
-bool Platform::getGamepadButtonState(unsigned int gamepadHandle, unsigned int buttonIndex)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    OSXGamepadButton* button = [gamepad buttonAtIndex:buttonIndex];
-    if(button)
-    {
-        return [button state];
-    }
-    return false;
-}
-
-unsigned int Platform::getGamepadJoystickCount(unsigned int gamepadHandle)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    if(gamepad)
-    {
-        return [gamepad numberOfSticks];
-    }
-    return 0;
-}
-
-bool Platform::isGamepadJoystickActive(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return true;
-}
-
-float Platform::getGamepadJoystickAxisX(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    OSXGamepadAxis* xAxis = [gamepad axisAtIndex:(joystickIndex*2)];
-    return [xAxis calibratedValue];
-}
-
-float Platform::getGamepadJoystickAxisY(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    OSXGamepadAxis* yAxis = [gamepad axisAtIndex:((joystickIndex*2)+1)];
-    return [yAxis calibratedValue];
-}
-
-void Platform::getGamepadJoystickAxisValues(unsigned int gamepadHandle, unsigned int joystickIndex, Vector2* outValue)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    OSXGamepadAxis* xAxis = [gamepad axisAtIndex:(joystickIndex*2)];
-    OSXGamepadAxis* yAxis = [gamepad axisAtIndex:((joystickIndex*2)+1)];
-    if(outValue)
-    {
-        outValue->x = [xAxis calibratedValue];
-        outValue->y = [yAxis calibratedValue];
-    }
-}
-
-unsigned int Platform::getGamepadTriggerCount(unsigned int gamepadHandle)
-{
-    OSXGamepad *gamepad = gamepadForLocationIDValue(gamepadHandle);
-    return [gamepad numberOfTriggerButtons];
-}
-
-float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int triggerIndex)
-{
-    OSXGamepad* gamepad = gamepadForLocationIDValue(gamepadHandle);
-    OSXGamepadButton* button = [gamepad triggerButtonAtIndex:triggerIndex];
-    if(button)
-    {
-        return [button stateValue];
-    }
-    return 0.0f;
 }
 
 }

+ 108 - 312
gameplay/src/PlatformWindows.cpp

@@ -40,78 +40,13 @@ static bool __cursorVisible = true;
 static unsigned int __gamepadsConnected = 0;
 
 #ifdef USE_XINPUT
-struct XInputGamepad
-{
-    static const unsigned int BUTTON_COUNT = 14;
-    static const unsigned int JOYSTICK_COUNT = 2;
-    static const unsigned int TRIGGER_COUNT = 2;
-    std::string id;
-    int handle;
-    bool connected;
-    XINPUT_STATE state;
-};
-
-static XInputGamepad* __xinputGamepads = NULL;
-
-static DWORD getXInputGamepadButtonMask(unsigned int buttonHandle)
-{
-    switch(buttonHandle)
-    {
-    case 0:
-        return XINPUT_GAMEPAD_DPAD_UP;
-    case 1:
-        return XINPUT_GAMEPAD_DPAD_DOWN;
-    case 2:
-        return XINPUT_GAMEPAD_DPAD_LEFT;
-    case 3:
-        return XINPUT_GAMEPAD_DPAD_RIGHT;
-    case 4:
-        return XINPUT_GAMEPAD_START;
-    case 5:
-        return XINPUT_GAMEPAD_BACK;
-    case 6:
-        return XINPUT_GAMEPAD_LEFT_THUMB;
-    case 7:
-        return XINPUT_GAMEPAD_RIGHT_THUMB;
-    case 8:
-        return XINPUT_GAMEPAD_LEFT_SHOULDER;
-    case 9:
-        return XINPUT_GAMEPAD_RIGHT_SHOULDER;
-    case 10:
-        return XINPUT_GAMEPAD_A;
-    case 11:
-        return XINPUT_GAMEPAD_B;
-    case 12:
-        return XINPUT_GAMEPAD_X;
-    case 13:
-        return XINPUT_GAMEPAD_Y;
-    default:
-        return 0;
-    }
-}
-
-static bool getXInputState(unsigned long gamepadHandle)
-{
-    GP_ASSERT(0 <= gamepadHandle && gamepadHandle < XUSER_MAX_COUNT);
-
-    if (XInputGetState((DWORD)gamepadHandle, &__xinputGamepads[gamepadHandle].state) == ERROR_SUCCESS)
-        return (__xinputGamepads[gamepadHandle].connected = true);
-    else
-        return (__xinputGamepads[gamepadHandle].connected = false);
-}
-
-static bool getXInputButtonState(unsigned long gamepadHandle, unsigned long buttonHandle)
-{
-    GP_ASSERT(0 <= gamepadHandle && gamepadHandle < XUSER_MAX_COUNT);
-    GP_ASSERT(0 <= buttonHandle && buttonHandle < 14);
-    
-    WORD buttonMask = getXInputGamepadButtonMask(buttonHandle); // Conversion to button mask.
+static const unsigned int XINPUT_BUTTON_COUNT = 14;
+static const unsigned int XINPUT_JOYSTICK_COUNT = 2;
+static const unsigned int XINPUT_TRIGGER_COUNT = 2;
+#endif
 
-    if ((__xinputGamepads[gamepadHandle].state.Gamepad.wButtons & buttonMask) == buttonMask)
-        return true;
-    else
-        return false;
-}
+#ifdef USE_XINPUT
+static XINPUT_STATE __xInputState;
 
 static float normalizeXInputJoystickAxis(int axisValue, int deadZone)
 {
@@ -133,54 +68,6 @@ static float normalizeXInputJoystickAxis(int axisValue, int deadZone)
         return value * (absAxisValue - deadZone) / (float)(32768 - deadZone);
     }
 }
-
-static float getXInputJoystickAxisX(unsigned long gamepadHandle, unsigned long joystickHandle)
-{
-    GP_ASSERT(0 <= gamepadHandle && gamepadHandle < XUSER_MAX_COUNT);
-    GP_ASSERT(0 <= joystickHandle && joystickHandle < 2);
-    
-    switch(joystickHandle)
-    {
-    case 0:
-        return normalizeXInputJoystickAxis(__xinputGamepads[gamepadHandle].state.Gamepad.sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
-    case 1:
-        return normalizeXInputJoystickAxis(__xinputGamepads[gamepadHandle].state.Gamepad.sThumbRX, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
-    default: return 0.0f;
-    }
-}
-
-static float getXInputJoystickAxisY(unsigned long gamepadHandle, unsigned long joystickHandle)
-{
-    GP_ASSERT(0 <= gamepadHandle && gamepadHandle < XUSER_MAX_COUNT);
-    GP_ASSERT(0 <= joystickHandle && joystickHandle < 2);
-
-    switch(joystickHandle)
-    {
-    case 0:
-        return normalizeXInputJoystickAxis(__xinputGamepads[gamepadHandle].state.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
-    case 1:
-        return normalizeXInputJoystickAxis(__xinputGamepads[gamepadHandle].state.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
-    default: return 0.0f;
-    }
-}
-
-static void getXInputJoystickAxisValues(unsigned long gamepadHandle, unsigned long joystickHandle, gameplay::Vector2* outValue)
-{
-    GP_ASSERT(0 <= gamepadHandle && gamepadHandle < XUSER_MAX_COUNT);
-    GP_ASSERT(0 <= joystickHandle && joystickHandle < 2);
-
-    switch(joystickHandle)
-    {
-    case 0:
-        outValue->x = normalizeXInputJoystickAxis(__xinputGamepads[gamepadHandle].state.Gamepad.sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
-        outValue->y = normalizeXInputJoystickAxis(__xinputGamepads[gamepadHandle].state.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
-        break;
-    case 1:
-        outValue->x = normalizeXInputJoystickAxis(__xinputGamepads[gamepadHandle].state.Gamepad.sThumbRX, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
-        outValue->y = normalizeXInputJoystickAxis(__xinputGamepads[gamepadHandle].state.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
-        break;
-    }
-}
 #endif
 
 static gameplay::Keyboard::Key getKey(WPARAM win32KeyCode, bool shiftDown)
@@ -633,9 +520,6 @@ Platform::~Platform()
         DestroyWindow(__hwnd);
         __hwnd = 0;
     }
-#ifdef USE_XINPUT
-    SAFE_DELETE_ARRAY(__xinputGamepads);
-#endif
 }
 
 bool createWindow(WindowCreationParams* params, HWND* hwnd, HDC* hdc)
@@ -995,26 +879,16 @@ Platform* Platform::create(Game* game, void* attachToWindow)
 
 #ifdef USE_XINPUT
     // Initialize XInputGamepads.
-    __xinputGamepads = new XInputGamepad[XUSER_MAX_COUNT];
-    for (unsigned int i = 0; i < XUSER_MAX_COUNT; i++)
+    for (DWORD i = 0; i < XUSER_MAX_COUNT; i++)
     {
-        switch(i)
+        if (XInputGetState(i, &__xInputState) == NO_ERROR)
         {
-        case 0:
-            __xinputGamepads[i].id = "XINPUT 1";
-            break;
-        case 1:
-            __xinputGamepads[i].id = "XINPUT 2";
-            break;
-        case 2:
-            __xinputGamepads[i].id = "XINPUT 3";
-            break;
-        case 3:
-            __xinputGamepads[i].id = "XINPUT 4";
-            break;
+            // Gamepad is connected.
+            char id[9];
+            sprintf(id, "XInput %d", i);
+            Gamepad::add(id, i, XINPUT_BUTTON_COUNT, XINPUT_JOYSTICK_COUNT, XINPUT_TRIGGER_COUNT,
+                         0, 0, "Unknown", "XInput Gamepad");
         }
-        __xinputGamepads[i].connected = false;
-        __xinputGamepads[i].handle = -1;
     }
 #endif
 
@@ -1068,6 +942,21 @@ int Platform::enterMessagePump()
         }
         else
         {
+#ifdef USE_XINPUT
+            // Check for connected XInput gamepads.
+            for (DWORD i = 0; i < XUSER_MAX_COUNT; i++)
+            {
+                if (XInputGetState(i, &__xInputState) == NO_ERROR && !Gamepad::getGamepad(i))
+                {
+                    // Gamepad was just connected.
+                    char id[9];
+                    sprintf(id, "XInput %d", i);
+                    Gamepad::add(id, i, XINPUT_BUTTON_COUNT, XINPUT_JOYSTICK_COUNT, XINPUT_TRIGGER_COUNT,
+                                    0, 0, "Unknown", "XInput Gamepad");
+                }
+            }
+#endif
+
             _game->frame();
             SwapBuffers(__hdc);
         }
@@ -1230,197 +1119,104 @@ bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
     return false;
 }
 
-unsigned int Platform::getGamepadsConnected()
+#ifdef USE_XINPUT
+void Platform::pollGamepadState(Gamepad* gamepad)
 {
-    // Check to see what xbox360 gamepads are connected.
-    __gamepadsConnected = 0;
+    GP_ASSERT(gamepad->_handle < XUSER_MAX_COUNT);
 
-#ifdef USE_XINPUT
-    for (unsigned int i = 0; i < XUSER_MAX_COUNT; i++)
+    if (XInputGetState(gamepad->_handle, &__xInputState) == NO_ERROR)
     {
-        if (isGamepadConnected(i))
-            __gamepadsConnected++;
-    }    
-#endif
-    return __gamepadsConnected;
-}
+        WORD buttons = __xInputState.Gamepad.wButtons;
+
+        // Map XInput buttons to Gamepad::ButtonMappings enum.
+        static const unsigned int xInputMapping[16] = {
+            Gamepad::BUTTON_UP,    // 0x0001
+            Gamepad::BUTTON_DOWN,  // 0x0002
+            Gamepad::BUTTON_LEFT,  // 0x0004
+            Gamepad::BUTTON_RIGHT, // 0x0008
+            Gamepad::BUTTON_MENU2, // 0x0010
+            Gamepad::BUTTON_MENU1, // 0x0020
+            Gamepad::BUTTON_L3,    // 0x0040
+            Gamepad::BUTTON_R3,    // 0x0080
+            Gamepad::BUTTON_L1,    // 0x0100
+            Gamepad::BUTTON_R1,    // 0x0200
+            0,
+            0,
+            Gamepad::BUTTON_A,     // 0x1000
+            Gamepad::BUTTON_B,     // 0x2000
+            Gamepad::BUTTON_X,     // 0x4000
+            Gamepad::BUTTON_Y      // 0x8000
+        };
+
+        const unsigned int *mapping = xInputMapping;
+        for (gamepad->_buttons = 0; buttons; buttons >>= 1, mapping++)
+        {
+            if (buttons & 1)
+            {
+                gamepad->_buttons |= *mapping;
+            }
+        }
 
-bool Platform::isGamepadConnected(unsigned int gamepadHandle)
-{
+        unsigned int i;
+        for (i = 0; i < gamepad->_joystickCount; ++i)
+        {
+            GP_ASSERT(i < 2);
 
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-    Game* game = Game::getInstance();
-    GP_ASSERT(game);
+            float x;
+            float y;
+            switch (i)
+            {
+            case 0:
+                x = normalizeXInputJoystickAxis(__xInputState.Gamepad.sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
+                y = normalizeXInputJoystickAxis(__xInputState.Gamepad.sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
+                break;
+            case 1:
+                x = normalizeXInputJoystickAxis(__xInputState.Gamepad.sThumbRX, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
+                y = normalizeXInputJoystickAxis(__xInputState.Gamepad.sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
+                break;
+            }
 
-    if (__xinputGamepads[gamepadHandle].handle == -1)
-        __xinputGamepads[gamepadHandle].handle = game->createGamepad(__xinputGamepads[gamepadHandle].id.c_str(), gamepadHandle, __xinputGamepads[gamepadHandle].BUTTON_COUNT, 
-            __xinputGamepads[gamepadHandle].JOYSTICK_COUNT, __xinputGamepads[gamepadHandle].TRIGGER_COUNT);
+            gamepad->_joysticks[i].set(x, y);
+        }
 
-    bool isConnected = __xinputGamepads[gamepadHandle].connected;
-    if (getXInputState(gamepadHandle))
-    {
-        if (!isConnected)
+        for (i = 0; i < gamepad->_triggerCount; ++i)
         {
-            __xinputGamepads[gamepadHandle].connected = true;
-            
-            Gamepad* gamepad = game->getGamepad(__xinputGamepads[gamepadHandle].handle);
-            GP_ASSERT(gamepad);
-            if (game->isInitialized())
-                game->gamepadEvent(Gamepad::CONNECTED_EVENT, game->getGamepad(__xinputGamepads[gamepadHandle].handle)); 
+            GP_ASSERT(i < 2);
+
+            BYTE trigger;
+            switch (i)
+            {
+            case 0:
+                trigger = __xInputState.Gamepad.bLeftTrigger;
+                break;
+            case 1:
+                trigger = __xInputState.Gamepad.bRightTrigger;
+                break;
+            }
+
+            if (trigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
+            {
+                gamepad->_triggers[i] = 0.0f;
+            }
+            else
+            {
+                gamepad->_triggers[i] = (float)trigger / 255.0f;
+            }
         }
-        return true;
     }
     else
     {
-        if (isConnected)
-        {
-            // if it was connected, but now isn't pass the detached event to gamepadEvent()
-            __xinputGamepads[gamepadHandle].connected = false;
-            
-            Gamepad* gamepad = game->getGamepad(__xinputGamepads[gamepadHandle].handle);
-            GP_ASSERT(gamepad);
-            if (game->isInitialized())
-                game->gamepadEvent(Gamepad::DISCONNECTED_EVENT, game->getGamepad(__xinputGamepads[gamepadHandle].handle));
-        }
-        return false;
+        // Gamepad was disconnected.
+        Gamepad::remove(gamepad);
     }
-#endif
-
-    return false;
-}
-
-const char* Platform::getGamepadId(unsigned int gamepadHandle) 
-{
-
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-
-    return __xinputGamepads[gamepadHandle].id.c_str();
-#endif
-    return NULL;
-}
-
-unsigned int Platform::getGamepadButtonCount(unsigned int gamepadHandle)
-{
-
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-    if (!__xinputGamepads[gamepadHandle].connected)
-        return 0;
-
-    return XInputGamepad::BUTTON_COUNT;
-#endif
-
-    return 0;
-}
-
-bool Platform::getGamepadButtonState(unsigned int gamepadHandle, unsigned int buttonIndex)
-{
-
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-    return getXInputButtonState(gamepadHandle, buttonIndex);
-#endif
-
-    return false;
-}
-
-unsigned int Platform::getGamepadJoystickCount(unsigned int gamepadHandle)
-{
-
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-
-    if (!__xinputGamepads[gamepadHandle].connected)
-        return 0;
-
-    return XInputGamepad::JOYSTICK_COUNT;
-#endif
-
-    return 0;
 }
-
-float Platform::getGamepadJoystickAxisX(unsigned int gamepadHandle, unsigned int joystickIndex)
+#else
+void Platform::pollGamepadState(Gamepad* gamepad)
 {
-    
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-
-    return getXInputJoystickAxisX(gamepadHandle, joystickIndex);
-#endif 
-
-    return 0.0f;
-}
-
-float Platform::getGamepadJoystickAxisY(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-
-    return getXInputJoystickAxisY(gamepadHandle, joystickIndex);
-#endif
-
-    return 0.0f;
+    // TODO: Support generic HID gamepads (including XBox controllers) without requiring XInput.
 }
-
-void Platform::getGamepadJoystickAxisValues(unsigned int gamepadHandle, unsigned int joystickIndex, Vector2* outValue)
-{
-    
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-
-    getXInputJoystickAxisValues(gamepadHandle, joystickIndex, outValue);
 #endif
 
-}
-
-bool Platform::isGamepadJoystickActive(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-
-    return (getXInputJoystickAxisX(gamepadHandle, joystickIndex) != 0.0f || getXInputJoystickAxisY(gamepadHandle, joystickIndex) != 0.0f);
-#endif 
-
-    return false;
-}
-
-unsigned int Platform::getGamepadTriggerCount(unsigned int gamepadHandle)
-{
-
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-
-    return XInputGamepad::TRIGGER_COUNT;
-#endif
-
-    return 0;
-}
-
-float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int triggerIndex)
-{
-    
-#ifdef USE_XINPUT
-    GP_ASSERT(0 <= gamepadHandle);
-    GP_ASSERT(gamepadHandle < XUSER_MAX_COUNT);
-    //TODO:
-#endif
-    return 0.0f;
-}
-
 void Platform::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
     if (!Form::touchEventInternal(evt, x, y, contactIndex))

+ 1 - 57
gameplay/src/PlatformiOS.mm

@@ -1391,64 +1391,8 @@ bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
     return [__view isGestureRegistered:evt];
 }
 
-
-unsigned int Platform::getGamepadsConnected()
-{
-    return 0;
-}
-
-bool Platform::isGamepadConnected(unsigned int gamepadHandle)
-{
-    return false;
-}
-
-const char* Platform::getGamepadId(unsigned int gamepadHandle)
-{
-    return NULL;
-}
-
-unsigned int Platform::getGamepadButtonCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-bool Platform::getGamepadButtonState(unsigned int gamepadHandle, unsigned int buttonIndex)
-{
-    return false;
-}
-
-unsigned int Platform::getGamepadJoystickCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-bool Platform::isGamepadJoystickActive(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return false;
-}
-
-float Platform::getGamepadJoystickAxisX(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return 0.0f;
-}
-
-float Platform::getGamepadJoystickAxisY(unsigned int gamepadHandle, unsigned int joystickIndex)
-{
-    return 0.0f;
-}
-
-void Platform::getGamepadJoystickAxisValues(unsigned int gamepadHandle, unsigned int joystickIndex, Vector2* outValue)
-{
-}
-
-unsigned int Platform::getGamepadTriggerCount(unsigned int gamepadHandle)
-{
-    return 0;
-}
-
-float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int triggerIndex)
+void Platform::pollGamepadState(Gamepad* gamepad)
 {
-    return 0.0f;
 }
 
 bool Platform::launchURL(const char *url)

+ 1 - 0
gameplay/src/gameplay.h

@@ -92,6 +92,7 @@
 #include "Form.h"
 #include "Label.h"
 #include "Button.h"
+#include "GamepadButton.h"
 #include "CheckBox.h"
 #include "TextBox.h"
 #include "RadioButton.h"

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

@@ -11,6 +11,7 @@
 #include "Control.h"
 #include "FlowLayout.h"
 #include "Game.h"
+#include "GamepadButton.h"
 #include "Joystick.h"
 #include "Label.h"
 #include "Layout.h"

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

@@ -12,6 +12,7 @@
 #include "FlowLayout.h"
 #include "Form.h"
 #include "Game.h"
+#include "GamepadButton.h"
 #include "Joystick.h"
 #include "Label.h"
 #include "Layout.h"

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

@@ -40,9 +40,6 @@ void luaRegister_Game()
         {"getAudioListener", lua_Game_getAudioListener},
         {"getConfig", lua_Game_getConfig},
         {"getFrameRate", lua_Game_getFrameRate},
-        {"getGamepad", lua_Game_getGamepad},
-        {"getGamepadCount", lua_Game_getGamepadCount},
-        {"getGamepadsConnected", lua_Game_getGamepadsConnected},
         {"getHeight", lua_Game_getHeight},
         {"getPhysicsController", lua_Game_getPhysicsController},
         {"getScriptController", lua_Game_getScriptController},
@@ -870,124 +867,6 @@ int lua_Game_getFrameRate(lua_State* state)
     return 0;
 }
 
-int lua_Game_getGamepad(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_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                Game* instance = getInstance(state);
-                void* returnPtr = (void*)instance->getGamepad(param1);
-                if (returnPtr)
-                {
-                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                    object->instance = returnPtr;
-                    object->owns = false;
-                    luaL_getmetatable(state, "Gamepad");
-                    lua_setmetatable(state, -2);
-                }
-                else
-                {
-                    lua_pushnil(state);
-                }
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Game_getGamepad - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 2).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Game_getGamepadCount(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 1:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
-                Game* instance = getInstance(state);
-                unsigned int result = instance->getGamepadCount();
-
-                // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Game_getGamepadCount - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Game_getGamepadsConnected(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 1:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
-                Game* instance = getInstance(state);
-                unsigned int result = instance->getGamepadsConnected();
-
-                // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Game_getGamepadsConnected - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
 int lua_Game_getHeight(lua_State* state)
 {
     // Get the number of parameters.

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

@@ -23,9 +23,6 @@ int lua_Game_getAudioController(lua_State* state);
 int lua_Game_getAudioListener(lua_State* state);
 int lua_Game_getConfig(lua_State* state);
 int lua_Game_getFrameRate(lua_State* state);
-int lua_Game_getGamepad(lua_State* state);
-int lua_Game_getGamepadCount(lua_State* state);
-int lua_Game_getGamepadsConnected(lua_State* state);
 int lua_Game_getHeight(lua_State* state);
 int lua_Game_getPhysicsController(lua_State* state);
 int lua_Game_getScriptController(lua_State* state);

+ 205 - 63
gameplay/src/lua/lua_Gamepad.cpp

@@ -4,7 +4,8 @@
 #include "Base.h"
 #include "Game.h"
 #include "Gamepad.h"
-#include "lua_GamepadButtonState.h"
+#include "GamepadButton.h"
+#include "lua_GamepadButtonMapping.h"
 
 namespace gameplay
 {
@@ -15,19 +16,26 @@ void luaRegister_Gamepad()
     {
         {"draw", lua_Gamepad_draw},
         {"getButtonCount", lua_Gamepad_getButtonCount},
-        {"getButtonState", lua_Gamepad_getButtonState},
         {"getForm", lua_Gamepad_getForm},
         {"getId", lua_Gamepad_getId},
-        {"getJoystickAxisValues", lua_Gamepad_getJoystickAxisValues},
-        {"getJoystickAxisX", lua_Gamepad_getJoystickAxisX},
-        {"getJoystickAxisY", lua_Gamepad_getJoystickAxisY},
         {"getJoystickCount", lua_Gamepad_getJoystickCount},
-        {"isJoystickActive", lua_Gamepad_isJoystickActive},
+        {"getJoystickValues", lua_Gamepad_getJoystickValues},
+        {"getProductId", lua_Gamepad_getProductId},
+        {"getProductString", lua_Gamepad_getProductString},
+        {"getTriggerCount", lua_Gamepad_getTriggerCount},
+        {"getTriggerValue", lua_Gamepad_getTriggerValue},
+        {"getVendorId", lua_Gamepad_getVendorId},
+        {"getVendorString", lua_Gamepad_getVendorString},
+        {"isButtonDown", lua_Gamepad_isButtonDown},
         {"isVirtual", lua_Gamepad_isVirtual},
         {"update", lua_Gamepad_update},
         {NULL, NULL}
     };
-    const luaL_Reg* lua_statics = NULL;
+    const luaL_Reg lua_statics[] = 
+    {
+        {"getGamepads", lua_Gamepad_static_getGamepads},
+        {NULL, NULL}
+    };
     std::vector<std::string> scopePath;
 
     ScriptUtil::registerClass("Gamepad", lua_members, NULL, NULL, lua_statics, scopePath);
@@ -107,7 +115,7 @@ int lua_Gamepad_getButtonCount(lua_State* state)
     return 0;
 }
 
-int lua_Gamepad_getButtonState(lua_State* state)
+int lua_Gamepad_getForm(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -115,30 +123,35 @@ int lua_Gamepad_getButtonState(lua_State* state)
     // Attempt to match the parameters to a valid binding.
     switch (paramCount)
     {
-        case 2:
+        case 1:
         {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER)
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 2);
-
                 Gamepad* instance = getInstance(state);
-                Gamepad::ButtonState result = instance->getButtonState(param1);
-
-                // Push the return value onto the stack.
-                lua_pushstring(state, lua_stringFromEnum_GamepadButtonState(result));
+                void* returnPtr = (void*)instance->getForm();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "Form");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
 
                 return 1;
             }
 
-            lua_pushstring(state, "lua_Gamepad_getButtonState - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Gamepad_getForm - 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_pushstring(state, "Invalid number of parameters (expected 1).");
             lua_error(state);
             break;
         }
@@ -146,7 +159,7 @@ int lua_Gamepad_getButtonState(lua_State* state)
     return 0;
 }
 
-int lua_Gamepad_getForm(lua_State* state)
+int lua_Gamepad_getId(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -159,24 +172,15 @@ int lua_Gamepad_getForm(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 Gamepad* instance = getInstance(state);
-                void* returnPtr = (void*)instance->getForm();
-                if (returnPtr)
-                {
-                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                    object->instance = returnPtr;
-                    object->owns = false;
-                    luaL_getmetatable(state, "Form");
-                    lua_setmetatable(state, -2);
-                }
-                else
-                {
-                    lua_pushnil(state);
-                }
+                const char* result = instance->getId();
+
+                // Push the return value onto the stack.
+                lua_pushstring(state, result);
 
                 return 1;
             }
 
-            lua_pushstring(state, "lua_Gamepad_getForm - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Gamepad_getId - Failed to match the given parameters to a valid function signature.");
             lua_error(state);
             break;
         }
@@ -190,7 +194,7 @@ int lua_Gamepad_getForm(lua_State* state)
     return 0;
 }
 
-int lua_Gamepad_getId(lua_State* state)
+int lua_Gamepad_getJoystickCount(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -203,15 +207,15 @@ int lua_Gamepad_getId(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 Gamepad* instance = getInstance(state);
-                const char* result = instance->getId();
+                unsigned int result = instance->getJoystickCount();
 
                 // Push the return value onto the stack.
-                lua_pushstring(state, result);
+                lua_pushunsigned(state, result);
 
                 return 1;
             }
 
-            lua_pushstring(state, "lua_Gamepad_getId - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Gamepad_getJoystickCount - Failed to match the given parameters to a valid function signature.");
             lua_error(state);
             break;
         }
@@ -225,7 +229,7 @@ int lua_Gamepad_getId(lua_State* state)
     return 0;
 }
 
-int lua_Gamepad_getJoystickAxisValues(lua_State* state)
+int lua_Gamepad_getJoystickValues(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -252,12 +256,12 @@ int lua_Gamepad_getJoystickAxisValues(lua_State* state)
                 }
 
                 Gamepad* instance = getInstance(state);
-                instance->getJoystickAxisValues(param1, param2);
+                instance->getJoystickValues(param1, param2);
                 
                 return 0;
             }
 
-            lua_pushstring(state, "lua_Gamepad_getJoystickAxisValues - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Gamepad_getJoystickValues - Failed to match the given parameters to a valid function signature.");
             lua_error(state);
             break;
         }
@@ -271,7 +275,7 @@ int lua_Gamepad_getJoystickAxisValues(lua_State* state)
     return 0;
 }
 
-int lua_Gamepad_getJoystickAxisX(lua_State* state)
+int lua_Gamepad_getProductId(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -279,30 +283,96 @@ int lua_Gamepad_getJoystickAxisX(lua_State* state)
     // Attempt to match the parameters to a valid binding.
     switch (paramCount)
     {
-        case 2:
+        case 1:
         {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER)
+            if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 2);
+                Gamepad* instance = getInstance(state);
+                unsigned int result = instance->getProductId();
+
+                // Push the return value onto the stack.
+                lua_pushunsigned(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Gamepad_getProductId - 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_Gamepad_getProductString(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))
+            {
+                Gamepad* instance = getInstance(state);
+                const char* result = instance->getProductString();
+
+                // Push the return value onto the stack.
+                lua_pushstring(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Gamepad_getProductString - 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_Gamepad_getTriggerCount(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))
+            {
                 Gamepad* instance = getInstance(state);
-                float result = instance->getJoystickAxisX(param1);
+                unsigned int result = instance->getTriggerCount();
 
                 // Push the return value onto the stack.
-                lua_pushnumber(state, result);
+                lua_pushunsigned(state, result);
 
                 return 1;
             }
 
-            lua_pushstring(state, "lua_Gamepad_getJoystickAxisX - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Gamepad_getTriggerCount - 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_pushstring(state, "Invalid number of parameters (expected 1).");
             lua_error(state);
             break;
         }
@@ -310,7 +380,7 @@ int lua_Gamepad_getJoystickAxisX(lua_State* state)
     return 0;
 }
 
-int lua_Gamepad_getJoystickAxisY(lua_State* state)
+int lua_Gamepad_getTriggerValue(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -327,7 +397,7 @@ int lua_Gamepad_getJoystickAxisY(lua_State* state)
                 unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 2);
 
                 Gamepad* instance = getInstance(state);
-                float result = instance->getJoystickAxisY(param1);
+                float result = instance->getTriggerValue(param1);
 
                 // Push the return value onto the stack.
                 lua_pushnumber(state, result);
@@ -335,7 +405,7 @@ int lua_Gamepad_getJoystickAxisY(lua_State* state)
                 return 1;
             }
 
-            lua_pushstring(state, "lua_Gamepad_getJoystickAxisY - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Gamepad_getTriggerValue - Failed to match the given parameters to a valid function signature.");
             lua_error(state);
             break;
         }
@@ -349,7 +419,7 @@ int lua_Gamepad_getJoystickAxisY(lua_State* state)
     return 0;
 }
 
-int lua_Gamepad_getJoystickCount(lua_State* state)
+int lua_Gamepad_getVendorId(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -362,7 +432,7 @@ int lua_Gamepad_getJoystickCount(lua_State* state)
             if ((lua_type(state, 1) == LUA_TUSERDATA))
             {
                 Gamepad* instance = getInstance(state);
-                unsigned int result = instance->getJoystickCount();
+                unsigned int result = instance->getVendorId();
 
                 // Push the return value onto the stack.
                 lua_pushunsigned(state, result);
@@ -370,7 +440,7 @@ int lua_Gamepad_getJoystickCount(lua_State* state)
                 return 1;
             }
 
-            lua_pushstring(state, "lua_Gamepad_getJoystickCount - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Gamepad_getVendorId - Failed to match the given parameters to a valid function signature.");
             lua_error(state);
             break;
         }
@@ -384,7 +454,42 @@ int lua_Gamepad_getJoystickCount(lua_State* state)
     return 0;
 }
 
-int lua_Gamepad_isJoystickActive(lua_State* state)
+int lua_Gamepad_getVendorString(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))
+            {
+                Gamepad* instance = getInstance(state);
+                const char* result = instance->getVendorString();
+
+                // Push the return value onto the stack.
+                lua_pushstring(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Gamepad_getVendorString - 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_Gamepad_isButtonDown(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -395,13 +500,13 @@ int lua_Gamepad_isJoystickActive(lua_State* state)
         case 2:
         {
             if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER)
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
             {
                 // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 2);
+                Gamepad::ButtonMapping param1 = (Gamepad::ButtonMapping)lua_enumFromString_GamepadButtonMapping(luaL_checkstring(state, 2));
 
                 Gamepad* instance = getInstance(state);
-                bool result = instance->isJoystickActive(param1);
+                bool result = instance->isButtonDown(param1);
 
                 // Push the return value onto the stack.
                 lua_pushboolean(state, result);
@@ -409,7 +514,7 @@ int lua_Gamepad_isJoystickActive(lua_State* state)
                 return 1;
             }
 
-            lua_pushstring(state, "lua_Gamepad_isJoystickActive - Failed to match the given parameters to a valid function signature.");
+            lua_pushstring(state, "lua_Gamepad_isButtonDown - Failed to match the given parameters to a valid function signature.");
             lua_error(state);
             break;
         }
@@ -458,6 +563,43 @@ int lua_Gamepad_isVirtual(lua_State* state)
     return 0;
 }
 
+int lua_Gamepad_static_getGamepads(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 0:
+        {
+            void* returnPtr = (void*)Gamepad::getGamepads();
+            if (returnPtr)
+            {
+                ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                object->instance = returnPtr;
+                object->owns = false;
+                luaL_getmetatable(state, "Gamepad");
+                lua_setmetatable(state, -2);
+            }
+            else
+            {
+                lua_pushnil(state);
+            }
+
+            return 1;
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 0).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Gamepad_update(lua_State* state)
 {
     // Get the number of parameters.

+ 9 - 5
gameplay/src/lua/lua_Gamepad.h

@@ -7,15 +7,19 @@ namespace gameplay
 // Lua bindings for Gamepad.
 int lua_Gamepad_draw(lua_State* state);
 int lua_Gamepad_getButtonCount(lua_State* state);
-int lua_Gamepad_getButtonState(lua_State* state);
 int lua_Gamepad_getForm(lua_State* state);
 int lua_Gamepad_getId(lua_State* state);
-int lua_Gamepad_getJoystickAxisValues(lua_State* state);
-int lua_Gamepad_getJoystickAxisX(lua_State* state);
-int lua_Gamepad_getJoystickAxisY(lua_State* state);
 int lua_Gamepad_getJoystickCount(lua_State* state);
-int lua_Gamepad_isJoystickActive(lua_State* state);
+int lua_Gamepad_getJoystickValues(lua_State* state);
+int lua_Gamepad_getProductId(lua_State* state);
+int lua_Gamepad_getProductString(lua_State* state);
+int lua_Gamepad_getTriggerCount(lua_State* state);
+int lua_Gamepad_getTriggerValue(lua_State* state);
+int lua_Gamepad_getVendorId(lua_State* state);
+int lua_Gamepad_getVendorString(lua_State* state);
+int lua_Gamepad_isButtonDown(lua_State* state);
 int lua_Gamepad_isVirtual(lua_State* state);
+int lua_Gamepad_static_getGamepads(lua_State* state);
 int lua_Gamepad_update(lua_State* state);
 
 void luaRegister_Gamepad();

+ 0 - 33
gameplay/src/lua/lua_GamepadButtonState.cpp

@@ -1,33 +0,0 @@
-#include "Base.h"
-#include "lua_GamepadButtonState.h"
-
-namespace gameplay
-{
-
-static const char* enumStringEmpty = "";
-
-static const char* luaEnumString_GamepadButtonState_BUTTON_PRESSED = "BUTTON_PRESSED";
-static const char* luaEnumString_GamepadButtonState_BUTTON_RELEASED = "BUTTON_RELEASED";
-
-Gamepad::ButtonState lua_enumFromString_GamepadButtonState(const char* s)
-{
-    if (strcmp(s, luaEnumString_GamepadButtonState_BUTTON_PRESSED) == 0)
-        return Gamepad::BUTTON_PRESSED;
-    if (strcmp(s, luaEnumString_GamepadButtonState_BUTTON_RELEASED) == 0)
-        return Gamepad::BUTTON_RELEASED;
-    GP_ERROR("Invalid enumeration value '%s' for enumeration Gamepad::ButtonState.", s);
-    return Gamepad::BUTTON_PRESSED;
-}
-
-const char* lua_stringFromEnum_GamepadButtonState(Gamepad::ButtonState e)
-{
-    if (e == Gamepad::BUTTON_PRESSED)
-        return luaEnumString_GamepadButtonState_BUTTON_PRESSED;
-    if (e == Gamepad::BUTTON_RELEASED)
-        return luaEnumString_GamepadButtonState_BUTTON_RELEASED;
-    GP_ERROR("Invalid enumeration value '%d' for enumeration Gamepad::ButtonState.", e);
-    return enumStringEmpty;
-}
-
-}
-

+ 0 - 15
gameplay/src/lua/lua_GamepadButtonState.h

@@ -1,15 +0,0 @@
-#ifndef LUA_GAMEPADBUTTONSTATE_H_
-#define LUA_GAMEPADBUTTONSTATE_H_
-
-#include "Gamepad.h"
-
-namespace gameplay
-{
-
-// Lua bindings for enum conversion functions for Gamepad::ButtonState.
-Gamepad::ButtonState lua_enumFromString_GamepadButtonState(const char* s);
-const char* lua_stringFromEnum_GamepadButtonState(Gamepad::ButtonState e);
-
-}
-
-#endif

+ 29 - 5
gameplay/src/lua/lua_Global.cpp

@@ -11,6 +11,7 @@ void luaRegister_lua_Global()
     ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Container");
     ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Control");
     ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Form");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "GamepadButton");
     ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Joint");
     ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Joystick");
     ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Label");
@@ -21,12 +22,14 @@ void luaRegister_lua_Global()
     ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "TextBox");
     ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Transform");
     ScriptUtil::setGlobalHierarchyPair("Button", "CheckBox");
+    ScriptUtil::setGlobalHierarchyPair("Button", "GamepadButton");
     ScriptUtil::setGlobalHierarchyPair("Button", "RadioButton");
     ScriptUtil::setGlobalHierarchyPair("Container", "Form");
     ScriptUtil::setGlobalHierarchyPair("Control", "Button");
     ScriptUtil::setGlobalHierarchyPair("Control", "CheckBox");
     ScriptUtil::setGlobalHierarchyPair("Control", "Container");
     ScriptUtil::setGlobalHierarchyPair("Control", "Form");
+    ScriptUtil::setGlobalHierarchyPair("Control", "GamepadButton");
     ScriptUtil::setGlobalHierarchyPair("Control", "Joystick");
     ScriptUtil::setGlobalHierarchyPair("Control", "Label");
     ScriptUtil::setGlobalHierarchyPair("Control", "RadioButton");
@@ -34,6 +37,7 @@ void luaRegister_lua_Global()
     ScriptUtil::setGlobalHierarchyPair("Control", "TextBox");
     ScriptUtil::setGlobalHierarchyPair("Label", "Button");
     ScriptUtil::setGlobalHierarchyPair("Label", "CheckBox");
+    ScriptUtil::setGlobalHierarchyPair("Label", "GamepadButton");
     ScriptUtil::setGlobalHierarchyPair("Label", "RadioButton");
     ScriptUtil::setGlobalHierarchyPair("Label", "Slider");
     ScriptUtil::setGlobalHierarchyPair("Label", "TextBox");
@@ -74,6 +78,7 @@ void luaRegister_lua_Global()
     ScriptUtil::setGlobalHierarchyPair("Ref", "Font");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Form");
     ScriptUtil::setGlobalHierarchyPair("Ref", "FrameBuffer");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "GamepadButton");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Image");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Joint");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Joystick");
@@ -112,6 +117,7 @@ void luaRegister_lua_Global()
     ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Container");
     ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Control");
     ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Form");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "GamepadButton");
     ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Joint");
     ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Joystick");
     ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Label");
@@ -342,12 +348,30 @@ void luaRegister_lua_Global()
         ScriptUtil::registerConstantString("PAUSED", "PAUSED", scopePath);
     }
 
-    // Register enumeration Gamepad::ButtonState.
+    // Register enumeration Gamepad::ButtonMapping.
     {
         std::vector<std::string> scopePath;
         scopePath.push_back("Gamepad");
-        ScriptUtil::registerConstantString("BUTTON_PRESSED", "BUTTON_PRESSED", scopePath);
-        ScriptUtil::registerConstantString("BUTTON_RELEASED", "BUTTON_RELEASED", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_A", "BUTTON_A", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_B", "BUTTON_B", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_C", "BUTTON_C", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_X", "BUTTON_X", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_Y", "BUTTON_Y", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_Z", "BUTTON_Z", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_MENU1", "BUTTON_MENU1", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_MENU2", "BUTTON_MENU2", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_MENU3", "BUTTON_MENU3", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_MENU4", "BUTTON_MENU4", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_L1", "BUTTON_L1", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_L2", "BUTTON_L2", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_L3", "BUTTON_L3", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_R1", "BUTTON_R1", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_R2", "BUTTON_R2", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_R3", "BUTTON_R3", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_UP", "BUTTON_UP", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_DOWN", "BUTTON_DOWN", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_LEFT", "BUTTON_LEFT", scopePath);
+        ScriptUtil::registerConstantString("BUTTON_RIGHT", "BUTTON_RIGHT", scopePath);
     }
 
     // Register enumeration Gamepad::GamepadEvent.
@@ -818,8 +842,8 @@ const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value)
         return lua_stringFromEnum_GameClearFlags((Game::ClearFlags)value);
     if (enumname == "Game::State")
         return lua_stringFromEnum_GameState((Game::State)value);
-    if (enumname == "Gamepad::ButtonState")
-        return lua_stringFromEnum_GamepadButtonState((Gamepad::ButtonState)value);
+    if (enumname == "Gamepad::ButtonMapping")
+        return lua_stringFromEnum_GamepadButtonMapping((Gamepad::ButtonMapping)value);
     if (enumname == "Gamepad::GamepadEvent")
         return lua_stringFromEnum_GamepadGamepadEvent((Gamepad::GamepadEvent)value);
     if (enumname == "Gesture::GestureEvent")

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

@@ -15,7 +15,7 @@
 #include "lua_FontStyle.h"
 #include "lua_GameClearFlags.h"
 #include "lua_GameState.h"
-#include "lua_GamepadButtonState.h"
+#include "lua_GamepadButtonMapping.h"
 #include "lua_GamepadGamepadEvent.h"
 #include "lua_GestureGestureEvent.h"
 #include "lua_ImageFormat.h"

+ 36 - 0
gameplay/src/lua/lua_Joystick.cpp

@@ -53,6 +53,7 @@ void luaRegister_Joystick()
         {"getImageColor", lua_Joystick_getImageColor},
         {"getImageRegion", lua_Joystick_getImageRegion},
         {"getImageUVs", lua_Joystick_getImageUVs},
+        {"getIndex", lua_Joystick_getIndex},
         {"getInnerRegionSize", lua_Joystick_getInnerRegionSize},
         {"getMargin", lua_Joystick_getMargin},
         {"getOpacity", lua_Joystick_getOpacity},
@@ -1724,6 +1725,41 @@ int lua_Joystick_getImageUVs(lua_State* state)
     return 0;
 }
 
+int lua_Joystick_getIndex(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))
+            {
+                Joystick* instance = getInstance(state);
+                unsigned int result = instance->getIndex();
+
+                // Push the return value onto the stack.
+                lua_pushunsigned(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Joystick_getIndex - 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_Joystick_getInnerRegionSize(lua_State* state)
 {
     // Get the number of parameters.

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

@@ -35,6 +35,7 @@ int lua_Joystick_getId(lua_State* state);
 int lua_Joystick_getImageColor(lua_State* state);
 int lua_Joystick_getImageRegion(lua_State* state);
 int lua_Joystick_getImageUVs(lua_State* state);
+int lua_Joystick_getIndex(lua_State* state);
 int lua_Joystick_getInnerRegionSize(lua_State* state);
 int lua_Joystick_getMargin(lua_State* state);
 int lua_Joystick_getOpacity(lua_State* state);

+ 41 - 478
gameplay/src/lua/lua_Platform.cpp

@@ -25,20 +25,8 @@ void luaRegister_Platform()
         {"getAccelerometerValues", lua_Platform_static_getAccelerometerValues},
         {"getDisplayHeight", lua_Platform_static_getDisplayHeight},
         {"getDisplayWidth", lua_Platform_static_getDisplayWidth},
-        {"getGamepadButtonCount", lua_Platform_static_getGamepadButtonCount},
-        {"getGamepadButtonState", lua_Platform_static_getGamepadButtonState},
-        {"getGamepadId", lua_Platform_static_getGamepadId},
-        {"getGamepadJoystickAxisValues", lua_Platform_static_getGamepadJoystickAxisValues},
-        {"getGamepadJoystickAxisX", lua_Platform_static_getGamepadJoystickAxisX},
-        {"getGamepadJoystickAxisY", lua_Platform_static_getGamepadJoystickAxisY},
-        {"getGamepadJoystickCount", lua_Platform_static_getGamepadJoystickCount},
-        {"getGamepadTriggerCount", lua_Platform_static_getGamepadTriggerCount},
-        {"getGamepadTriggerValue", lua_Platform_static_getGamepadTriggerValue},
-        {"getGamepadsConnected", lua_Platform_static_getGamepadsConnected},
         {"hasMouse", lua_Platform_static_hasMouse},
         {"isCursorVisible", lua_Platform_static_isCursorVisible},
-        {"isGamepadConnected", lua_Platform_static_isGamepadConnected},
-        {"isGamepadJoystickActive", lua_Platform_static_isGamepadJoystickActive},
         {"isGestureRegistered", lua_Platform_static_isGestureRegistered},
         {"isGestureSupported", lua_Platform_static_isGestureSupported},
         {"isMouseCaptured", lua_Platform_static_isMouseCaptured},
@@ -47,6 +35,7 @@ void luaRegister_Platform()
         {"keyEventInternal", lua_Platform_static_keyEventInternal},
         {"launchURL", lua_Platform_static_launchURL},
         {"mouseEventInternal", lua_Platform_static_mouseEventInternal},
+        {"pollGamepadState", lua_Platform_static_pollGamepadState},
         {"registerGesture", lua_Platform_static_registerGesture},
         {"setAbsoluteTime", lua_Platform_static_setAbsoluteTime},
         {"setCursorVisible", lua_Platform_static_setCursorVisible},
@@ -329,394 +318,6 @@ int lua_Platform_static_getDisplayWidth(lua_State* state)
     return 0;
 }
 
-int lua_Platform_static_getGamepadButtonCount(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_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                unsigned int result = Platform::getGamepadButtonCount(param1);
-
-                // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadButtonCount - 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_Platform_static_getGamepadButtonState(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_TNUMBER &&
-                lua_type(state, 2) == LUA_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                // Get parameter 2 off the stack.
-                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                bool result = Platform::getGamepadButtonState(param1, param2);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadButtonState - 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_Platform_static_getGamepadId(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_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                const char* result = Platform::getGamepadId(param1);
-
-                // Push the return value onto the stack.
-                lua_pushstring(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadId - 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_Platform_static_getGamepadJoystickAxisValues(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 3:
-        {
-            if (lua_type(state, 1) == LUA_TNUMBER &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                (lua_type(state, 3) == LUA_TUSERDATA || lua_type(state, 3) == LUA_TTABLE || lua_type(state, 3) == LUA_TNIL))
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                // Get parameter 2 off the stack.
-                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                // Get parameter 3 off the stack.
-                bool param3Valid;
-                ScriptUtil::LuaArray<Vector2> param3 = ScriptUtil::getObjectPointer<Vector2>(3, "Vector2", false, &param3Valid);
-                if (!param3Valid)
-                {
-                    lua_pushstring(state, "Failed to convert parameter 3 to type 'Vector2'.");
-                    lua_error(state);
-                }
-
-                Platform::getGamepadJoystickAxisValues(param1, param2, param3);
-                
-                return 0;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadJoystickAxisValues - 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).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Platform_static_getGamepadJoystickAxisX(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_TNUMBER &&
-                lua_type(state, 2) == LUA_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                // Get parameter 2 off the stack.
-                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                float result = Platform::getGamepadJoystickAxisX(param1, param2);
-
-                // Push the return value onto the stack.
-                lua_pushnumber(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadJoystickAxisX - 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_Platform_static_getGamepadJoystickAxisY(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_TNUMBER &&
-                lua_type(state, 2) == LUA_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                // Get parameter 2 off the stack.
-                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                float result = Platform::getGamepadJoystickAxisY(param1, param2);
-
-                // Push the return value onto the stack.
-                lua_pushnumber(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadJoystickAxisY - 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_Platform_static_getGamepadJoystickCount(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_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                unsigned int result = Platform::getGamepadJoystickCount(param1);
-
-                // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadJoystickCount - 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_Platform_static_getGamepadTriggerCount(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_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                unsigned int result = Platform::getGamepadTriggerCount(param1);
-
-                // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadTriggerCount - 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_Platform_static_getGamepadTriggerValue(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_TNUMBER &&
-                lua_type(state, 2) == LUA_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                // Get parameter 2 off the stack.
-                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                float result = Platform::getGamepadTriggerValue(param1, param2);
-
-                // Push the return value onto the stack.
-                lua_pushnumber(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_getGamepadTriggerValue - 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_Platform_static_getGamepadsConnected(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 0:
-        {
-            unsigned int result = Platform::getGamepadsConnected();
-
-            // Push the return value onto the stack.
-            lua_pushunsigned(state, result);
-
-            return 1;
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 0).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
 int lua_Platform_static_hasMouse(lua_State* state)
 {
     // Get the number of parameters.
@@ -773,84 +374,6 @@ int lua_Platform_static_isCursorVisible(lua_State* state)
     return 0;
 }
 
-int lua_Platform_static_isGamepadConnected(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_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                bool result = Platform::isGamepadConnected(param1);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_isGamepadConnected - 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_Platform_static_isGamepadJoystickActive(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_TNUMBER &&
-                lua_type(state, 2) == LUA_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                // Get parameter 2 off the stack.
-                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                bool result = Platform::isGamepadJoystickActive(param1, param2);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Platform_static_isGamepadJoystickActive - 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_Platform_static_isGestureRegistered(lua_State* state)
 {
     // Get the number of parameters.
@@ -1133,6 +656,46 @@ int lua_Platform_static_mouseEventInternal(lua_State* state)
     return 0;
 }
 
+int lua_Platform_static_pollGamepadState(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 || lua_type(state, 1) == LUA_TTABLE || lua_type(state, 1) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                bool param1Valid;
+                ScriptUtil::LuaArray<Gamepad> param1 = ScriptUtil::getObjectPointer<Gamepad>(1, "Gamepad", false, &param1Valid);
+                if (!param1Valid)
+                {
+                    lua_pushstring(state, "Failed to convert parameter 1 to type 'Gamepad'.");
+                    lua_error(state);
+                }
+
+                Platform::pollGamepadState(param1);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_Platform_static_pollGamepadState - 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_Platform_static_registerGesture(lua_State* state)
 {
     // Get the number of parameters.

+ 1 - 12
gameplay/src/lua/lua_Platform.h

@@ -13,20 +13,8 @@ int lua_Platform_static_getAbsoluteTime(lua_State* state);
 int lua_Platform_static_getAccelerometerValues(lua_State* state);
 int lua_Platform_static_getDisplayHeight(lua_State* state);
 int lua_Platform_static_getDisplayWidth(lua_State* state);
-int lua_Platform_static_getGamepadButtonCount(lua_State* state);
-int lua_Platform_static_getGamepadButtonState(lua_State* state);
-int lua_Platform_static_getGamepadId(lua_State* state);
-int lua_Platform_static_getGamepadJoystickAxisValues(lua_State* state);
-int lua_Platform_static_getGamepadJoystickAxisX(lua_State* state);
-int lua_Platform_static_getGamepadJoystickAxisY(lua_State* state);
-int lua_Platform_static_getGamepadJoystickCount(lua_State* state);
-int lua_Platform_static_getGamepadTriggerCount(lua_State* state);
-int lua_Platform_static_getGamepadTriggerValue(lua_State* state);
-int lua_Platform_static_getGamepadsConnected(lua_State* state);
 int lua_Platform_static_hasMouse(lua_State* state);
 int lua_Platform_static_isCursorVisible(lua_State* state);
-int lua_Platform_static_isGamepadConnected(lua_State* state);
-int lua_Platform_static_isGamepadJoystickActive(lua_State* state);
 int lua_Platform_static_isGestureRegistered(lua_State* state);
 int lua_Platform_static_isGestureSupported(lua_State* state);
 int lua_Platform_static_isMouseCaptured(lua_State* state);
@@ -35,6 +23,7 @@ int lua_Platform_static_isVsync(lua_State* state);
 int lua_Platform_static_keyEventInternal(lua_State* state);
 int lua_Platform_static_launchURL(lua_State* state);
 int lua_Platform_static_mouseEventInternal(lua_State* state);
+int lua_Platform_static_pollGamepadState(lua_State* state);
 int lua_Platform_static_registerGesture(lua_State* state);
 int lua_Platform_static_setAbsoluteTime(lua_State* state);
 int lua_Platform_static_setCursorVisible(lua_State* state);

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

@@ -45,6 +45,7 @@ void lua_RegisterAllBindings()
     luaRegister_Frustum();
     luaRegister_Game();
     luaRegister_Gamepad();
+    luaRegister_GamepadButton();
     luaRegister_Gesture();
     luaRegister_Image();
     luaRegister_Joint();

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

@@ -40,6 +40,7 @@
 #include "lua_Frustum.h"
 #include "lua_Game.h"
 #include "lua_Gamepad.h"
+#include "lua_GamepadButton.h"
 #include "lua_Gesture.h"
 #include "lua_Image.h"
 #include "lua_Joint.h"