Add ultimate xr
This commit is contained in:
@@ -0,0 +1,658 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrSteamVRControllerInput.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using System.Collections.Generic;
|
||||
using UltimateXR.Avatar.Controllers;
|
||||
using UltimateXR.Core;
|
||||
using UltimateXR.Haptics;
|
||||
using UnityEngine;
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Valve.VR;
|
||||
using UltimateXR.Avatar.Rig;
|
||||
using UltimateXR.Core.Settings;
|
||||
using UltimateXR.Manipulation;
|
||||
#endif
|
||||
|
||||
#pragma warning disable 414 // Disable warnings due to unused values
|
||||
|
||||
namespace UltimateXR.Devices.Integrations.SteamVR
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for all SteamVR input devices.
|
||||
/// Provides common input handling thanks to using the actions exported by the
|
||||
/// SteamVRActionsExporter.
|
||||
/// Child classes will require some overrides and minimal input handling if necessary.
|
||||
/// </summary>
|
||||
public abstract class UxrSteamVRControllerInput : UxrControllerInput
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
// These will be shown only in custom inspectors for controllers that use them (f.e. index controllers).
|
||||
[SerializeField] [HideInInspector] private string _openHandPoseName;
|
||||
[SerializeField] [HideInInspector] private float _indexCurlAmount = 60.0f;
|
||||
[SerializeField] [HideInInspector] private float _middleCurlAmount = 60.0f;
|
||||
[SerializeField] [HideInInspector] private float _ringCurlAmount = 60.0f;
|
||||
[SerializeField] [HideInInspector] private float _littleCurlAmount = 60.0f;
|
||||
[SerializeField] [HideInInspector] private float _thumbCurlAmount = 60.0f;
|
||||
[SerializeField] [HideInInspector] private float _thumbSpreadAmount = 30.0f;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Types & Data
|
||||
|
||||
/// <summary>
|
||||
/// Gets list of controller names that the component can handle.
|
||||
/// </summary>
|
||||
public abstract IEnumerable<string> ControllerNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the class will use hand skeletons.
|
||||
/// </summary>
|
||||
public virtual bool UsesHandSkeletons => false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Overrides UxrControllerInput
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsHandednessSupported => true;
|
||||
|
||||
/// <summary>
|
||||
/// SteamVR child classes will require SteamVR SDK to access functionality.
|
||||
/// </summary>
|
||||
public override string SDKDependency => UxrConstants.SdkSteamVR;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsControllerEnabled(UxrHandSide handSide)
|
||||
{
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
if (s_controllerList.TryGetValue(GetType().Name, out List<int> controllerIndices))
|
||||
{
|
||||
return controllerIndices.Contains(handSide == UxrHandSide.Left
|
||||
? (int)OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand)
|
||||
: (int)OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.RightHand));
|
||||
}
|
||||
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override float GetInput1D(UxrHandSide handSide, UxrInput1D input1D, bool getIgnoredInput = false)
|
||||
{
|
||||
if (ShouldIgnoreInput(handSide, getIgnoredInput))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
SteamVR_Input_Sources source = handSide == UxrHandSide.Left ? SteamVR_Input_Sources.LeftHand : SteamVR_Input_Sources.RightHand;
|
||||
|
||||
if (_actionsInput1D.TryGetValue(input1D, out SteamVR_Action_Single action))
|
||||
{
|
||||
return action[source].axis;
|
||||
}
|
||||
|
||||
#endif
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Vector2 GetInput2D(UxrHandSide handSide, UxrInput2D input2D, bool getIgnoredInput = false)
|
||||
{
|
||||
if (ShouldIgnoreInput(handSide, getIgnoredInput))
|
||||
{
|
||||
return Vector2.zero;
|
||||
}
|
||||
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
SteamVR_Input_Sources source = handSide == UxrHandSide.Left ? SteamVR_Input_Sources.LeftHand : SteamVR_Input_Sources.RightHand;
|
||||
|
||||
if (_actionsInput2D.TryGetValue(input2D, out SteamVR_Action_Vector2 action))
|
||||
{
|
||||
return FilterTwoAxesDeadZone(action[source].axis, JoystickDeadZone);
|
||||
}
|
||||
|
||||
#endif
|
||||
return Vector2.zero;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SendHapticFeedback(UxrHandSide handSide, UxrHapticClip hapticClip)
|
||||
{
|
||||
if (hapticClip.FallbackClipType != UxrHapticClipType.None)
|
||||
{
|
||||
SendHapticFeedback(handSide, hapticClip.FallbackClipType, hapticClip.FallbackAmplitude, hapticClip.FallbackDurationSeconds, hapticClip.HapticMode);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SendHapticFeedback(UxrHandSide handSide,
|
||||
float frequency,
|
||||
float amplitude,
|
||||
float durationSeconds,
|
||||
UxrHapticMode hapticMode = UxrHapticMode.Mix)
|
||||
{
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
SteamVR_Input_Sources source = handSide == UxrHandSide.Left ? SteamVR_Input_Sources.LeftHand : SteamVR_Input_Sources.RightHand;
|
||||
_handHapticsAction.Execute(0.0f, durationSeconds, frequency, amplitude, source);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void StopHapticFeedback(UxrHandSide handSide)
|
||||
{
|
||||
// TODO. Doesn't seem to be supported.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Takes care of registering the component in the global list of SteamVR input components.
|
||||
/// Builds the action list to access input and starts listening for device connections.
|
||||
/// </summary>
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
// Build actions
|
||||
BuildActionObjects();
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
// Listen to device connected events
|
||||
SteamVR_Events.DeviceConnected.Remove(OnDeviceConnected);
|
||||
SteamVR_Events.DeviceConnected.Listen(OnDeviceConnected);
|
||||
}
|
||||
|
||||
_awakeFinished = true;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
// Disabled by default at the beginning, unless we already these controllers registered.
|
||||
// If we already have the controllers registered it is due to an Awake() when loading a new scene.
|
||||
enabled = s_controllerList.TryGetValue(InputClassName, out List<int> controllerIndices) && controllerIndices.Count > 0;
|
||||
RaiseConnectOnStart = enabled;
|
||||
|
||||
if (!s_initializedSteamVR)
|
||||
{
|
||||
global::Valve.VR.SteamVR.Initialize();
|
||||
SteamVR_Input.GetActionSet(UxrSteamVRConstants.ActionSetName).Activate();
|
||||
s_initializedSteamVR = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the component is disabled. In the case the component was using skeletal
|
||||
/// input, the hand will be driven by the Avatar Animator back again.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
if (UsesHandSkeletons)
|
||||
{
|
||||
if (!_awakeFinished || !UxrManager.Instance || !Avatar || !Avatar.AvatarController)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UxrStandardAvatarController standardAvatarController = Avatar.AvatarController as UxrStandardAvatarController;
|
||||
|
||||
if (standardAvatarController == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_openHandPoseName))
|
||||
{
|
||||
standardAvatarController.LeftHandDefaultPoseNameOverride = null;
|
||||
standardAvatarController.RightHandDefaultPoseNameOverride = null;
|
||||
standardAvatarController.LeftHandGrabPoseNameOverride = null;
|
||||
standardAvatarController.RightHandGrabPoseNameOverride = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes SteamVR if necessary and activates the UltimateXR action set.
|
||||
/// Will initialize skeleton functionality if necessary.
|
||||
/// </summary>
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
if (UsesHandSkeletons)
|
||||
{
|
||||
_handSkeletonActionLeft.SetSkeletalTransformSpace(EVRSkeletalTransformSpace.Model);
|
||||
_handSkeletonActionRight.SetSkeletalTransformSpace(EVRSkeletalTransformSpace.Model);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the component has skeleton capabilities, the hand bones will be updated here.
|
||||
/// </summary>
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (Avatar == null)
|
||||
{
|
||||
}
|
||||
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
// Update using skeleton if necessary
|
||||
if (UsesHandSkeletons)
|
||||
{
|
||||
UxrStandardAvatarController avatarControllerStandard = Avatar.AvatarController as UxrStandardAvatarController;
|
||||
UxrAvatarRig avatarRig = Avatar.AvatarRig;
|
||||
|
||||
if (avatarControllerStandard == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float curlIndex = _handSkeletonActionLeft.fingerCurls[SteamVR_Skeleton_FingerIndexes.index] * _indexCurlAmount;
|
||||
float curlMiddle = _handSkeletonActionLeft.fingerCurls[SteamVR_Skeleton_FingerIndexes.middle] * _middleCurlAmount;
|
||||
float curlRing = _handSkeletonActionLeft.fingerCurls[SteamVR_Skeleton_FingerIndexes.ring] * _ringCurlAmount;
|
||||
float curlLittle = _handSkeletonActionLeft.fingerCurls[SteamVR_Skeleton_FingerIndexes.pinky] * _littleCurlAmount;
|
||||
float curlThumb = _handSkeletonActionLeft.fingerCurls[SteamVR_Skeleton_FingerIndexes.thumb] * _thumbCurlAmount;
|
||||
float splayThumb = _handSkeletonActionLeft.fingerSplays[SteamVR_Skeleton_FingerIndexes.thumb] * _thumbSpreadAmount;
|
||||
|
||||
if (!UxrGrabManager.Instance.IsHandGrabbing(Avatar, UxrHandSide.Left) && !avatarControllerStandard.IsLeftHandInsideFingerPointingVolume)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_openHandPoseName))
|
||||
{
|
||||
avatarControllerStandard.LeftHandDefaultPoseNameOverride = _openHandPoseName;
|
||||
avatarControllerStandard.LeftHandGrabPoseNameOverride = _openHandPoseName;
|
||||
Avatar.SetCurrentHandPoseImmediately(UxrHandSide.Left, _openHandPoseName);
|
||||
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Left, Avatar.LeftHand.Index, curlIndex, curlIndex, curlIndex);
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Left, Avatar.LeftHand.Middle, curlMiddle, curlMiddle, curlMiddle);
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Left, Avatar.LeftHand.Ring, curlRing, curlRing, curlRing);
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Left, Avatar.LeftHand.Little, curlLittle, curlLittle, curlLittle);
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Left, Avatar.LeftHand.Thumb, curlThumb * 0.1f, curlThumb * 0.3f, curlThumb * 1.0f, splayThumb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_openHandPoseName))
|
||||
{
|
||||
avatarControllerStandard.LeftHandDefaultPoseNameOverride = null;
|
||||
}
|
||||
}
|
||||
|
||||
curlIndex = _handSkeletonActionRight.fingerCurls[SteamVR_Skeleton_FingerIndexes.index] * _indexCurlAmount;
|
||||
curlMiddle = _handSkeletonActionRight.fingerCurls[SteamVR_Skeleton_FingerIndexes.middle] * _middleCurlAmount;
|
||||
curlRing = _handSkeletonActionRight.fingerCurls[SteamVR_Skeleton_FingerIndexes.ring] * _ringCurlAmount;
|
||||
curlLittle = _handSkeletonActionRight.fingerCurls[SteamVR_Skeleton_FingerIndexes.pinky] * _littleCurlAmount;
|
||||
curlThumb = _handSkeletonActionRight.fingerCurls[SteamVR_Skeleton_FingerIndexes.thumb] * _thumbCurlAmount;
|
||||
splayThumb = _handSkeletonActionRight.fingerSplays[SteamVR_Skeleton_FingerIndexes.thumb] * _thumbSpreadAmount;
|
||||
|
||||
if (!UxrGrabManager.Instance.IsHandGrabbing(Avatar, UxrHandSide.Right) && !avatarControllerStandard.IsRightHandInsideFingerPointingVolume)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_openHandPoseName))
|
||||
{
|
||||
avatarControllerStandard.RightHandDefaultPoseNameOverride = _openHandPoseName;
|
||||
avatarControllerStandard.RightHandGrabPoseNameOverride = _openHandPoseName;
|
||||
Avatar.SetCurrentHandPoseImmediately(UxrHandSide.Right, _openHandPoseName);
|
||||
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Right, Avatar.RightHand.Index, curlIndex, curlIndex, curlIndex);
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Right, Avatar.RightHand.Middle, curlMiddle, curlMiddle, curlMiddle);
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Right, Avatar.RightHand.Ring, curlRing, curlRing, curlRing);
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Right, Avatar.RightHand.Little, curlLittle, curlLittle, curlLittle);
|
||||
UxrAvatarRig.CurlFinger(Avatar, UxrHandSide.Right, Avatar.RightHand.Thumb, curlThumb * 0.1f, curlThumb * 0.3f, curlThumb * 1.0f, splayThumb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_openHandPoseName))
|
||||
{
|
||||
avatarControllerStandard.RightHandDefaultPoseNameOverride = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected Overrides UxrControllerInput
|
||||
|
||||
/// <summary>
|
||||
/// Updates the complete input state using our common SteamVR actions. This allows to use the same interface
|
||||
/// for all controllers and enables the implementation of new devices with minimal effort.
|
||||
/// </summary>
|
||||
protected override void UpdateInput()
|
||||
{
|
||||
base.UpdateInput();
|
||||
|
||||
// Get joystick values
|
||||
Vector2 leftJoystickValue = GetInput2D(UxrHandSide.Left, UxrInput2D.Joystick);
|
||||
Vector2 rightJoystickValue = GetInput2D(UxrHandSide.Right, UxrInput2D.Joystick);
|
||||
Vector2 leftJoystick2Value = GetInput2D(UxrHandSide.Left, UxrInput2D.Joystick2);
|
||||
Vector2 rightJoystick2Value = GetInput2D(UxrHandSide.Right, UxrInput2D.Joystick2);
|
||||
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
var system = OpenVR.System;
|
||||
|
||||
if (system == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update buttons
|
||||
foreach (UxrInputButtons button in Enum.GetValues(typeof(UxrInputButtons)))
|
||||
{
|
||||
if (button != UxrInputButtons.None && button != UxrInputButtons.Any && button != UxrInputButtons.Everything)
|
||||
{
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, button, _actionsButtonClick[button][SteamVR_Input_Sources.LeftHand].state);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, button, _actionsButtonClick[button][SteamVR_Input_Sources.RightHand].state);
|
||||
SetButtonFlags(ButtonFlags.TouchFlagsLeft, button, _actionsButtonTouch[button][SteamVR_Input_Sources.LeftHand].state);
|
||||
SetButtonFlags(ButtonFlags.TouchFlagsRight, button, _actionsButtonTouch[button][SteamVR_Input_Sources.RightHand].state);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// These ones are mainly for teleporting functionality when we don't get touch values out of joysticks:
|
||||
if (leftJoystickValue != Vector2.zero && leftJoystickValue.magnitude > AnalogAsDPadThreshold)
|
||||
{
|
||||
SetButtonFlags(ButtonFlags.TouchFlagsLeft, UxrInputButtons.Joystick, true);
|
||||
}
|
||||
|
||||
if (rightJoystickValue != Vector2.zero && rightJoystickValue.magnitude > AnalogAsDPadThreshold)
|
||||
{
|
||||
SetButtonFlags(ButtonFlags.TouchFlagsRight, UxrInputButtons.Joystick, true);
|
||||
}
|
||||
|
||||
// Same for joystick2 just in case
|
||||
if (leftJoystick2Value != Vector2.zero && leftJoystick2Value.magnitude > AnalogAsDPadThreshold)
|
||||
{
|
||||
SetButtonFlags(ButtonFlags.TouchFlagsLeft, UxrInputButtons.Joystick2, true);
|
||||
}
|
||||
|
||||
if (rightJoystick2Value != Vector2.zero && rightJoystick2Value.magnitude > AnalogAsDPadThreshold)
|
||||
{
|
||||
SetButtonFlags(ButtonFlags.TouchFlagsRight, UxrInputButtons.Joystick2, true);
|
||||
}
|
||||
|
||||
// Update joystick/DPad direction buttons using joystick analog value and pressed state
|
||||
uint leftDirectionFlags = GetButtonFlags(MainJoystickIsTouchpad ? ButtonFlags.PressFlagsLeft : ButtonFlags.TouchFlagsLeft);
|
||||
|
||||
if (leftJoystickValue != Vector2.zero && leftJoystickValue.magnitude > AnalogAsDPadThreshold && (leftDirectionFlags & (int)UxrInputButtons.Joystick) != 0)
|
||||
{
|
||||
float leftJoystickAngle = Input2DToAngle(leftJoystickValue);
|
||||
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.DPadLeft, IsInput2dDPadLeft(leftJoystickAngle));
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.DPadRight, IsInput2dDPadRight(leftJoystickAngle));
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.DPadUp, IsInput2dDPadUp(leftJoystickAngle));
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.DPadDown, IsInput2dDPadDown(leftJoystickAngle));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.DPadLeft, false);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.DPadRight, false);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.DPadUp, false);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.DPadDown, false);
|
||||
}
|
||||
|
||||
uint leftButtonPressFlags = GetButtonFlags(ButtonFlags.PressFlagsLeft);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.JoystickLeft, (leftButtonPressFlags & (uint)UxrInputButtons.DPadLeft) != 0);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.JoystickRight, (leftButtonPressFlags & (uint)UxrInputButtons.DPadRight) != 0);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.JoystickUp, (leftButtonPressFlags & (uint)UxrInputButtons.DPadUp) != 0);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsLeft, UxrInputButtons.JoystickDown, (leftButtonPressFlags & (uint)UxrInputButtons.DPadDown) != 0);
|
||||
|
||||
uint rightDirectionFlags = GetButtonFlags(MainJoystickIsTouchpad ? ButtonFlags.PressFlagsRight : ButtonFlags.TouchFlagsRight);
|
||||
|
||||
if (rightJoystickValue != Vector2.zero && rightJoystickValue.magnitude > AnalogAsDPadThreshold && (rightDirectionFlags & (int)UxrInputButtons.Joystick) != 0)
|
||||
{
|
||||
float rightJoystickAngle = Input2DToAngle(rightJoystickValue);
|
||||
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.DPadLeft, IsInput2dDPadLeft(rightJoystickAngle));
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.DPadRight, IsInput2dDPadRight(rightJoystickAngle));
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.DPadUp, IsInput2dDPadUp(rightJoystickAngle));
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.DPadDown, IsInput2dDPadDown(rightJoystickAngle));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.DPadLeft, false);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.DPadRight, false);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.DPadUp, false);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.DPadDown, false);
|
||||
}
|
||||
|
||||
uint rightButtonPressFlags = GetButtonFlags(ButtonFlags.PressFlagsRight);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.JoystickLeft, (rightButtonPressFlags & (uint)UxrInputButtons.DPadLeft) != 0);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.JoystickRight, (rightButtonPressFlags & (uint)UxrInputButtons.DPadRight) != 0);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.JoystickUp, (rightButtonPressFlags & (uint)UxrInputButtons.DPadUp) != 0);
|
||||
SetButtonFlags(ButtonFlags.PressFlagsRight, UxrInputButtons.JoystickDown, (rightButtonPressFlags & (uint)UxrInputButtons.DPadDown) != 0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Types & Data
|
||||
|
||||
private string InputClassName => GetType().Name;
|
||||
|
||||
// Global data
|
||||
private static readonly Dictionary<string, List<int>> s_controllerList = new Dictionary<string, List<int>>();
|
||||
private static bool s_initializedSteamVR;
|
||||
|
||||
// Local data
|
||||
private bool _awakeFinished;
|
||||
|
||||
#endregion
|
||||
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
|
||||
/// <summary>
|
||||
/// Given a controller name, gets a list of controller names using the Virtual Desktop controller naming convention.
|
||||
/// </summary>
|
||||
/// <param name="controllerName">Controller name to get the virtual desktop controller names for</param>
|
||||
/// <returns>List of virtual desktop controller names</returns>
|
||||
private static IEnumerable<string> GetVirtualDesktopWrappedControllerNames(string controllerName)
|
||||
{
|
||||
yield return $"OpenVR Controller({controllerName}) - Left";
|
||||
yield return $"OpenVR Controller({controllerName}) - Right";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a SteamVR device is connected
|
||||
/// </summary>
|
||||
/// <param name="index">Device index</param>
|
||||
/// <param name="connected">True if connected, false if disconnected</param>
|
||||
private static void OnDeviceConnected(int index, bool connected)
|
||||
{
|
||||
if (OpenVR.System == null)
|
||||
{
|
||||
if (UxrGlobalSettings.Instance.LogLevelDevices >= UxrLogLevel.Errors)
|
||||
{
|
||||
Debug.LogError($"{UxrConstants.DevicesModule} {nameof(UxrSteamVRControllerInput)}::{nameof(OnDeviceConnected)}: OpenVR.System is null");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (OpenVR.System.GetTrackedDeviceClass((uint)index) != ETrackedDeviceClass.Controller)
|
||||
{
|
||||
// Ignore devices that aren't controllers
|
||||
return;
|
||||
}
|
||||
|
||||
var renderModelName = new StringBuilder(ModelNameMaxLength);
|
||||
var error = ETrackedPropertyError.TrackedProp_Success;
|
||||
|
||||
OpenVR.System.GetStringTrackedDeviceProperty((uint)index, ETrackedDeviceProperty.Prop_ModelNumber_String, renderModelName, ModelNameMaxLength, ref error);
|
||||
|
||||
string modelNameString = renderModelName.ToString();
|
||||
|
||||
if (UxrGlobalSettings.Instance.LogLevelDevices >= UxrLogLevel.Relevant)
|
||||
{
|
||||
Debug.Log($"{UxrConstants.DevicesModule} {nameof(UxrSteamVRControllerInput)}::{nameof(OnDeviceConnected)}: connected={connected}, model={modelNameString}");
|
||||
}
|
||||
|
||||
IEnumerable<UxrSteamVRControllerInput> inputsSteamVR = AllComponents.Where(i => i is UxrSteamVRControllerInput).Cast<UxrSteamVRControllerInput>();
|
||||
|
||||
UxrSteamVRControllerInput inputSteamVR = inputsSteamVR.FirstOrDefault(i =>
|
||||
i.ControllerNames.Any(n => string.Equals(n, modelNameString)) || i.ControllerNames.SelectMany(GetVirtualDesktopWrappedControllerNames).Any(n => string.Equals(n, modelNameString)));
|
||||
|
||||
if (inputSteamVR != null)
|
||||
{
|
||||
// Model is one of the registered SteamVR inputs and needs to be processed
|
||||
if (UxrGlobalSettings.Instance.LogLevelDevices >= UxrLogLevel.Relevant)
|
||||
{
|
||||
Debug.Log($"{UxrConstants.DevicesModule} {nameof(UxrSteamVRControllerInput)}::{nameof(OnDeviceConnected)}: Device name {modelNameString} was registered by {inputSteamVR.InputClassName} and is being processed!");
|
||||
}
|
||||
|
||||
if (!s_controllerList.TryGetValue(inputSteamVR.InputClassName, out List<int> controllerIndices))
|
||||
{
|
||||
controllerIndices = new List<int>();
|
||||
s_controllerList.Add(inputSteamVR.InputClassName, controllerIndices);
|
||||
}
|
||||
|
||||
if (connected)
|
||||
{
|
||||
// Connected
|
||||
controllerIndices.Add(index);
|
||||
|
||||
if (inputSteamVR.enabled == false)
|
||||
{
|
||||
// First controller: Notify device is connected since we consider the device the whole setup
|
||||
inputSteamVR.enabled = true;
|
||||
inputSteamVR.OnDeviceConnected(new UxrDeviceConnectEventArgs(true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disconnected
|
||||
controllerIndices.Remove(index);
|
||||
|
||||
if (controllerIndices.Count == 0)
|
||||
{
|
||||
// Last controller disconnected: Notify device is disconnected.
|
||||
inputSteamVR.enabled = false;
|
||||
inputSteamVR.OnDeviceConnected(new UxrDeviceConnectEventArgs(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (UxrGlobalSettings.Instance.LogLevelDevices >= UxrLogLevel.Relevant)
|
||||
{
|
||||
Debug.Log($"{UxrConstants.DevicesModule} {nameof(UxrSteamVRControllerInput)}::{nameof(OnDeviceConnected)}: Device is not recognized as input by any of {inputsSteamVR.Count()} components");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the action bound to the given button and input type.
|
||||
/// </summary>
|
||||
/// <param name="button">Button to look for</param>
|
||||
/// <param name="inputType">Type of input to handle. Use <see cref="UxrSteamVRConstants" />.</param>
|
||||
/// <returns>
|
||||
/// Action bound to the given button and input type. If the button doesn't exist
|
||||
/// in the current controller it will return a fake action showing no input
|
||||
/// </returns>
|
||||
private static SteamVR_Action_Boolean GetButtonAction(UxrInputButtons button, string inputType)
|
||||
{
|
||||
return SteamVR_Input.GetAction<SteamVR_Action_Boolean>(UxrSteamVRConstants.ActionSetName, $"{button.ToString().ToLower()}_{inputType}_{UxrSteamVRConstants.BindingVarBool}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the action bound to the given <see cref="UxrInput1D" />.
|
||||
/// </summary>
|
||||
/// <param name="input1D">Element to look for</param>
|
||||
/// <returns>
|
||||
/// Action bound to the given 1D input. If the element doesn't exist in the current controller it will return a
|
||||
/// fake action showing no input
|
||||
/// </returns>
|
||||
private static SteamVR_Action_Single GetInput1DAction(UxrInput1D input1D)
|
||||
{
|
||||
return SteamVR_Input.GetAction<SteamVR_Action_Single>(UxrSteamVRConstants.ActionSetName, $"{input1D.ToString().ToLower()}_{UxrSteamVRConstants.BindingVarVector1}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the action bound to the given <see cref="UxrInput2D" />.
|
||||
/// </summary>
|
||||
/// <param name="input2D">Element to look for</param>
|
||||
/// <returns>
|
||||
/// Action bound to the given 2D input. If the element doesn't exist in the current controller it will return a fake
|
||||
/// action showing no input
|
||||
/// </returns>
|
||||
private static SteamVR_Action_Vector2 GetInput2DAction(UxrInput2D input2D)
|
||||
{
|
||||
return SteamVR_Input.GetAction<SteamVR_Action_Vector2>(UxrSteamVRConstants.ActionSetName, $"{input2D.ToString().ToLower()}_{UxrSteamVRConstants.BindingVarVector2}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds all action objects needed to check for input using SteamVR.
|
||||
/// We use enumeration of all elements inside an Enum to build our action list and,
|
||||
/// thanks to the functionality of SteamVR, when an action doesn't exist it will
|
||||
/// generate a fake action showing no input.
|
||||
/// </summary>
|
||||
private void BuildActionObjects()
|
||||
{
|
||||
// Buttons
|
||||
foreach (UxrInputButtons button in Enum.GetValues(typeof(UxrInputButtons)))
|
||||
{
|
||||
if (button != UxrInputButtons.None && button != UxrInputButtons.Any && button != UxrInputButtons.Everything)
|
||||
{
|
||||
_actionsButtonClick.Add(button, GetButtonAction(button, UxrSteamVRConstants.BindingInputClick));
|
||||
_actionsButtonTouch.Add(button, GetButtonAction(button, UxrSteamVRConstants.BindingInputTouch));
|
||||
}
|
||||
}
|
||||
|
||||
// UxrInput1D
|
||||
foreach (UxrInput1D input1D in Enum.GetValues(typeof(UxrInput1D)))
|
||||
{
|
||||
if (input1D != UxrInput1D.None)
|
||||
{
|
||||
_actionsInput1D.Add(input1D, GetInput1DAction(input1D));
|
||||
}
|
||||
}
|
||||
|
||||
// UxrInput2D
|
||||
foreach (UxrInput2D input2D in Enum.GetValues(typeof(UxrInput2D)))
|
||||
{
|
||||
if (input2D != UxrInput2D.None)
|
||||
{
|
||||
_actionsInput2D.Add(input2D, GetInput2DAction(input2D));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ULTIMATEXR_USE_STEAMVR_SDK
|
||||
private const int ModelNameMaxLength = 256;
|
||||
|
||||
private readonly Dictionary<UxrInputButtons, SteamVR_Action_Boolean> _actionsButtonClick = new Dictionary<UxrInputButtons, SteamVR_Action_Boolean>();
|
||||
private readonly Dictionary<UxrInputButtons, SteamVR_Action_Boolean> _actionsButtonTouch = new Dictionary<UxrInputButtons, SteamVR_Action_Boolean>();
|
||||
private readonly Dictionary<UxrInput1D, SteamVR_Action_Single> _actionsInput1D = new Dictionary<UxrInput1D, SteamVR_Action_Single>();
|
||||
private readonly Dictionary<UxrInput2D, SteamVR_Action_Vector2> _actionsInput2D = new Dictionary<UxrInput2D, SteamVR_Action_Vector2>();
|
||||
|
||||
private readonly SteamVR_Action_Skeleton _handSkeletonActionLeft = SteamVR_Input.GetAction<SteamVR_Action_Skeleton>(UxrSteamVRConstants.ActionSetName, UxrSteamVRConstants.ActionNameHandSkeletonLeft);
|
||||
private readonly SteamVR_Action_Skeleton _handSkeletonActionRight = SteamVR_Input.GetAction<SteamVR_Action_Skeleton>(UxrSteamVRConstants.ActionSetName, UxrSteamVRConstants.ActionNameHandSkeletonRight);
|
||||
private readonly SteamVR_Action_Vibration _handHapticsAction = SteamVR_Input.GetAction<SteamVR_Action_Vibration>(UxrSteamVRConstants.ActionSetName, UxrSteamVRConstants.ActionNameHandHaptics);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 414 // Restore warnings due to unused values
|
||||
Reference in New Issue
Block a user