Skip to content

Instantly share code, notes, and snippets.

@BanditTech
Created March 26, 2020 05:49
Show Gist options
  • Save BanditTech/20880ae5e55af816e8af62f0962ee5be to your computer and use it in GitHub Desktop.
Save BanditTech/20880ae5e55af816e8af62f0962ee5be to your computer and use it in GitHub Desktop.
XInput Controller Testbench
; Example: Control the vibration motors using the analog triggers of each controller.
XInput_Init()
deadzone := 10
Global Controller := {}
Controller.Btn := {}
Global GameX, GameY, GameW, GameH
while !WinExist("Path of Exile")
sleep, 100
WinGetPos, GameX, GameY, GameW, GameH
global y_offset := 150
Global x_center := GameX + GameW / 2
Global compensation := (GameW / GameH) == (16 / 10) ? 1.103829 : 1.103719
Global y_center := GameY + GameH / 2 / compensation
Global offset_mod := y_offset / GameH
Global x_offset := GameW * (offset_mod / 1.5 )
Global ScrCenter := { "X" : GameX + Round(GameW / 2) , "Y" : GameY + Round(GameH / 2) }
Global GameWindow := {"X" : GameX, "Y" : GameY, "W" : GameW, "H" : GameH, "BBarY" : (GameY + (GameH / (1080 / 75))) }
Global Controller_Active := 0
DetectJoystick()
{
If XInput_GetState(Controller_Active)
Return Controller_Active
Else
{
Loop, 4
{
If XInput_GetState(A_Index)
{
Return Controller_Active := A_Index
}
}
Return False
}
}
Controller_Rumble(){
RumbleX=0
RumbleY=0
If (Abs(LX) >= deadzone || Abs(LY) >= deadzone)
RumbleX += Abs(LX)*257*2.55, RumbleY += Abs(LY)*257*2.55
If (Abs(RX) >= deadzone || Abs(RY) >= deadzone)
RumbleX += Abs(RX)*257*2.55, RumbleY += Abs(RY)*257*2.55
If (LT || RT)
RumbleX += LT*257, RumbleY += RT*257
;Maximum rumble value 0-65535
XInput_SetState(A_Index-1, CapRange(RumbleX), CapRange(RumbleY))
return
}
Controller_Refresh(tt:=0){
Global Controller
if State := XInput_GetState(Controller_Active)
{
Static oldStatus := ""
Status := ""
; LX,LY,RX,RY,LT,RT,A,B,X,Y,LB,RB,L3,R3,BACK,START,UP,DOWN,LEFT,RIGHT
Controller.LX := PercentAxis( State.sThumbLX )
Controller.LY := PercentAxis( State.sThumbLY )
Controller.RX := PercentAxis( State.sThumbRX )
Controller.RY := PercentAxis( State.sThumbRY )
If (Controller.LT := State.bLeftTrigger)
Status .= "LT,"
If (Controller.RT := State.bRightTrigger)
Status .= "RT,"
If (Controller.Btn.A := XInputButtonIsDown( "A", State.wButtons ))
Status .= "A,"
If (Controller.Btn.B := XInputButtonIsDown( "B", State.wButtons ))
Status .= "B,"
If (Controller.Btn.X := XInputButtonIsDown( "X", State.wButtons ))
Status .= "X,"
If (Controller.Btn.Y := XInputButtonIsDown( "Y", State.wButtons ))
Status .= "Y,"
If (Controller.Btn.LB := XInputButtonIsDown( "LB", State.wButtons ))
Status .= "LB,"
If (Controller.Btn.RB := XInputButtonIsDown( "RB", State.wButtons ))
Status .= "RB,"
If (Controller.Btn.L3 := XInputButtonIsDown( "LStick", State.wButtons ))
Status .= "L3,"
If (Controller.Btn.R3 := XInputButtonIsDown( "RStick", State.wButtons ))
Status .= "R3,"
If (Controller.Btn.BACK := XInputButtonIsDown( "Back", State.wButtons ))
Status .= "BACK,"
If (Controller.Btn.START := XInputButtonIsDown( "Start", State.wButtons ))
Status .= "START,"
If (Controller.Btn.UP := XInputButtonIsDown( "PovUp", State.wButtons ))
Status .= "UP,"
If (Controller.Btn.DOWN := XInputButtonIsDown( "PovDown", State.wButtons ))
Status .= "DOWN,"
If (Controller.Btn.LEFT := XInputButtonIsDown( "PovLeft", State.wButtons ))
Status .= "LEFT,"
If (Controller.Btn.RIGHT := XInputButtonIsDown( "PovRight", State.wButtons ))
Status .= "RIGHT,"
If (tt && status != "" && oldStatus != status){
oldStatus := status
Tooltip, %status%
} else if (tt && status = "" && oldStatus != status){
oldStatus := status
Tooltip,
}
}
Else
DetectJoystick()
return
}
Controller_Keypress(){
Global Controller
for key, state in Controller.Btn
{
if ((!(Controller.LT && Controller.RT) || (Controller.LT && Controller.RT && !state)) && KeyActions[key].LR.pressed) {
Send, % KeyActions[key].LR.mod "{" KeyActions[key].LR.key " up}"
KeyActions[key].LR.pressed := false
}
if ((!Controller.LT || (Controller.LT && !state)) && KeyActions[key].L.pressed) {
Send, % KeyActions[key].L.mod "{" KeyActions[key].L.key " up}"
KeyActions[key].L.pressed := false
}
if ((!Controller.RT || (Controller.RT && !state)) && KeyActions[key].R.pressed) {
Send, % KeyActions[key].R.mod "{" KeyActions[key].R.key " up}"
KeyActions[key].R.pressed := false
}
if (!state && IsDown[key].I.pressed) {
Send, % KeyActions[key].I.mod "{" KeyActions[key].I.key " up}"
KeyActions[key].I.pressed := false
}
if (!state && IsDown[key].D.pressed) {
Send, % KeyActions[key].D.mod "{" KeyActions[key].D.key " up}"
KeyActions[key].D.pressed := false
}
if !state
Continue
if ((Controller.LT && Controller.RT) && KeyActions[key].LR.set != "inherit")
triggered := "LR"
else if (Controller.LT && KeyActions[key].L.set != "inherit")
triggered := "L"
else if (Controller.RT && KeyActions[key].R.set != "inherit")
triggered := "R"
else if ((OnInventory || OnStash || OnVendor) && KeyActions[key].I.set != "inherit")
triggered := "I"
else
triggered := "D"
if (KeyActions[key][triggered].set = "inherit" || KeyActions[key][triggered].set = "" || KeyActions[key][triggered].set = "unset")
return
Send, % KeyActions[key][triggered].mod "{" KeyActions[key][triggered].key " down}"
KeyActions[key][triggered].pressed :=True
}
}
Controller_BuildKeys() {
Global KeyActions := { "A" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"B" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"X" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"Y" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"LB" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"RB" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"L3" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"R3" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"BACK" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"START" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"UP" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"DOWN" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"LEFT" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} }
,"RIGHT" : { "D": {"set":"unset", "mod":"", "key":"", "pressed":false} , "I": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "L": {"set":"inherit", "mod":"", "key":"", "pressed":false} , "R": {"set":"inherit", "mod":"", "key":"", "pressed":false}, "LR": {"set":"inherit", "mod":"", "key":"", "pressed":false} } }
for key, actions in KeyActions
{
for type, modifier in actions
{
if (modifier.set != "unset" || modifier.set != "inherit" || modifier.set != "default" || modifier.set != "")
{
Modifiers := String := ""
for k, Letter in StrSplit(modifier.set) {
if (IsModifier(Letter)) {
Modifiers .= Letter
}
else {
String .= Letter
}
}
modifier.mod := Modifiers
modifier.key := String
}
}
}
}
XInputButtonState( bsButtonState )
{
If XInputButtonIsDown( "A", bsButtonState )
Status .= "A,"
If XInputButtonIsDown( "B", bsButtonState )
Status .= "B,"
If XInputButtonIsDown( "X", bsButtonState )
Status .= "X,"
If XInputButtonIsDown( "Y", bsButtonState )
Status .= "Y,"
If XInputButtonIsDown( "LB", bsButtonState )
Status .= "LB,"
If XInputButtonIsDown( "RB", bsButtonState )
Status .= "RB,"
If XInputButtonIsDown( "LStick", bsButtonState )
Status .= "LStick,"
If XInputButtonIsDown( "RStick", bsButtonState )
Status .= "RStick,"
If XInputButtonIsDown( "Back", bsButtonState )
Status .= "Back,"
If XInputButtonIsDown( "Start", bsButtonState )
Status .= "Start,"
If XInputButtonIsDown( "PovUp", bsButtonState )
Status .= "PovUp,"
If XInputButtonIsDown( "PovDown", bsButtonState )
Status .= "PovDown,"
If XInputButtonIsDown( "PovLeft", bsButtonState )
Status .= "PovLeft,"
If XInputButtonIsDown( "PovRight", bsButtonState )
Status .= "PovRight,"
Return SubStr( Status, 1, -1 ) ; Omit the trailing comma
}
Loop
{
Controller_Refresh()
Controller("JoystickL")
Controller("JoystickR")
Sleep, 15
}
Controller(inputType:="JoystickL")
{
Static JoyLHoldCount:=0, JoyRHoldCount:=0, LClicked := False, RClicked := False
, JoyMultiplier := 3, YAxisMultiplier := .6
If (inputType = "JoystickL")
{
moveX := DeadZone(Controller.LX)
moveY := DeadZone(Controller.LY)
If (moveX || moveY)
{
MouseMove,% x_center + Controller.LX * JoyMultiplier, % y_center - Controller.LY * JoyMultiplier
++JoyLHoldCount
If (!LClicked && JoyLHoldCount > 0)
{
Click, Down
LClicked := True
}
}
Else
{
If LClicked
{
Click, Up
LClicked := False
}
JoyLHoldCount := 0
Return
}
}
Else If (inputType = "JoystickR")
{
moveX := DeadZone(Controller.RX)
moveY := DeadZone(Controller.RY)
If (moveX || moveY)
{
MouseMove,% x_center + Controller.RX * JoyMultiplier, % y_center - Controller.RY * JoyMultiplier
++JoyRHoldCount
If (!RClicked && JoyRHoldCount > 0)
{
Send {RButton Down}
RClicked := True
}
}
Else
{
If RClicked
{
Send {RButton Up}
RClicked := False
}
JoyRHoldCount := 0
Return
}
}
Return
}
Joystick2_Handler:
IfWinActive ahk_group POEGameGroup
{
If (!JoystickActive || !YesController)
{
SetTimer, Joystick2_Handler, off
Return
}
MouseNeedsToBeMoved := false ; Set default.
SetFormat, float, 03
GetKeyState, JoyX, %JoystickNumber%JoyU
GetKeyState, JoyY, %JoystickNumber%JoyR
if (JoyX < Joy2ThresholdUpper) && (JoyX > Joy2ThresholdLower)
{
DeltaX = 0
}
else if (JoyX > Joy2ThresholdUpper)
{
MouseNeedsToBeMoved := true
DeltaX := JoyX - Joy2ThresholdUpper
}
else if (JoyX < Joy2ThresholdLower) && (JoyX != -1)
{
MouseNeedsToBeMoved := true
DeltaX := JoyX - JoyThresholdLower
}
else
DeltaX = 0
if (JoyY < Joy2ThresholdUpper) && (JoyY > Joy2ThresholdLower)
{
DeltaY = 0
}
else if (JoyY > Joy2ThresholdUpper)
{
MouseNeedsToBeMoved := true
DeltaY := JoyY - Joy2ThresholdUpper
}
else if (JoyY < Joy2ThresholdLower) && (JoyY != -1)
{
MouseNeedsToBeMoved := true
DeltaY := JoyY - JoyThresholdLower
}
else
DeltaY = 0
if MouseNeedsToBeMoved
{
MouseMove, x_center + DeltaX * JoyMultiplier2, y_center + DeltaY * JoyMultiplier2 * YAxisMultiplier
++HeldCountJoystick2
;Ding(500,1,"Count: " . HeldCountJoystick2)
if (YesTriggerJoystick2Key && !checkvarJoy2 && HeldCountJoystick2 > 6)
{
Send {%hotkeyControllerJoystick2% down}
checkvarJoy2 := True
}
}
Else If (checkvarJoy2)
{
Send {%hotkeyControllerJoystick2% up}
checkvarJoy2 := False
HeldCountJoystick2 := 0
}
}
return
DeadZone(val, deadzone:=10 )
{
Return (Abs(val)<deadzone?False:True)
}
CapRange(var,min:=0,max:=65535)
{
return (var > max ? max : (var < min ? min : var))
}
PercentAxis(axisPos)
{
If (axisPos = 0)
Return False
Else If (axisPos > 0)
Positive := True
Else
Positive := False
Percentage := Round((axisPos / (Positive?32767:32768)) * 100 ,2)
Return Percentage
}
; XInputButtonIsDown functions found - https://autohotkey.com/board/topic/35848-xinput-xbox-360-controller-api/
XInputButtonIsDown( ButtonName, bidButtonState )
{
; Constants for gamepad buttons
Static PovUp = 0x0001
, PovDown = 0x0002
, PovLeft = 0x0004
, PovRight = 0x0008
, Start = 0x0010
, Back = 0x0020
, LStick = 0x0040
, RStick = 0x0080
, LB = 0x0100
, RB = 0x0200
, A = 0x1000
, B = 0x2000
, X = 0x4000
, Y = 0x8000
isDown := false ; If something screws up, we want to return false.
If ( bidButtonState & %ButtonName% )
isDown := true ; Return true if bidButtonState matches ButtonName
Else isDown := false ; Return false otherwise
Return %isDown%
}
/* XInput by Lexikos
* This version of the script uses objects, so requires AutoHotkey_L.
*/
/*
Function: XInput_Init
Initializes XInput.ahk with the given XInput DLL.
Parameters:
dll - The path or name of the XInput DLL to load.
*/
XInput_Init(dll="xinput1_3")
{
global
if _XInput_hm
return
;======== CONSTANTS DEFINED IN XINPUT.H ========
; NOTE: These are based on my outdated copy of the DirectX SDK.
; Newer versions of XInput may require additional constants.
; Device types available in XINPUT_CAPABILITIES
XINPUT_DEVTYPE_GAMEPAD := 0x01
; Device subtypes available in XINPUT_CAPABILITIES
XINPUT_DEVSUBTYPE_GAMEPAD := 0x01
; Flags for XINPUT_CAPABILITIES
XINPUT_CAPS_VOICE_SUPPORTED := 0x0004
; Constants for gamepad buttons
XINPUT_GAMEPAD_DPAD_UP := 0x0001
XINPUT_GAMEPAD_DPAD_DOWN := 0x0002
XINPUT_GAMEPAD_DPAD_LEFT := 0x0004
XINPUT_GAMEPAD_DPAD_RIGHT := 0x0008
XINPUT_GAMEPAD_START := 0x0010
XINPUT_GAMEPAD_BACK := 0x0020
XINPUT_GAMEPAD_LEFT_THUMB := 0x0040
XINPUT_GAMEPAD_RIGHT_THUMB := 0x0080
XINPUT_GAMEPAD_LEFT_SHOULDER := 0x0100
XINPUT_GAMEPAD_RIGHT_SHOULDER := 0x0200
XINPUT_GAMEPAD_A := 0x1000
XINPUT_GAMEPAD_B := 0x2000
XINPUT_GAMEPAD_X := 0x4000
XINPUT_GAMEPAD_Y := 0x8000
; Gamepad thresholds
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE := 7849
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE := 8689
XINPUT_GAMEPAD_TRIGGER_THRESHOLD := 30
; Flags to pass to XInputGetCapabilities
XINPUT_FLAG_GAMEPAD := 0x00000001
;=============== END CONSTANTS =================
_XInput_hm := DllCall("LoadLibrary" ,"str",dll)
if !_XInput_hm
{
MsgBox, Failed to initialize XInput: %dll%.dll not found.
return
}
_XInput_GetState := DllCall("GetProcAddress" ,"ptr",_XInput_hm ,"astr","XInputGetState")
_XInput_SetState := DllCall("GetProcAddress" ,"ptr",_XInput_hm ,"astr","XInputSetState")
_XInput_GetCapabilities := DllCall("GetProcAddress" ,"ptr",_XInput_hm ,"astr","XInputGetCapabilities")
if !(_XInput_GetState && _XInput_SetState && _XInput_GetCapabilities)
{
XInput_Term()
MsgBox, Failed to initialize XInput: function not found.
return
}
}
/*
Function: XInput_GetState
Retrieves the current state of the specified controller.
Parameters:
UserIndex - [in] Index of the user's controller. Can be a value from 0 to 3.
State - [out] Receives the current state of the controller.
Returns:
If the function succeeds, the return value is ERROR_SUCCESS (zero).
If the controller is not connected, the return value is ERROR_DEVICE_NOT_CONNECTED (1167).
If the function fails, the return value is an error code defined in Winerror.h.
http://msdn.microsoft.com/en-us/library/ms681381.aspx
Remarks:
XInput.dll returns controller state as a binary structure:
http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.xinput_state
http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.xinput_gamepad
XInput.ahk converts this structure to an AutoHotkey_L object.
*/
XInput_GetState(UserIndex)
{
--UserIndex
global _XInput_GetState
VarSetCapacity(xiState,16)
if ErrorLevel := DllCall(_XInput_GetState ,"uint",UserIndex ,"uint",&xiState)
return 0
return {
(Join,
dwPacketNumber: NumGet(xiState, 0, "UInt")
wButtons: NumGet(xiState, 4, "UShort")
bLeftTrigger: NumGet(xiState, 6, "UChar")
bRightTrigger: NumGet(xiState, 7, "UChar")
sThumbLX: NumGet(xiState, 8, "Short")
sThumbLY: NumGet(xiState, 10, "Short")
sThumbRX: NumGet(xiState, 12, "Short")
sThumbRY: NumGet(xiState, 14, "Short")
)}
}
/*
Function: XInput_SetState
Sends data to a connected controller. This function is used to activate the vibration
function of a controller.
Parameters:
UserIndex - [in] Index of the user's controller. Can be a value from 0 to 3.
LeftMotorSpeed - [in] Speed of the left motor, between 0 and 65535.
RightMotorSpeed - [in] Speed of the right motor, between 0 and 65535.
Returns:
If the function succeeds, the return value is 0 (ERROR_SUCCESS).
If the controller is not connected, the return value is 1167 (ERROR_DEVICE_NOT_CONNECTED).
If the function fails, the return value is an error code defined in Winerror.h.
http://msdn.microsoft.com/en-us/library/ms681381.aspx
Remarks:
The left motor is the low-frequency rumble motor. The right motor is the
high-frequency rumble motor. The two motors are not the same, and they create
different vibration effects.
*/
XInput_SetState(UserIndex, LeftMotorSpeed, RightMotorSpeed)
{
global _XInput_SetState
return DllCall(_XInput_SetState ,"uint",UserIndex ,"uint*",LeftMotorSpeed|RightMotorSpeed<<16)
}
/*
Function: XInput_GetCapabilities
Retrieves the capabilities and features of a connected controller.
Parameters:
UserIndex - [in] Index of the user's controller. Can be a value in the range 0�3.
Flags - [in] Input flags that identify the controller type.
0 - All controllers.
1 - XINPUT_FLAG_GAMEPAD: Xbox 360 Controllers only.
Caps - [out] Receives the controller capabilities.
Returns:
If the function succeeds, the return value is 0 (ERROR_SUCCESS).
If the controller is not connected, the return value is 1167 (ERROR_DEVICE_NOT_CONNECTED).
If the function fails, the return value is an error code defined in Winerror.h.
http://msdn.microsoft.com/en-us/library/ms681381.aspx
Remarks:
XInput.dll returns capabilities via a binary structure:
http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.xinput_capabilities
XInput.ahk converts this structure to an AutoHotkey_L object.
*/
XInput_GetCapabilities(UserIndex, Flags)
{
global _XInput_GetCapabilities
VarSetCapacity(xiCaps,20)
if ErrorLevel := DllCall(_XInput_GetCapabilities ,"uint",UserIndex ,"uint",Flags ,"ptr",&xiCaps)
return 0
return,
(Join
{
Type: NumGet(xiCaps, 0, "UChar"),
SubType: NumGet(xiCaps, 1, "UChar"),
Flags: NumGet(xiCaps, 2, "UShort"),
Gamepad:
{
wButtons: NumGet(xiCaps, 4, "UShort"),
bLeftTrigger: NumGet(xiCaps, 6, "UChar"),
bRightTrigger: NumGet(xiCaps, 7, "UChar"),
sThumbLX: NumGet(xiCaps, 8, "Short"),
sThumbLY: NumGet(xiCaps, 10, "Short"),
sThumbRX: NumGet(xiCaps, 12, "Short"),
sThumbRY: NumGet(xiCaps, 14, "Short")
},
Vibration:
{
wLeftMotorSpeed: NumGet(xiCaps, 16, "UShort"),
wRightMotorSpeed: NumGet(xiCaps, 18, "UShort")
}
}
)
}
/*
Function: XInput_Term
Unloads the previously loaded XInput DLL.
*/
XInput_Term() {
global
if _XInput_hm
DllCall("FreeLibrary","uint",_XInput_hm), _XInput_hm :=_XInput_GetState :=_XInput_SetState :=_XInput_GetCapabilities :=0
}
; TODO: XInputEnable, 'GetBatteryInformation and 'GetKeystroke.
@BanditTech
Copy link
Author

still not finished assigning inputs to actions saved in the settings

@BanditTech
Copy link
Author

also needs the same thing done to the joysticks as the buttons, with multiple types of actions based on triggers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment