Skip to content

Instantly share code, notes, and snippets.

@acsr
Last active August 12, 2021 11:28
Show Gist options
  • Save acsr/0b7659c1e467aa4ec6fca755ab06644f to your computer and use it in GitHub Desktop.
Save acsr/0b7659c1e467aa4ec6fca755ab06644f to your computer and use it in GitHub Desktop.
CycleSpaces P4D Desktop Joystick Mouse Simulation via F1-F4 + F6 for Navigation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;
;;;;; 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
@acsr
Copy link
Author

acsr commented Aug 11, 2021

Version 0.9.4

@acsr
Copy link
Author

acsr commented Aug 11, 2021

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:

  • download and install autohotkey Version 1.x (not 2.x) from https://www.autohotkey.com
  • download this script and install it by doubleclicking
  • maybe you need additionally the general setup script CSVRstartupsequence_p4DV2-3-2D.ahk (seperate private gist on request)

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