Xbox 360 controller D-pad rebinds

Ask gaming related questions (AHK v1.1 and older)
3os
Posts: 12
Joined: 11 Jul 2016, 16:46

Xbox 360 controller D-pad rebinds

21 Feb 2017, 08:17

Hi Guys

I'm writing a script to macro Chat Messages for a Xbox360 controller. A typical example would be to have a certain key respond the default way when pressed and released, but to run a macro when held. The following script works on all the regular buttons, and I'm pretty happy with the result:

Code: Select all

#InstallKeybdHook
#UseHook

;sends "Hello world" when Joypad Button1 is pressed and held for one second.
$Joy1::			
KeyWait, Joy1, T1
If ErrorLevel = 1
   {
send {enter}
send Hello world
send {enter}
   }
Return



But now I want to add some more macros to the D-Pad which is slightly more tricky. (in my understanding, the d-pad outputs angles, rather than bindable keys. I found the following code online that should work, however, im finding difficulties to rebind the keys, never mind even applying the hold-button script. Ive done some testing to see all my POV values:

0 up
4500 up right
9000 right
13500 down right
18000 down
22500 left down
27000 left
31500 left up



Here is the script I found:

GetKeyState, POV, JoyPOV ; Get position of the POV control.

Code: Select all

if POV = -1   ; No angle to report
KeyToHoldDown =

else if POV = 0		
KeyToHoldDown = XXXX

else if POV = 4500
KeyToHoldDown = YYYY

else if POV = 9000
KeyToHoldDown = ZZZZ

else                    
KeyToHoldDown = CCCC
return
Is there any way to accomplish this idea? or would it be simpler to just bind a secondary button to a modifier key and bind the combination keys instead?

Thanks in advance
3os
User avatar
Spawnova
Posts: 554
Joined: 08 Jul 2015, 00:12
Contact:

Re: Xbox 360 controller D-pad rebinds

21 Feb 2017, 14:32

Code: Select all

#persistent
dpadBindings := [] ;this is array which will hold 4 items of data, with povdir as a key and the text to send as a value
dpadBindings.insert(0,"Send this text on 0") ;if joypov = 0  send this text
dpadBindings.insert(9000,"Send this text on 9000")
dpadBindings.insert(18000,"Send this text on 18000")
dpadBindings.insert(27000,"Send this text on 27000")
settimer,checkBindings,50 ;check bindings every 50ms
return

checkBindings:
dir := GetKeyState("joyPov","p")
if dpadBindings[dir] { ;this is checking if there is a key equal to this direction, if the dir = 4500 it would not work since we don't have that key in our array
	if (lastDir = -1) { ;only send if the joy just was pressed, to prevent spamming
		send % dpadBindings[dir]
	}
}
lastDir := dir
return

f8::exitapp
f9::reload
Here's an example, I'm using an array here but I've commented it for you so hopefully it's not too confusing.
3os
Posts: 12
Joined: 11 Jul 2016, 16:46

Re: Xbox 360 controller D-pad rebinds

22 Feb 2017, 04:45

Thanks for responding, Spawnova

The code makes sense (thanks to your comments) and works perfectly. I now need to find a way to hold these POVs to send the text, otherwise it is just interfering with the controls.

So far, if tried KeyWait, but it does not seem to work. i assume that it only works on physical keys?
User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: Xbox 360 controller D-pad rebinds

27 Feb 2017, 15:00

Would if (lastDir = -1) not be better expressed as if (lastDir != dir)?
With the current code, if the dpad is up, it sends the string for up.
If you then move the dpad to up+right, then right, it would not send the string for right, because lastDir would hold the value for up+right, not -1

If you want "long press" functionality, then yeah, KeyWait is not gonna help you as there is no keyname for hat directions.

This adaptation of Spawnova's code may work (Untested):

Code: Select all

#persistent

dpadBindings := [] ;this is array which will hold 4 items of data, with povdir as a key and the text to send as a value
dpadBindings.insert(0,"Send this text on 0") ;if joypov = 0  send this text
dpadBindings.insert(9000,"Send this text on 9000")
dpadBindings.insert(18000,"Send this text on 18000")
dpadBindings.insert(27000,"Send this text on 27000")
settimer,checkBindings,50 ;check bindings every 50ms
return

checkBindings:
dir := GetKeyState("joyPov","p")
if dpadBindings[dir] { ;this is checking if there is a key equal to this direction, if the dir = 4500 it would not work since we don't have that key in our array
	if (dir == lastDir) {
		heldCount++
		if (heldCount == 10){	; Has direction been held for 10 loops? (10x50ms = 500ms)
			send % dpadBindings[dir]
		}
	} else {
		heldCount := 1
	}
}
lastDir := dir
return

f8::exitapp
f9::reload
User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: Xbox 360 controller D-pad rebinds

27 Feb 2017, 15:12

Oh, and by the way...

UCR (See signature) is a GUI app that lets you map d-pad directions as if they were buttons.
If you added a "Code Runner" plugin to UCR, then mapped a d-pad direction as the input, any time you pressed the d-pad direction, it would run the AHK code that you typed in the box.

UCR does not support "Long Press" functionality at the moment though, it is on the to-do list.

If you are interested though, feel free to root through the UCR source code to see how I abstract out the hat directions into "buttons".
Basically, what I do is:

Convert the angle (-1, 0, 4500, 9000 etc) to a "direction" using:
state := (state = -1 ? -1 : round(state / 4500) + 1)
This will result in -1 for center, 1 for north, 2 for ne, 3 for east, etc...

Then I use this array to extract directional information:
PovMap := {-1: [0,0,0,0], 1: [1,0,0,0], 2: [1,1,0,0] , 3: [0,1,0,0], 4: [0,1,1,0], 5: [0,0,1,0], 6: [0,0,1,1], 7: [0,0,0,1], 8: [1,0,0,1]}

eg for north-east (direction 2):
dirMap := PovMap[2]

dirMap would then hold [1,1,0,0]
This array represents the state of the four directions on a hat for the given angle. The first array element is up, the 2nd right, the 3rd down, the 4th is left - so as elements 1+2 are set to 1, then this means "Up + Right".
So using this technique, my code can extract 4 "buttons" from 1 hat, and it supports diagonals - using this technique it would be easy for the code to figure out that to transition from north -east to east, then the "up" direction is released and nothing new is held.

To recap:
angle -1 = direction -1 = PovMap[-1] is [0,0,0,0] (No buttons are held for this angle)
angle 0 = direction 1 = PovMap[1] is [1,0,0,0] (Up is held for this angle)
angle 4500 = direction 2 = PovMap[2] is [1,1,0,0] (Up and Right are held for this angle)
angle 9000 = direction 3 = PovMap[3] is [0,1,0,0] (Right is held for this angle)

Return to “Gaming Help (v1)”

Who is online

Users browsing this forum: No registered users and 51 guests