-
-
Save kurohai/eb32e8b99146ccdddb5672f5be96571b to your computer and use it in GitHub Desktop.
Small script to convert HTC Vive controller inputs into virtual keypresses for autohotkey (thanks to awesomebytes)
This file contains hidden or 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
#!/usr/bin/env python | |
import time | |
import pprint | |
import openvr | |
import win32api | |
import win32con | |
""" | |
Convert HTC Vive inputs to virtual keypresses for autohotkey | |
Key identifiers for autohotkey: | |
vk0x88 = left grip | |
vk0x89 = right grip | |
vk0x8A = left trigger | |
vk0x8B = right trigger | |
vk0x8C = left menu | |
vk0x8D = right menu | |
vk0x8E = left touchpad clicked | |
vk0x8F = right touchpad clicked | |
vk0x92 = left touchpad touched | |
vk0x93 = right touchpad clicked | |
""" | |
def get_controller_ids(vrsys=None): | |
if vrsys is None: | |
vrsys = openvr.VRSystem() | |
else: | |
vrsys = vrsys | |
left = None | |
right = None | |
for i in range(openvr.k_unMaxTrackedDeviceCount): | |
device_class = vrsys.getTrackedDeviceClass(i) | |
if device_class == openvr.TrackedDeviceClass_Controller: | |
role = vrsys.getControllerRoleForTrackedDeviceIndex(i) | |
if role == openvr.TrackedControllerRole_RightHand: | |
right = i | |
if role == openvr.TrackedControllerRole_LeftHand: | |
left = i | |
return left, right | |
def from_controller_state_to_dict(pControllerState): | |
d = {} | |
d['unPacketNum'] = pControllerState.unPacketNum | |
d['trigger'] = pControllerState.rAxis[1].x | |
d['trackpad_x'] = pControllerState.rAxis[0].x | |
d['trackpad_y'] = pControllerState.rAxis[0].y | |
d['ulButtonPressed'] = pControllerState.ulButtonPressed | |
d['ulButtonTouched'] = pControllerState.ulButtonTouched | |
d['menu_button'] = bool(pControllerState.ulButtonPressed >> 1 & 1) | |
d['trackpad_pressed'] = bool(pControllerState.ulButtonPressed >> 32 & 1) | |
d['trackpad_touched'] = bool(pControllerState.ulButtonTouched >> 32 & 1) | |
d['grip_button'] = bool(pControllerState.ulButtonPressed >> 2 & 1) | |
return d | |
pressed = {} | |
def take_press(set_side, set_key, set_value, set_keycode, data): | |
if data['side'] == set_side and data[set_key] == set_value and not pressed.get(hex(set_keycode)): | |
pressed[hex(set_keycode)] = True | |
win32api.keybd_event(set_keycode, 0, 0, 0) | |
elif data['side'] == set_side and data[set_key] != set_value and pressed.get(hex(set_keycode)): | |
pressed[hex(set_keycode)] = False | |
win32api.keybd_event(set_keycode, 0 ,win32con.KEYEVENTF_KEYUP ,0) | |
def handle_input(data): | |
take_press('left', 'grip_button', True, 0x88, data) | |
take_press('right', 'grip_button', True, 0x89, data) | |
take_press('left', 'trigger', 1, 0x8A, data) | |
take_press('right', 'trigger', 1, 0x8B, data) | |
take_press('left', 'menu_button', True, 0x8C, data) | |
take_press('right', 'menu_button', True, 0x8D, data) | |
take_press('left', 'trackpad_pressed', True, 0x8E, data) | |
take_press('right', 'trackpad_pressed', True, 0x8F, data) | |
take_press('left', 'trackpad_touched', True, 0x92, data) | |
take_press('right', 'trackpad_touched', True, 0x93, data) | |
if __name__ == '__main__': | |
max_init_retries = 4 | |
retries = 0 | |
print("===========================") | |
print("Initializing OpenVR...") | |
while retries < max_init_retries: | |
try: | |
openvr.init(openvr.VRApplication_Utility) | |
break | |
except openvr.OpenVRError as e: | |
print("Error when initializing OpenVR (try {} / {})".format( | |
retries + 1, max_init_retries)) | |
print(e) | |
retries += 1 | |
time.sleep(2.0) | |
else: | |
print("Could not initialize OpenVR, aborting.") | |
exit(0) | |
print("Success!") | |
print("===========================") | |
vrsystem = openvr.VRSystem() | |
left_id, right_id = None, None | |
print("===========================") | |
print("Waiting for controllers...") | |
try: | |
while left_id is None or right_id is None: | |
left_id, right_id = get_controller_ids(vrsystem) | |
if left_id and right_id: | |
break | |
print("Waiting for controllers...") | |
time.sleep(1.0) | |
except KeyboardInterrupt: | |
print("Control+C pressed, shutting down...") | |
openvr.shutdown() | |
print("Left controller ID: " + str(left_id)) | |
print("Right controller ID: " + str(right_id)) | |
print("===========================") | |
pp = pprint.PrettyPrinter(indent=4) | |
reading_rate_hz = 250 | |
show_only_new_events = True | |
last_unPacketNum_left = 0 | |
last_unPacketNum_right = 0 | |
print("===========================") | |
print("Outputting controller key events!") | |
try: | |
while True: | |
time.sleep(1.0 / reading_rate_hz) | |
result, pControllerState = vrsystem.getControllerState(left_id) | |
d = from_controller_state_to_dict(pControllerState) | |
if show_only_new_events and last_unPacketNum_left != d['unPacketNum']: | |
last_unPacketNum_left = d['unPacketNum'] | |
d['side'] = 'left' | |
handle_input(d) | |
result, pControllerState = vrsystem.getControllerState(right_id) | |
d = from_controller_state_to_dict(pControllerState) | |
if show_only_new_events and last_unPacketNum_right != d['unPacketNum']: | |
last_unPacketNum_right = d['unPacketNum'] | |
d['side'] = 'right' | |
handle_input(d) | |
except KeyboardInterrupt: | |
print("Control+C pressed, shutting down...") | |
openvr.shutdown() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment