Last active
August 12, 2021 11:28
-
-
Save acsr/0b7659c1e467aa4ec6fca755ab06644f to your computer and use it in GitHub Desktop.
CycleSpaces P4D Desktop Joystick Mouse Simulation via F1-F4 + F6 for Navigation
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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;; | |
;;;;; CycleSpaces P4D Desktop Joystick Mouse Simulation via F1-F4 | |
;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
SimulateP4DDesktopMouseFunctionKeys.ahk script based on: | |
Windows Scripting Environment: https://www.autohotkey.com | |
Version 0.9.11 | |
COPYRIGHT 2021 by acsr industrialdesign, Armin Stross-Radschinski / evenios productions | |
All rights reserved | |
developer@acsr.de | |
Production: http://www.evenios.com | |
Design & Development: http://www.acsr.de | |
VR technology by http://present4d.com using Unity | |
This AutoHotkey script | |
- Simulates the Mouse Control of the 2D Movement (Tilt and Rotate) in Panoramas | |
- Installs the Hotkeys F1-F4 for the four directions Left, Right, Up, Down | |
- Is intended for use without the Oculus Rift in fullscreen mode on Monitor 1 | |
- The purpose of the F1-F4 keys is to be mapped to the buttons of a custom Hardware Joystick via USB-Controller that translates to F1-F4 | |
- Starts and relocates the pointer to the center of Monitor 1 | |
To install this script | |
- Install https://www.autohotkey.com Version 1.x | |
- Doubleclick after every update of the code | |
- Add to Autostart or integrate code into the CSVRstartupsequenceOculusCV1.ahk script | |
ToDo: | |
- Smooth acceleration if F-Keys are pressed longer | |
- Change the appearance of the cursor | |
- Limit execution to duration of the active p4D application run and screen | |
- Calculate Center correctly if multiple monitors are attached | |
- Refactor into function | |
*/ | |
/* History: | |
initial release on 23rd Mar. 2021 | |
20210323_17-40-00 Mouse-Simulation for P4D Desktopmode on CycleSpaces Satellite 2 ASUS PC | |
20210417_16-52-00 add single click at end of move back to trigger hotspts, add SmoothMouse value comment | |
20210417_19-35-00 Add SystemCursor() function to hide cursor (via https://www.autohotkey.com/boards/viewtopic.php?p=293421#p293421 courtesy Maestr0) but deactivate Blockinput | |
20210417_20-22-00 Add code to all directions | |
20210418_16-27-00 Refactor Code to functions for further development | |
20210418_18-43-00 Fix single Timer issue | |
20210418_18-57-00 Set maximum repeated acceleration | |
20210418_20-43-00 Get more finegrained acceleration | |
20210421_13-46-00 Test once to triple presses and long press of F8 key | |
20210421_14-14-00 Once to triple presses and long press of F8 key -> Next, Prev, Inforoom, Restart | |
20210421_17-16-00 changed F8 to F6 | |
*/ | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;; | |
;;;;;;; General Autohotkey Initialization Sequence | |
;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
#MaxHotkeysPerInterval 200 | |
#SingleInstance Force ; Make the script update itself after starting again | |
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. | |
#Warn ; Enable warnings to assist with detecting common errors. | |
; Sendmode Input -> disables the smooth mouse movement! | |
; SendMode Input ; Recommended for new scripts due to its superior speed and reliability. | |
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. | |
SplashImage, Off | |
; KeyHistory ; Comment out to display keys preessed in a debug window | |
winc_presses := 0 ; init var | |
/* End General Autohotkey Initialization Sequence */ | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;; | |
;;;;;;; Function Definitions | |
;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
Define all complex actions as function before calling them from a hotkey | |
*/ | |
SystemCursor(OnOff:=1) { | |
if (OnOff == 1) | |
{ | |
;BlockInput MouseMoveOff | |
DllCall("ShowCursor", Int,1) | |
} | |
else | |
{ | |
MouseGetPos, , , hwnd | |
Gui Cursor:+Owner%hwnd% | |
;BlockInput MouseMove | |
DllCall("ShowCursor", Int,0) | |
} | |
} | |
; MsgBox, , Mouse Mapping Rev 0.7 , Mouse Mapping updated , 3 | |
SysGet, MonitorCount, MonitorCount | |
SysGet, MonitorPrimary, MonitorPrimary | |
; MsgBox, Monitor Count:`t%MonitorCount%`nPrimary Monitor:`t%MonitorPrimary% | |
Loop, %MonitorCount% | |
{ | |
SysGet, MonitorName, MonitorName, %A_Index% | |
SysGet, Monitor, Monitor, %A_Index% | |
SysGet, MonitorWorkArea, MonitorWorkArea, %A_Index% | |
; MsgBox, Monitor:`t#%A_Index%`nName:`t%MonitorName%`nLeft:`t%MonitorLeft% (%MonitorWorkAreaLeft% work)`nTop:`t%MonitorTop% (%MonitorWorkAreaTop% work)`nRight:`t%MonitorRight% (%MonitorWorkAreaRight% work)`nBottom:`t%MonitorBottom% (%MonitorWorkAreaBottom% work) | |
} | |
MidX := Format("{:d}", (MonitorRight-MonitorLeft)/2) | |
MidY := Format("{:d}", (MonitorBottom-MonitorTop)/2) | |
; MsgBox, , MonitorCenter , Mid X:%MidX%`nMid Y:%MidY% , 3 | |
CoordMode, Mouse, Screen | |
Thread, interrupt, 0 ; Make all threads always-interruptible. | |
MouseSpeed := 0 | |
AcceleratorTimerDelay := -500 | |
MouseMove, MidX, MidY, 0 | |
MouseOffsetX := 20 | |
MouseOffsetX2 := 5 | |
MouseOffsetY := MouseOffsetX | |
MouseOffsetY2 := MouseOffsetX2 | |
AccelCount := 0 ; Reset Counter | |
MaxAccelCount := 50 ; Maximum Counter | |
SmoothMouseX := 0 ; The speed to return to center horizontally | |
SmoothMouseY := SmoothMouseX ; The speed to return to center vertically | |
SetMouseDelay, 2 | |
; Functions to calculate X,Y direction factors | |
FKey2XFactor(FKeyID) ; X-Direction | |
{ | |
if (FKeyID = 1) | |
return -1 | |
if (FKeyID = 2) | |
return 1 | |
else | |
return 0 | |
} | |
FKey2YFactor(FKeyID) ; Y-Direction | |
{ | |
if (FKeyID = 3) | |
return -1 | |
if (FKeyID = 4) | |
return 1 | |
else | |
return 0 | |
} | |
JoystickFKey_Down(FKeyID) | |
{ | |
global MidX | |
global MidY | |
global MouseOffsetX | |
global MouseOffsetY | |
global MouseOffsetX2 | |
global MouseOffsetY2 | |
global MouseSpeed | |
global FKey2XF | |
global FKey2YF | |
global AccelCount | |
global MaxAccelCount | |
AccelCount := 0 ; Reset Counter | |
FKey2XF := FKey2XFactor(FKeyID) | |
FKey2YF := FKey2YFactor(FKeyID) | |
TimerName := "TimerX" | |
;MsgBox, TimerName is "%TimerName%" | |
TimerX := TimerName . FKeyID | |
;MsgBox, TimerX is "%TimerX%" | |
IfWinActive, ahk_class UnityWndClass | |
SystemCursor(0) ; hides cursor | |
MouseMove, MidX, MidY, 0 ; start at center | |
Click, Down | |
SetTimer %TimerX%, 25 | |
MouseMove, FKey2XF*MouseOffsetX, FKey2YF*MouseOffsetY, MouseSpeed, R ; Move cursor | |
SetMouseDelay, -1 | |
return | |
TimerX1: | |
if (AccelCount < MaxAccelCount) | |
{ | |
++AccelCount | |
MouseMove, FKey2XF*MouseOffsetX2, FKey2YF*MouseOffsetY2, MouseSpeed, R ; Move cursor more | |
} | |
return | |
TimerX2: | |
if (AccelCount < MaxAccelCount) | |
{ | |
++AccelCount | |
MouseMove, FKey2XF*MouseOffsetX2, FKey2YF*MouseOffsetY2, MouseSpeed, R ; Move cursor more | |
} | |
return | |
TimerX3: | |
if (AccelCount < MaxAccelCount) | |
{ | |
++AccelCount | |
MouseMove, FKey2XF*MouseOffsetX2, FKey2YF*MouseOffsetY2, MouseSpeed, R ; Move cursor more | |
} | |
return | |
TimerX4: | |
if (AccelCount < MaxAccelCount) | |
{ | |
++AccelCount | |
MouseMove, FKey2XF*MouseOffsetX2, FKey2YF*MouseOffsetY2, MouseSpeed, R ; Move cursor more | |
} | |
return | |
} | |
JoystickFKey_Up(FKeyID) | |
{ | |
global MidX | |
global MidY | |
global SmoothMouseX | |
global AccelCount | |
global MaxAccelCount | |
AccelCount := MaxAccelCount | |
TimerName := "TimerX" | |
TimerX := TimerName . FKeyID | |
Click, Up | |
;SetTimer %TimerX%, Off | |
SetTimer %TimerX%, Delete | |
MouseMove, MidX, MidY, SmoothMouseX | |
SetMouseDelay, -1 | |
Click | |
SetMouseDelay, 2 | |
} | |
; F5:: ; Test when App is not running | |
; ;WinActivate, ahk_class UnityWndClass | |
; ;IfWinActive, ahk_class UnityWndClass | |
; { | |
; JoystickFKey_Down(2) | |
; } | |
; return; | |
; F5 up:: ; Test when App is not running | |
; { | |
; JoystickFKey_Up(3) | |
; } | |
; return | |
F1:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
JoystickFKey_Down(1) | |
} | |
return | |
F1 up:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
JoystickFKey_Up(1) | |
} | |
return | |
F2:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
JoystickFKey_Down(2) | |
} | |
return | |
F2 up:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
JoystickFKey_Up(2) | |
} | |
return | |
F3:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
JoystickFKey_Down(3) | |
} | |
return | |
F3 up:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
JoystickFKey_Up(3) | |
} | |
return | |
F4:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
JoystickFKey_Down(4) | |
} | |
return | |
F4 up:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
JoystickFKey_Up(4) | |
} | |
return | |
; Test Double & Long Click Next,Previous Location | |
NumpadAdd:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
Send {Up} | |
} else { | |
Send {NumpadAdd} | |
} | |
return | |
NumpadSub:: | |
WinActivate, ahk_class UnityWndClass | |
IfWinActive, ahk_class UnityWndClass | |
{ | |
Send {Down} | |
} else { | |
Send {NumpadSub} | |
} | |
return | |
F6:: ; Test once to triple presses an long press of F8 key | |
if (winc_presses > 0) ; SetTimer already started, so we log the keypress instead. | |
{ | |
winc_presses += 1 | |
return | |
} | |
; Otherwise, this is the first press of a new series. Set count to 1 and start | |
; the timer: | |
winc_presses := 1 | |
SetTimer, KeyWinC, -800 ; Wait for more presses within a 800 millisecond window. | |
return | |
KeyWinC: | |
if GetKeyState("F6", "P") and (winc_presses = 1) ; Pressed once and longer as 800ms | |
{ | |
;MsgBox, 0, , F8 Pressed long, 1 | |
Send x | |
} | |
else if (winc_presses = 1) ; The key was pressed once. | |
{ | |
;MsgBox, 0, , F8 Pressed once, 1 | |
Send {Up} | |
} | |
else if (winc_presses = 2) ; The key was pressed twice. | |
{ | |
;MsgBox, 0, , F8 Pressed twice, 1 | |
Send {Down} | |
} | |
else if (winc_presses > 2) | |
{ | |
;MsgBox, 0, , F8 Pressed three or more detected., 1 | |
Send 111 | |
} | |
; Regardless of which action above was triggered, reset the count to | |
; prepare for the next series of presses: | |
winc_presses := 0 | |
return |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Update to version 0.9.11 with additional F6 single button control of next, back and restart using single-click (next), double-click (back) and long-click (restart, goto initial location).
To test: