Skip to content

Instantly share code, notes, and snippets.

@notgne2
Last active January 3, 2019 15:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save notgne2/833ce83c9bf9f8034a4c8c11ab3d16e2 to your computer and use it in GitHub Desktop.
Save notgne2/833ce83c9bf9f8034a4c8c11ab3d16e2 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)
#!/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