Skip to content

Instantly share code, notes, and snippets.

@chrismwendt
Created March 15, 2015 04:46
Show Gist options
  • Save chrismwendt/7193e4c61073767af528 to your computer and use it in GitHub Desktop.
Save chrismwendt/7193e4c61073767af528 to your computer and use it in GitHub Desktop.
Maps joystick and buttons to mouse movement, buttons, and scroll
; Using a Joystick as a Mouse
; http://www.autohotkey.com
; This script converts a joystick into a three-button mouse. It allows each
; button to drag just like a mouse button and it uses virtually no CPU time.
; Also, it will move the cursor faster depending on how far you push the joystick
; from center. You can personalize various settings at the top of the script.
; Increase the following value to make the mouse cursor move faster:
JoyMultiplier = 30
JoyWheelMultiplier = 50
; Decrease the following value to require less joystick displacement-from-center
; to start moving the mouse. However, you may need to calibrate your joystick
; -- ensuring it's properly centered -- to avoid cursor drift. A perfectly tight
; and centered joystick could use a value of 1:
JoyThreshold = 3
; Change the following to true to invert the Y-axis, which causes the mouse to
; move vertically in the direction opposite the stick:
InvertYAxis := false
; Change these values to use joystick button numbers other than 1, 2, and 3 for
; the left, right, and middle mouse buttons. Available numbers are 1 through 32.
; Use the Joystick Test Script to find out your joystick's numbers more easily.
ButtonLeft = 1
ButtonRight = 2
ButtonMiddle = 3
; If your joystick has a POV control, you can use it as a mouse wheel. The
; following value is the number of milliseconds between turns of the wheel.
; Decrease it to have the wheel turn faster:
WheelDelay = 250
; If your system has more than one joystick, increase this value to use a joystick
; other than the first:
JoystickNumber = 1
; END OF CONFIG SECTION -- Don't change anything below this point unless you want
; to alter the basic nature of the script.
#SingleInstance force
SetTimer,UPDATEDSCRIPT,1000
global fractionalX := 0
global fractionalY := 0
JoystickPrefix = %JoystickNumber%Joy
Hotkey, %JoystickPrefix%%ButtonLeft%, ButtonLeft
Hotkey, %JoystickPrefix%%ButtonRight%, ButtonRight
Hotkey, %JoystickPrefix%%ButtonMiddle%, ButtonMiddle
Hotkey, Joy4, JFour
Hotkey, Joy5, JFive
Hotkey, Joy6, JSix
; Calculate the axis displacements that are needed to start moving the cursor:
JoyThresholdUpper := 50 + JoyThreshold
JoyThresholdLower := 50 - JoyThreshold
SetTimer, WatchJoystick, 10 ; Monitor the movement of the joystick.
GetKeyState, JoyInfo, %JoystickNumber%JoyInfo
IfInString, JoyInfo, P ; Joystick has POV control, so use it as a mouse wheel.
SetTimer, MouseWheel, %WheelDelay%
return ; End of auto-execute section.
; The subroutines below do not use KeyWait because that would sometimes trap the
; WatchJoystick quasi-thread beneath the wait-for-button-up thread, which would
; effectively prevent mouse-dragging with the joystick.
JFour:
Joy4::Send ^w
return
JFive:
Joy5::Send ^+{TAB}
return
JSix:
Joy6::Send ^{TAB}
return
ButtonLeft:
SetMouseDelay, -1 ; Makes movement smoother.
MouseClick, left,,, 1, 0, D ; Hold down the left mouse button.
SetTimer, WaitForLeftButtonUp, 10
return
ButtonRight:
SetMouseDelay, -1 ; Makes movement smoother.
MouseClick, right,,, 1, 0, D ; Hold down the right mouse button.
SetTimer, WaitForRightButtonUp, 10
return
ButtonMiddle:
SetMouseDelay, -1 ; Makes movement smoother.
MouseClick, middle,,, 1, 0, D ; Hold down the right mouse button.
SetTimer, WaitForMiddleButtonUp, 10
return
WaitForLeftButtonUp:
if GetKeyState(JoystickPrefix . ButtonLeft)
return ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForLeftButtonUp, off
SetMouseDelay, -1 ; Makes movement smoother.
MouseClick, left,,, 1, 0, U ; Release the mouse button.
return
WaitForRightButtonUp:
if GetKeyState(JoystickPrefix . ButtonRight)
return ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForRightButtonUp, off
MouseClick, right,,, 1, 0, U ; Release the mouse button.
return
WaitForMiddleButtonUp:
if GetKeyState(JoystickPrefix . ButtonMiddle)
return ; The button is still, down, so keep waiting.
; Otherwise, the button has been released.
SetTimer, WaitForMiddleButtonUp, off
MouseClick, middle,,, 1, 0, U ; Release the mouse button.
return
WatchJoystick:
MouseNeedsToBeMoved := false ; Set default.
;SetFormat, float, 03
GetKeyState, joyx, %JoystickNumber%JoyX
GetKeyState, joyy, %JoystickNumber%JoyY
GetKeyState, joyr, %JoystickNumber%JoyR
if joyx > %JoyThresholdUpper%
{
MouseNeedsToBeMoved := true
DeltaX := joyx - JoyThresholdUpper
}
else if joyx < %JoyThresholdLower%
{
MouseNeedsToBeMoved := true
DeltaX := joyx - JoyThresholdLower
}
else
DeltaX = 0
if joyy > %JoyThresholdUpper%
{
MouseNeedsToBeMoved := true
DeltaY := joyy - JoyThresholdUpper
}
else if joyy < %JoyThresholdLower%
{
MouseNeedsToBeMoved := true
DeltaY := joyy - JoyThresholdLower
}
else
DeltaY = 0
if MouseNeedsToBeMoved
{
SetMouseDelay, -1 ; Makes movement smoother.
global fractionalX
global fractionalY
JoyDeviationToMouseVelocity(DeltaX / (50 - JoyThreshold), DeltaY / (50 - JoyThreshold), dx, dy)
sdx := dx + fractionalX
sdy := dy + fractionalY
rdx := trunc(sdx)
rdy := trunc(sdy)
fractionalX := sdx - rdx
fractionalY := sdy - rdy
MouseMove, rdx, rdy, 0, R
}
if joyr > %JoyThreshholdUpper% or joyr < %JoyThresholdLower%
{
a := -(joyr - 50) / 50
PostMW(signum(a) * a ** 2 * JoyWheelMultiplier)
}
return
trunc(v)
{
return signum(v) * Floor(abs(v))
}
JoyDeviationToMouseVelocity(dx, dy, ByRef ox, ByRef oy)
{
global JoyMultiplier
m := mag(dx, dy)
;~ a := (m + m ** 3) / 2
a := m ** 3
ox := m * dx * JoyMultiplier
oy := m * dy * JoyMultiplier
}
mag(x, y)
{
return sqrt(x ** 2 + y ** 2)
}
signum(v)
{
if v < 0
{
return -1
}
if v = 0
{
return 0
}
if v > 0
{
return 1
}
}
PostMW(delta)
{ ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx
CoordMode, Mouse, Screen
MouseGetPos, x, y
Modifiers := 0x8*GetKeyState("ctrl") | 0x1*GetKeyState("lbutton") | 0x10*GetKeyState("mbutton")
|0x2*GetKeyState("rbutton") | 0x4*GetKeyState("shift") | 0x20*GetKeyState("xbutton1")
|0x40*GetKeyState("xbutton2")
PostMessage, 0x20A, delta << 16 | Modifiers, y << 16 | x ,, A
}
MouseWheel:
GetKeyState, JoyPOV, %JoystickNumber%JoyPOV
if JoyPOV = -1 ; No angle.
return
if JoyPOV between 4500 and 13500 ; Forward
Send {Browser_Forward}
else if JoyPOV between 22500 and 31500 ; Back
Send {Browser_Back}
return
UPDATEDSCRIPT:
FileGetAttrib,attribs,%A_ScriptFullPath%
IfInString,attribs,A
{
FileSetAttrib,-A,%A_ScriptFullPath%
SplashTextOn,,,Updated script,
Sleep,500
Reload
}
Return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment