Replace UltimateXR with HurricaneVR
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
#if HVR_OCULUS
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
#if HVR_INPUT_SYSTEM && ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace HurricaneVR.Framework.Oculus
|
||||
{
|
||||
public class HVRGestureDetector : MonoBehaviour
|
||||
{
|
||||
public OVRSkeleton Skeleton;
|
||||
public List<HVRGesture> Gestures = new List<HVRGesture>();
|
||||
private HVRGesture CurrentGesture;
|
||||
private HVRGesture _previousGesture;
|
||||
|
||||
public float BoneThreshold = .1f;
|
||||
public float GestureTimeNeeded = 1.5f;
|
||||
public float GestureTimer;
|
||||
public HVRHandSide HandSide;
|
||||
private bool _activated;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
|
||||
CheckAddGesture();
|
||||
|
||||
#endif
|
||||
if (!Skeleton || !Skeleton.IsInitialized || !Skeleton.IsDataValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var closest = DetectGesture();
|
||||
|
||||
if (CurrentGesture == null && closest != null)
|
||||
{
|
||||
CurrentGesture = closest;
|
||||
}
|
||||
|
||||
if (CurrentGesture == closest && CurrentGesture != null)
|
||||
{
|
||||
GestureTimer += Time.deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
GestureTimer -= Time.deltaTime;
|
||||
}
|
||||
|
||||
if (_activated && CurrentGesture != _previousGesture)
|
||||
{
|
||||
GestureTimer = 0f;
|
||||
|
||||
}
|
||||
GestureTimer = Mathf.Clamp(GestureTimer, 0, GestureTimeNeeded + .1f);
|
||||
if (Mathf.Approximately(GestureTimer, 0f))
|
||||
{
|
||||
CurrentGesture = closest;
|
||||
}
|
||||
|
||||
if (!_activated && GestureTimer > GestureTimeNeeded && CurrentGesture != null)
|
||||
{
|
||||
_activated = true;
|
||||
CurrentGesture.GestureCompleted.Invoke();
|
||||
Debug.Log($"{CurrentGesture.Name} gestured!");
|
||||
}
|
||||
|
||||
if (CurrentGesture != _previousGesture && _activated)
|
||||
{
|
||||
_activated = false;
|
||||
}
|
||||
|
||||
_previousGesture = CurrentGesture;
|
||||
|
||||
}
|
||||
|
||||
private void CheckAddGesture()
|
||||
{
|
||||
bool pressed;
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
pressed = Input.GetKeyDown(KeyCode.L) && HandSide == HVRHandSide.Left || Input.GetKeyDown(KeyCode.R) && HandSide == HVRHandSide.Right;
|
||||
#elif HVR_INPUT_SYSTEM && ENABLE_INPUT_SYSTEM
|
||||
pressed = Keyboard.current[Key.L].wasPressedThisFrame && HandSide == HVRHandSide.Left ||
|
||||
Keyboard.current[Key.R].wasPressedThisFrame && HandSide == HVRHandSide.Right;
|
||||
#endif
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
var gesture = new HVRGesture();
|
||||
gesture.Name = "NoName";
|
||||
foreach (var bone in Skeleton.Bones)
|
||||
{
|
||||
gesture.PositionOffsets.Add(Skeleton.transform.InverseTransformPoint(bone.Transform.position));
|
||||
}
|
||||
|
||||
Gestures.Add(gesture);
|
||||
DetectGesture();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private HVRGesture DetectGesture()
|
||||
{
|
||||
HVRGesture closest = null;
|
||||
|
||||
var currentMin = Mathf.Infinity;
|
||||
for (var j = 0; j < Gestures.Count; j++)
|
||||
{
|
||||
var gesture = Gestures[j];
|
||||
var total = 0f;
|
||||
var isInvalid = false;
|
||||
|
||||
for (var i = 0; i < Skeleton.Bones.Count; i++)
|
||||
{
|
||||
var bone = Skeleton.Bones[i];
|
||||
var position = Skeleton.transform.InverseTransformPoint(bone.Transform.position);
|
||||
var distance = Vector3.Distance(position, gesture.PositionOffsets[i]);
|
||||
|
||||
if (distance > BoneThreshold)
|
||||
{
|
||||
isInvalid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
total += distance;
|
||||
}
|
||||
|
||||
if (!isInvalid && total < currentMin)
|
||||
{
|
||||
currentMin = total;
|
||||
closest = gesture;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class HVRGesture
|
||||
{
|
||||
public string Name;
|
||||
public List<Vector3> PositionOffsets = new List<Vector3>();
|
||||
public UnityEvent GestureCompleted = new UnityEvent();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 445b50449b3b35046b94bd0538def739
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,130 @@
|
||||
#if HVR_OCULUS
|
||||
using System.Collections;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace HurricaneVR.Framework.Oculus
|
||||
{
|
||||
public class HVROculusController : HVRController
|
||||
{
|
||||
public OVRInput.Controller ControllerMask => Side == HVRHandSide.Left ? OVRInput.Controller.LTouch : OVRInput.Controller.RTouch;
|
||||
public bool OVRHaptics { get; set; }
|
||||
|
||||
public static void UpdateOVRInput()
|
||||
{
|
||||
OVRInput.Update();
|
||||
}
|
||||
|
||||
protected override void UpdateInput()
|
||||
{
|
||||
JoystickAxis = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick, ControllerMask);
|
||||
Grip = OVRInput.Get(OVRInput.Axis1D.PrimaryHandTrigger, ControllerMask);
|
||||
Trigger = OVRInput.Get(OVRInput.Axis1D.PrimaryIndexTrigger, ControllerMask);
|
||||
|
||||
PrimaryButton = OVRInput.Get(OVRInput.Button.One, ControllerMask);
|
||||
SecondaryButton = OVRInput.Get(OVRInput.Button.Two, ControllerMask);
|
||||
|
||||
PrimaryTouch = OVRInput.Get(OVRInput.Touch.One, ControllerMask);
|
||||
SecondaryTouch = OVRInput.Get(OVRInput.Touch.Two, ControllerMask);
|
||||
|
||||
TriggerNearTouch = OVRInput.Get(OVRInput.NearTouch.PrimaryIndexTrigger, ControllerMask);
|
||||
ThumbNearTouch = OVRInput.Get(OVRInput.NearTouch.PrimaryThumbButtons, ControllerMask);
|
||||
|
||||
TriggerTouch = OVRInput.Get(OVRInput.Touch.PrimaryIndexTrigger, ControllerMask);
|
||||
ThumbTouch = OVRInput.Get(OVRInput.Touch.PrimaryThumbRest, ControllerMask);
|
||||
JoystickTouch = OVRInput.Get(OVRInput.Touch.PrimaryThumbstick, ControllerMask);
|
||||
|
||||
MenuButton = OVRInput.Get(OVRInput.Button.Start, ControllerMask);
|
||||
JoystickClicked = OVRInput.Get(OVRInput.Button.PrimaryThumbstick, ControllerMask);
|
||||
|
||||
GripButton = OVRInput.Get(OVRInput.Button.PrimaryHandTrigger, ControllerMask);
|
||||
TriggerButton = OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, ControllerMask);
|
||||
}
|
||||
|
||||
protected override void CheckButtonState(HVRButtons button, ref HVRButtonState buttonState)
|
||||
{
|
||||
ResetButton(ref buttonState);
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case HVRButtons.Grip:
|
||||
buttonState.Value = Grip;
|
||||
if (InputMap.GripUseAnalog)
|
||||
SetButtonState(button, ref buttonState, Grip >= InputMap.GripThreshold);
|
||||
else
|
||||
SetButtonState(button, ref buttonState, GripButton);
|
||||
|
||||
break;
|
||||
case HVRButtons.Trigger:
|
||||
buttonState.Value = Trigger;
|
||||
if (InputMap.TriggerUseAnalog)
|
||||
SetButtonState(button, ref buttonState, Trigger >= InputMap.TriggerThreshold);
|
||||
else
|
||||
SetButtonState(button, ref buttonState, TriggerButton);
|
||||
break;
|
||||
case HVRButtons.Primary:
|
||||
SetButtonState(button, ref buttonState, PrimaryButton);
|
||||
break;
|
||||
case HVRButtons.PrimaryTouch:
|
||||
SetButtonState(button, ref buttonState, PrimaryTouch);
|
||||
break;
|
||||
case HVRButtons.Secondary:
|
||||
SetButtonState(button, ref buttonState, SecondaryButton);
|
||||
break;
|
||||
case HVRButtons.SecondaryTouch:
|
||||
SetButtonState(button, ref buttonState, SecondaryTouch);
|
||||
break;
|
||||
case HVRButtons.Menu:
|
||||
SetButtonState(button, ref buttonState, MenuButton);
|
||||
break;
|
||||
case HVRButtons.JoystickButton:
|
||||
SetButtonState(button, ref buttonState, JoystickClicked);
|
||||
break;
|
||||
case HVRButtons.TrackPadButton:
|
||||
break;
|
||||
case HVRButtons.JoystickTouch:
|
||||
SetButtonState(button, ref buttonState, JoystickTouch);
|
||||
break;
|
||||
case HVRButtons.TriggerTouch:
|
||||
SetButtonState(button, ref buttonState, TriggerTouch);
|
||||
break;
|
||||
case HVRButtons.ThumbTouch:
|
||||
SetButtonState(button, ref buttonState, ThumbTouch);
|
||||
break;
|
||||
case HVRButtons.TriggerNearTouch:
|
||||
SetButtonState(button, ref buttonState, TriggerNearTouch);
|
||||
break;
|
||||
case HVRButtons.ThumbNearTouch:
|
||||
SetButtonState(button, ref buttonState, ThumbNearTouch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private Coroutine _vibrateRoutine;
|
||||
|
||||
public override void Vibrate(float amplitude, float duration = 1, float frequency = 1)
|
||||
{
|
||||
if (HVRSettings.Instance.DisableHaptics) return;
|
||||
if (OVRHaptics)
|
||||
{
|
||||
if (_vibrateRoutine != null)
|
||||
StopCoroutine(_vibrateRoutine);
|
||||
_vibrateRoutine = StartCoroutine(VibrateRoutine(amplitude, duration, frequency));
|
||||
}
|
||||
else
|
||||
{
|
||||
base.Vibrate(amplitude, duration, frequency);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator VibrateRoutine(float amplitude, float duration = 1, float frequency = 1)
|
||||
{
|
||||
OVRInput.SetControllerVibration(frequency, amplitude, ControllerMask);
|
||||
yield return new WaitForSeconds(duration);
|
||||
OVRInput.SetControllerVibration(0, 0, ControllerMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8033a30134ce6cf4da69194445b50a4c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,104 @@
|
||||
#if HVR_OCULUS
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Oculus
|
||||
{
|
||||
public class HVROculusHandAnimator : MonoBehaviour
|
||||
{
|
||||
public UnityEvent HandTrackingEnabled = new UnityEvent();
|
||||
public UnityEvent HandTrackingDisabled = new UnityEvent();
|
||||
|
||||
public OVRSkeleton Skeleton;
|
||||
|
||||
public OVRSkeleton.BoneId HandBoneId = OVRSkeleton.BoneId.Hand_Start;
|
||||
public Vector3 HandRotationOffset;
|
||||
public Vector3 HandPositionOffset;
|
||||
public Transform OffsetTarget;
|
||||
|
||||
public List<HVROculusBone> Bones = new List<HVROculusBone>();
|
||||
private HVROculusBone[] _boneMap;
|
||||
|
||||
private Vector3 _targetOriginalPosition;
|
||||
private Quaternion _targetOriginalRotation;
|
||||
private bool _previousIsHandTracking;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_boneMap = new HVROculusBone[(int)OVRSkeleton.BoneId.Max];
|
||||
foreach (var bone in Bones)
|
||||
{
|
||||
var index = (int)bone.OVRSkeletonBoneId;
|
||||
if (_boneMap[index] != null)
|
||||
{
|
||||
Debug.LogWarning($"{bone.OVRSkeletonBoneId} has already been mapped!");
|
||||
}
|
||||
|
||||
_boneMap[index] = bone;
|
||||
}
|
||||
|
||||
if (OffsetTarget)
|
||||
{
|
||||
_targetOriginalPosition = OffsetTarget.localPosition;
|
||||
_targetOriginalRotation = OffsetTarget.localRotation;
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (Skeleton && Skeleton.IsInitialized && Skeleton.IsDataValid)
|
||||
{
|
||||
if (!_previousIsHandTracking)
|
||||
{
|
||||
HandTrackingEnabled.Invoke();
|
||||
_previousIsHandTracking = true;
|
||||
}
|
||||
|
||||
if (OffsetTarget)
|
||||
{
|
||||
OffsetTarget.localRotation = Quaternion.Euler(HandRotationOffset);
|
||||
OffsetTarget.localPosition = HandPositionOffset;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Skeleton.Bones.Count; i++)
|
||||
{
|
||||
var ovrBone = Skeleton.Bones[i];
|
||||
var index = (int)ovrBone.Id;
|
||||
var bone = _boneMap[index];
|
||||
|
||||
//unity seems to fill my null array slots with empty objects?
|
||||
if (bone != null && bone.Transform)
|
||||
{
|
||||
bone.Transform.localRotation = bone.RotationOffset * ovrBone.Transform.localRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_previousIsHandTracking)
|
||||
{
|
||||
HandTrackingDisabled.Invoke();
|
||||
_previousIsHandTracking = false;
|
||||
}
|
||||
|
||||
if (OffsetTarget)
|
||||
{
|
||||
OffsetTarget.localRotation = _targetOriginalRotation;
|
||||
OffsetTarget.localPosition = _targetOriginalPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class HVROculusBone
|
||||
{
|
||||
public OVRSkeleton.BoneId OVRSkeletonBoneId;
|
||||
public Transform Transform;
|
||||
public Vector3 RotationOffsetEuler;
|
||||
public Quaternion RotationOffset => Quaternion.Euler(RotationOffsetEuler);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afde9f7da2484b5a931bcd0532556cbc
|
||||
timeCreated: 1600859810
|
||||
Reference in New Issue
Block a user