mirror of
https://github.com/LibreVR/Revive.git
synced 2026-08-04 00:54:37 -04:00
214 lines
6.4 KiB
Lua
214 lines
6.4 KiB
Lua
-- Helper function
|
|
function ButtonFromQuadrant(axis, right_hand)
|
|
if (right_hand) then
|
|
if (axis.y < -axis.x) then
|
|
if (axis.y < axis.x) then
|
|
return ovrButton_A;
|
|
else
|
|
return ovrButton_B;
|
|
end
|
|
else
|
|
return ovrButton_RThumb;
|
|
end
|
|
else
|
|
if (axis.y < axis.x) then
|
|
if (axis.y < -axis.x) then
|
|
return ovrButton_X
|
|
else
|
|
return ovrButton_Y
|
|
end
|
|
else
|
|
return ovrButton_LThumb
|
|
end
|
|
end
|
|
end
|
|
|
|
function GetButtons(right_hand)
|
|
buttons = {}
|
|
|
|
if (string.match(controller_model, "Knuckles")) then
|
|
if (state.ApplicationMenu.pressed and state.Grip.pressed) then
|
|
table.insert(buttons, ovrButton_Enter)
|
|
else
|
|
if (state.Grip.pressed) then
|
|
table.insert(buttons, right_hand and ovrButton_A or ovrButton_X)
|
|
end
|
|
|
|
if (state.ApplicationMenu.pressed) then
|
|
table.insert(buttons, right_hand and ovrButton_B or ovrButton_Y)
|
|
end
|
|
end
|
|
|
|
if (state[SteamVR_Touchpad].pressed) then
|
|
table.insert(buttons, right_hand and ovrButton_RThumb or ovrButton_LThumb)
|
|
end
|
|
|
|
return unpack(buttons)
|
|
end
|
|
|
|
if (state.ApplicationMenu.pressed) then
|
|
table.insert(buttons, ovrButton_Enter)
|
|
end
|
|
|
|
if (state.A.pressed) then
|
|
table.insert(buttons, right_hand and ovrButton_A or ovrButton_X)
|
|
end
|
|
|
|
if (state.B.pressed) then
|
|
table.insert(buttons, right_hand and ovrButton_B or ovrButton_Y)
|
|
end
|
|
|
|
if (state[SteamVR_Touchpad].pressed) then
|
|
table.insert(buttons, ButtonFromQuadrant(state[SteamVR_Touchpad], right_hand))
|
|
end
|
|
|
|
return unpack(buttons)
|
|
end
|
|
|
|
function GetTouches(right_hand)
|
|
touches = {}
|
|
|
|
if (string.match(controller_model, "Knuckles")) then
|
|
if (state.Grip.touched) then
|
|
table.insert(touches, right_hand and ovrTouch_A or ovrTouch_X)
|
|
end
|
|
|
|
if (state.ApplicationMenu.touched) then
|
|
table.insert(touches, right_hand and ovrTouch_B or ovrTouch_Y)
|
|
end
|
|
|
|
if (state[SteamVR_Touchpad].touched) then
|
|
table.insert(touches, right_hand and ovrTouch_RThumb or ovrTouch_LThumb)
|
|
elseif (not state.Grip.touched and not state.ApplicationMenu.touched) then
|
|
table.insert(touches, right_hand and ovrTouch_RThumbUp or ovrTouch_LThumbUp)
|
|
end
|
|
|
|
if (state[SteamVR_Trigger].touched) then
|
|
table.insert(touches, right_hand and ovrTouch_RIndexTrigger or ovrTouch_LIndexTrigger)
|
|
elseif (state[4].x < 0.8) then
|
|
table.insert(touches, right_hand and ovrTouch_RIndexPointing or ovrTouch_LIndexPointing)
|
|
end
|
|
|
|
return unpack(touches)
|
|
end
|
|
|
|
if (state.A.touched) then
|
|
table.insert(touches, right_hand and ovrTouch_A or ovrTouch_X)
|
|
end
|
|
|
|
if (state.B.touched) then
|
|
table.insert(touches, right_hand and ovrTouch_B or ovrTouch_Y)
|
|
end
|
|
|
|
if (state[SteamVR_Touchpad].touched) then
|
|
table.insert(touches, ButtonFromQuadrant(state[SteamVR_Touchpad], right_hand))
|
|
elseif (state.Grip.pressed) then
|
|
table.insert(touches, right_hand and ovrTouch_RThumbUp or ovrTouch_LThumbUp)
|
|
end
|
|
|
|
if (state[SteamVR_Trigger].touched) then
|
|
table.insert(touches, right_hand and ovrTouch_RIndexTrigger or ovrTouch_LIndexTrigger)
|
|
elseif (state.Grip.pressed) then
|
|
table.insert(touches, right_hand and ovrTouch_RIndexPointing or ovrTouch_LIndexPointing)
|
|
end
|
|
|
|
return unpack(touches)
|
|
end
|
|
|
|
function ApplyDeadzone(axis, deadZoneLow, deadZoneHigh)
|
|
mag = math.sqrt(axis.x^2 + axis.y^2)
|
|
if (mag > deadZoneLow) then
|
|
-- scale such that output magnitude is in the range [0, 1]
|
|
legalRange = 1 - deadZoneHigh - deadZoneLow
|
|
normalizedMag = math.min(1, (mag - deadZoneLow) / legalRange)
|
|
scale = normalizedMag / mag
|
|
return axis.x * scale, axis.y * scale
|
|
else
|
|
-- stick is in the inner dead zone
|
|
return 0, 0
|
|
end
|
|
end
|
|
|
|
local was_touched = false
|
|
local center = {x=0, y=0}
|
|
function GetThumbstick(right_hand, deadzone)
|
|
if (string.match(controller_model, "Knuckles")) then
|
|
-- For the knuckles we use the trackpad and apply a simple radial deadzone
|
|
return ApplyDeadzone(state[SteamVR_Touchpad], deadzone, 0)
|
|
end
|
|
|
|
-- Find a physical Joystick, skip the touchpad and trigger
|
|
for i=3,5 do
|
|
if (state[i].type == "Joystick") then
|
|
-- If there is a physical joystick use that axis with a simple radial deadzone
|
|
return ApplyDeadzone(state[i], deadzone, 0)
|
|
elseif (state[i].type == "None") then
|
|
-- This is not a valid axis anymore, so exit the loop
|
|
break
|
|
end
|
|
end
|
|
|
|
-- If we can't find a physical joystick, emulate one with the trackpad
|
|
local axis = state[SteamVR_Touchpad]
|
|
|
|
if (not axis.touched) then
|
|
-- we're not touching the touchpad
|
|
return 0, 0
|
|
elseif not was_touched then
|
|
-- center the virtual thumbstick at the location the touchpad is touched for the first time
|
|
center.x = axis.x
|
|
center.y = axis.y
|
|
end
|
|
was_touched = axis.touched
|
|
|
|
-- account for the center
|
|
local out = {x=axis.x - center.x, y=axis.y - center.y}
|
|
return ApplyDeadzone(out, deadzone, deadzone / 2)
|
|
end
|
|
|
|
local gripped = false
|
|
local was_pressed = false
|
|
local hybrid_time = 0
|
|
function GetTriggers(right_hand, grip_mode)
|
|
if (string.match(controller_model, "Knuckles")) then
|
|
return state[SteamVR_Trigger].x, state[4].y
|
|
end
|
|
|
|
if (state.Grip.pressed ~= was_pressed) then
|
|
-- Allow users to enable a toggled grip.
|
|
if (grip_mode.hybrid) then
|
|
-- In hybrid grip mode the user will toggle the grip if it has been released within the delay time.
|
|
if (state.Grip.pressed) then
|
|
-- Only set the timestamp on when we're not toggled on, we don't want to toggle twice.
|
|
if (not gripped) then
|
|
hybrid_time = time + grip_mode.delay
|
|
end
|
|
gripped = true
|
|
else
|
|
-- If the user releases the grip after the delay has passed, then we can release the grip normally.
|
|
if (time > hybrid_time) then
|
|
gripped = false
|
|
end
|
|
-- Reset the timestamp so we immediately release the next time.
|
|
hybrid_time = 0
|
|
end
|
|
elseif (grip_mode.toggle) then
|
|
-- A simple grip toggle
|
|
if (state.Grip.pressed) then
|
|
gripped = not gripped
|
|
end
|
|
else
|
|
gripped = state.Grip.pressed
|
|
end
|
|
end
|
|
was_pressed = state.Grip.pressed
|
|
|
|
if (grip_mode.trigger) then
|
|
-- Some users prefer the trigger and grip to be swapped.
|
|
return gripped and 1 or 0, state[SteamVR_Trigger].x
|
|
else
|
|
-- When we release the grip we need to keep it just a little bit pressed.
|
|
-- This is necessary because Toybox can't handle a sudden jump to zero.
|
|
return state[SteamVR_Trigger].x, gripped and 1 or 0.01
|
|
end
|
|
end
|