Created
March 26, 2020 05:49
-
-
Save BanditTech/20880ae5e55af816e8af62f0962ee5be to your computer and use it in GitHub Desktop.
XInput Controller Testbench
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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. |
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
still not finished assigning inputs to actions saved in the settings