Replace UltimateXR with HurricaneVR
This commit is contained in:
8
Assets/HurricaneVR/Framework/Scripts/Components.meta
Normal file
8
Assets/HurricaneVR/Framework/Scripts/Components.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91ad5e85488a9994e8c254c2a88a77ad
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e538dc1865da2ed41b9f803e3e586405
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components.Creators
|
||||
{
|
||||
public class HVRPhysicsLeverCreator : MonoBehaviour
|
||||
{
|
||||
public Transform Anchor;
|
||||
public Transform Lever;
|
||||
public HVRAxis Axis;
|
||||
public float Mass = 5f;
|
||||
public float MinAngle = 90f;
|
||||
public float MaxAngle = 90f;
|
||||
public float GrabbedDamper = 3f;
|
||||
public float Damper = 10f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1b17ef000f068b468782f079bd24ba6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
97
Assets/HurricaneVR/Framework/Scripts/Components/HVRButton.cs
Normal file
97
Assets/HurricaneVR/Framework/Scripts/Components/HVRButton.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic button check for travel along a defined axis, requires the user to have setup their own constraint system.
|
||||
/// Superceded by the new HVRPhysicsButton component which helps create joints and limits for you
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRButton : MonoBehaviour
|
||||
{
|
||||
public VRButtonEvent ButtonDown = new VRButtonEvent();
|
||||
public VRButtonEvent ButtonUp = new VRButtonEvent();
|
||||
|
||||
|
||||
public Vector3 Axis;
|
||||
|
||||
[Tooltip("How far the button must travel to become pressed.")]
|
||||
public float Threshold;
|
||||
[Tooltip("Threshold to hit on the return to allow the button to be pressed again.")]
|
||||
public float UpThreshold;
|
||||
[Tooltip("The resting position of the button")]
|
||||
public Vector3 StartPosition;
|
||||
public bool IsPressed = false;
|
||||
|
||||
public AudioClip AudioButtonDown;
|
||||
public AudioClip AudioButtonUp;
|
||||
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
//for older projects that wouldn't have set this in the editor
|
||||
if(StartPosition == Vector3.zero)
|
||||
{
|
||||
StartPosition = transform.localPosition;
|
||||
}
|
||||
|
||||
Rigidbody = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
var distance = (StartPosition - transform.localPosition).magnitude;
|
||||
|
||||
if (!IsPressed && distance >= Threshold)
|
||||
{
|
||||
IsPressed = true;
|
||||
OnButtonDown();
|
||||
}
|
||||
else if (IsPressed && distance < UpThreshold)
|
||||
{
|
||||
IsPressed = false;
|
||||
OnButtonUp();
|
||||
}
|
||||
|
||||
ClampBounds();
|
||||
}
|
||||
|
||||
private void ClampBounds()
|
||||
{
|
||||
var test = new Vector3(transform.localPosition.x * Axis.x, transform.localPosition.y * Axis.y, transform.localPosition.z * Axis.z);
|
||||
|
||||
if (test.x > StartPosition.x || test.y > StartPosition.y || test.z > StartPosition.z)
|
||||
{
|
||||
transform.localPosition = StartPosition;
|
||||
Rigidbody.velocity = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
ClampBounds();
|
||||
}
|
||||
|
||||
protected virtual void OnButtonDown()
|
||||
{
|
||||
if (AudioButtonDown)
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(AudioButtonDown, transform.position);
|
||||
|
||||
ButtonDown.Invoke(this);
|
||||
}
|
||||
|
||||
protected virtual void OnButtonUp()
|
||||
{
|
||||
if (AudioButtonUp)
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(AudioButtonUp, transform.position);
|
||||
ButtonUp.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class VRButtonEvent : UnityEvent<HVRButton> { }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73f686e3f59dc0541a3a83773538b43f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Tags a grabbable object as climbable which is then used by the player controller to know if they can climb or not.
|
||||
/// For the hexabody integration it will kick in the climbing strength override set on the HexaHands component.
|
||||
/// </summary>
|
||||
public class HVRClimbable : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ff48744587821344b5cc14739c2d16c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper component used to propogate a collision if a force or velocity threshold was met.
|
||||
/// </summary>
|
||||
public class HVRCollisionEvents : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
|
||||
public CollisionEventType CollisionType = CollisionEventType.Impulse;
|
||||
|
||||
[Tooltip("Force threshold to breach to fire the ThresholdMet event")]
|
||||
public float ForceThreshold;
|
||||
|
||||
[Tooltip("Collision velocity threshold to breach to fire the ThresholdMetEvent")]
|
||||
public float VelocityThreshold;
|
||||
|
||||
public UnityEvent ThresholdMet = new UnityEvent();
|
||||
|
||||
[Header("Debug")]
|
||||
public float LastImpulse;
|
||||
public float LastVelocity;
|
||||
|
||||
public float MaxImpulse;
|
||||
public float MaxVelocity;
|
||||
|
||||
protected virtual void OnCollisionEnter(Collision other)
|
||||
{
|
||||
LastImpulse = other.impulse.magnitude;
|
||||
LastVelocity = other.relativeVelocity.magnitude;
|
||||
|
||||
MaxImpulse = Mathf.Max(MaxImpulse, LastImpulse);
|
||||
MaxVelocity = Mathf.Max(MaxVelocity, LastVelocity);
|
||||
|
||||
var forceMet = LastImpulse > ForceThreshold;
|
||||
var velocityMet = LastVelocity > VelocityThreshold;
|
||||
|
||||
|
||||
if (CollisionType == CollisionEventType.Impulse && forceMet ||
|
||||
CollisionType == CollisionEventType.Velocity && velocityMet ||
|
||||
CollisionType == CollisionEventType.ImpulseOrVelocity && (forceMet || velocityMet))
|
||||
{
|
||||
ThresholdMet.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public enum CollisionEventType
|
||||
{
|
||||
Impulse, Velocity, ImpulseOrVelocity
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 123d9563fca44af1864835effb36ffbc
|
||||
timeCreated: 1600399646
|
||||
@@ -0,0 +1,184 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.ControllerInput;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles offsettings the physics hand target based on the connected device. Also offsets the target based on grab point settings if desired.
|
||||
/// To manage custom offsets please use the SetMiscPositionOffset(Vector3 position, Vector3 rotation) and ResetGrabPointOffsets() functions.
|
||||
/// </summary>
|
||||
public class HVRControllerOffset : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The hand that this controller offset represents.
|
||||
/// </summary>
|
||||
public HVRHandSide HandSide;
|
||||
|
||||
/// <summary>
|
||||
/// The transform that aim's the teleport line, it will be counter rotated when a grabbable requests the hand to rotate when held.
|
||||
/// </summary>
|
||||
[Tooltip("The transform that aim's the teleport line, it will be counter rotated when a grabbable requests the hand to rotate when held.")]
|
||||
public Transform Teleport;
|
||||
|
||||
/// <summary>
|
||||
/// Smooth lerp speed to move towards the target grab point rotation offset
|
||||
/// </summary>
|
||||
[Tooltip("Smooth lerp speed to move towards the target grab point rotation offset")]
|
||||
public float GrabPointSmoothSpeed = 8f;
|
||||
|
||||
private HVRDevicePoseOffset _offsets;
|
||||
|
||||
public Vector3 ControllerPositionOffset => _offsets != null ? _offsets.Position : Vector3.zero;
|
||||
public Vector3 ControllerRotationOffset => _offsets != null ? _offsets.Rotation : Vector3.zero;
|
||||
|
||||
[Header("Debugging")]
|
||||
|
||||
[Tooltip("Enable to test live updating of the Misc offset fields.")]
|
||||
public bool LiveUpdateOffsets;
|
||||
|
||||
[SerializeField] private Vector3 TargetGrabPointPositionOffset;
|
||||
[SerializeField] private Vector3 TargetGrabPointRotationOffset;
|
||||
|
||||
[SerializeField] private Vector3 GrabPointPositionOffset;
|
||||
[SerializeField] private Vector3 GrabPointRotationOffset;
|
||||
|
||||
[SerializeField] private Vector3 MiscPositionOffset;
|
||||
[SerializeField] private Vector3 MiscRotationOffset;
|
||||
|
||||
|
||||
private Quaternion _teleportStartRotation;
|
||||
|
||||
public bool _updatingRotation;
|
||||
public bool _updatingPosition;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (Teleport)
|
||||
{
|
||||
_teleportStartRotation = Teleport.localRotation;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (HandSide == HVRHandSide.Left)
|
||||
{
|
||||
if (HVRInputManager.Instance.LeftController)
|
||||
ControllerConnected(HVRInputManager.Instance.LeftController);
|
||||
HVRInputManager.Instance.LeftControllerConnected.AddListener(ControllerConnected);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HVRInputManager.Instance.RightController)
|
||||
ControllerConnected(HVRInputManager.Instance.RightController);
|
||||
HVRInputManager.Instance.RightControllerConnected.AddListener(ControllerConnected);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_updatingRotation)
|
||||
{
|
||||
GrabPointRotationOffset = Vector3.Lerp(GrabPointRotationOffset, TargetGrabPointRotationOffset, GrabPointSmoothSpeed * Time.deltaTime);
|
||||
if (Vector3.Distance(GrabPointRotationOffset, TargetGrabPointRotationOffset) < .01f)
|
||||
{
|
||||
_updatingRotation = false;
|
||||
GrabPointRotationOffset = TargetGrabPointRotationOffset;
|
||||
ApplyOffsets();
|
||||
}
|
||||
}
|
||||
|
||||
if (_updatingPosition)
|
||||
{
|
||||
GrabPointPositionOffset = Vector3.Lerp(GrabPointPositionOffset, TargetGrabPointPositionOffset, GrabPointSmoothSpeed * Time.deltaTime);
|
||||
if (Vector3.Distance(GrabPointPositionOffset, TargetGrabPointPositionOffset) < .01f)
|
||||
{
|
||||
_updatingPosition = false;
|
||||
GrabPointPositionOffset = TargetGrabPointPositionOffset;
|
||||
ApplyOffsets();
|
||||
}
|
||||
}
|
||||
|
||||
if (LiveUpdateOffsets || _updatingPosition || _updatingRotation)
|
||||
{
|
||||
ApplyOffsets();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMiscPositionOffset(Vector3 position, Vector3 rotation)
|
||||
{
|
||||
MiscPositionOffset = position;
|
||||
MiscRotationOffset = rotation;
|
||||
ApplyOffsets();
|
||||
}
|
||||
|
||||
|
||||
public void SetGrabPointOffsets(Vector3 position, Vector3 rotation)
|
||||
{
|
||||
TargetGrabPointPositionOffset = position;
|
||||
TargetGrabPointRotationOffset = rotation;
|
||||
_updatingRotation = true;
|
||||
_updatingPosition = true;
|
||||
}
|
||||
|
||||
public void ResetGrabPointOffsets()
|
||||
{
|
||||
TargetGrabPointPositionOffset = Vector3.zero;
|
||||
TargetGrabPointRotationOffset = Vector3.zero;
|
||||
_updatingRotation = true;
|
||||
_updatingPosition = true;
|
||||
}
|
||||
|
||||
public void ApplyOffsets()
|
||||
{
|
||||
var position = ControllerPositionOffset + GrabPointPositionOffset + MiscPositionOffset;
|
||||
|
||||
if (HandSide == HVRHandSide.Left)
|
||||
{
|
||||
position.x *= -1f;
|
||||
}
|
||||
|
||||
transform.localPosition = position;
|
||||
|
||||
var controllerRotation = Quaternion.Euler(ControllerRotationOffset);
|
||||
var grabPointRotation = Quaternion.Euler(GrabPointRotationOffset);
|
||||
var miscRotation = Quaternion.Euler(MiscRotationOffset);
|
||||
|
||||
var finalRotation = controllerRotation * grabPointRotation * miscRotation;
|
||||
var angles = finalRotation.eulerAngles;
|
||||
|
||||
if (HandSide == HVRHandSide.Left)
|
||||
{
|
||||
angles.y *= -1f;
|
||||
angles.z *= -1f;
|
||||
}
|
||||
|
||||
if (Teleport)
|
||||
{
|
||||
Teleport.localRotation = _teleportStartRotation * Quaternion.Inverse(grabPointRotation);
|
||||
}
|
||||
|
||||
transform.localEulerAngles = angles;
|
||||
}
|
||||
|
||||
private void ControllerConnected(HVRController controller)
|
||||
{
|
||||
var offsets = HVRInputManager.Instance.ControllerOffsets;
|
||||
if (!offsets)
|
||||
{
|
||||
Debug.LogWarning($"HVRInputManager.ControllerOffsets are not assigned.");
|
||||
return;
|
||||
}
|
||||
|
||||
_offsets = offsets.GetDeviceOffset(controller.Side);
|
||||
|
||||
ApplyOffsets();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59ef9bc5899042d588a09adb8a254aa9
|
||||
timeCreated: 1601145324
|
||||
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using HurricaneVR.Framework.ControllerInput;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores Unity SDK and Device offset combinations to handle the differences between SDK's and the position and rotation values they report.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "HurricaneVR/Controller Offsets", fileName = "ControllerOffset")]
|
||||
public class HVRControllerOffsets : ScriptableObject
|
||||
{
|
||||
[Header("Unity XR")]
|
||||
public HVRDevicePoseOffset Oculus;
|
||||
|
||||
public HVRDevicePoseOffset WMR;
|
||||
public HVRDevicePoseOffset Pico;
|
||||
|
||||
[Header("SteamVR")]
|
||||
public HVRDevicePoseOffset OculusSteamVR;
|
||||
|
||||
public HVRDevicePoseOffset WMRSteamVR;
|
||||
public HVRDevicePoseOffset ReverbG2SteamVR;
|
||||
public HVRDevicePoseOffset CosmosSteamVR;
|
||||
public HVRDevicePoseOffset ViveSteamVR;
|
||||
public HVRDevicePoseOffset KnucklesSteamVR;
|
||||
|
||||
[Header("OpenXR")]
|
||||
public HVRDevicePoseOffset OculusOpenXR;
|
||||
|
||||
public HVRDevicePoseOffset WMROpenXR;
|
||||
public HVRDevicePoseOffset ReverbG2OpenXR;
|
||||
public HVRDevicePoseOffset ViveOpenXR;
|
||||
public HVRDevicePoseOffset CosmosOpenXR;
|
||||
public HVRDevicePoseOffset KnucklesOpenXR;
|
||||
public HVRDevicePoseOffset PicoOpenXR;
|
||||
|
||||
public HVRDevicePoseOffset GetDeviceOffset(HVRHandSide side)
|
||||
{
|
||||
if (side == HVRHandSide.Left)
|
||||
return GetDeviceOffset(HVRInputManager.Instance.LeftController.ControllerType);
|
||||
return GetDeviceOffset(HVRInputManager.Instance.RightController.ControllerType);
|
||||
}
|
||||
|
||||
public HVRDevicePoseOffset GetDeviceOffset(HVRControllerType type)
|
||||
{
|
||||
var steamVR = HVRInputManager.Instance.IsSteamVR;
|
||||
var openXr = HVRInputManager.Instance.IsOpenXR;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case HVRControllerType.Oculus:
|
||||
if (steamVR)
|
||||
{
|
||||
return OculusSteamVR;
|
||||
}
|
||||
else if (openXr)
|
||||
{
|
||||
return OculusOpenXR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Oculus;
|
||||
}
|
||||
case HVRControllerType.WMR:
|
||||
if (steamVR)
|
||||
{
|
||||
return WMRSteamVR;
|
||||
}
|
||||
else if (openXr)
|
||||
{
|
||||
return WMROpenXR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return WMR;
|
||||
}
|
||||
case HVRControllerType.Vive:
|
||||
if (steamVR)
|
||||
{
|
||||
return ViveSteamVR;
|
||||
}
|
||||
else if (openXr)
|
||||
{
|
||||
return ViveOpenXR;
|
||||
}
|
||||
|
||||
break;
|
||||
case HVRControllerType.Knuckles:
|
||||
if (steamVR)
|
||||
{
|
||||
return KnucklesSteamVR;
|
||||
}
|
||||
else if (openXr)
|
||||
{
|
||||
return KnucklesOpenXR;
|
||||
}
|
||||
|
||||
break;
|
||||
case HVRControllerType.Cosmos:
|
||||
if (steamVR)
|
||||
{
|
||||
return CosmosSteamVR;
|
||||
}
|
||||
else if (openXr)
|
||||
{
|
||||
return CosmosOpenXR;
|
||||
}
|
||||
|
||||
break;
|
||||
case HVRControllerType.ReverbG2:
|
||||
if (steamVR)
|
||||
{
|
||||
return ReverbG2SteamVR;
|
||||
}
|
||||
else if (openXr)
|
||||
{
|
||||
return ReverbG2OpenXR;
|
||||
}
|
||||
|
||||
break;
|
||||
case HVRControllerType.Pico:
|
||||
if (steamVR) //is there a way to detect pico when using steamvr? it's emulated as a oculus device
|
||||
return null;
|
||||
if (openXr)
|
||||
return PicoOpenXR;
|
||||
return Pico;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class HVRDevicePoseOffset
|
||||
{
|
||||
public Vector3 Position;
|
||||
|
||||
[FormerlySerializedAs("_rotation")]
|
||||
[SerializeField]
|
||||
public Vector3 Rotation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab72751261f74e5ebaa6986a0464cd15
|
||||
timeCreated: 1635035319
|
||||
@@ -0,0 +1,50 @@
|
||||
using HurricaneVR.Framework.Weapons;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public class HVRDamageHandler : HVRDamageHandlerBase
|
||||
{
|
||||
public float Life = 100f;
|
||||
|
||||
public bool Damageable = true;
|
||||
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
public HVRDestructible Desctructible;
|
||||
|
||||
void Start()
|
||||
{
|
||||
Rigidbody = GetComponent<Rigidbody>();
|
||||
if (!Desctructible)
|
||||
Desctructible = GetComponent<HVRDestructible>();
|
||||
}
|
||||
|
||||
public override void TakeDamage(float damage)
|
||||
{
|
||||
if (Damageable)
|
||||
{
|
||||
Life -= damage;
|
||||
}
|
||||
|
||||
if (Life <= 0)
|
||||
{
|
||||
if (Desctructible)
|
||||
{
|
||||
Desctructible.Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void HandleDamageProvider(HVRDamageProvider damageProvider, Vector3 hitPoint, Vector3 direction)
|
||||
{
|
||||
base.HandleDamageProvider(damageProvider, hitPoint, direction);
|
||||
|
||||
if (Rigidbody)
|
||||
{
|
||||
Rigidbody.AddForceAtPosition(direction.normalized * damageProvider.Force, hitPoint, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2fba50691c4c804ea3f345eb904cc95
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public abstract class HVRDamageHandlerBase : MonoBehaviour
|
||||
{
|
||||
public virtual void TakeDamage(float damage)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void HandleDamageProvider(HVRDamageProvider damageProvider, Vector3 hitPoint, Vector3 direction)
|
||||
{
|
||||
TakeDamage(damageProvider.Damage);
|
||||
}
|
||||
|
||||
public virtual void HandleRayCastHit(HVRDamageProvider damageProvider, RaycastHit hit)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e49c8bf2db256ba438a090d0d46c85ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public class HVRDamageProvider : MonoBehaviour
|
||||
{
|
||||
public float Damage = 25f;
|
||||
public float Force;
|
||||
|
||||
[Tooltip("Player transform for ai frameworks like emerald ai")]
|
||||
public Transform Player;
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 029f5fabd456e3d4ca818afd570d575d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Publishes the destroyed event so others may know, used by the hand grabber to know if the held object is destroyed
|
||||
/// </summary>
|
||||
public class HVRDestroyListener : MonoBehaviour
|
||||
{
|
||||
public HVRDestroyedEvent Destroyed = new HVRDestroyedEvent();
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Destroyed.Invoke(this);
|
||||
Destroyed.RemoveAllListeners();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class HVRDestroyedEvent : UnityEvent<HVRDestroyListener>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d73b26c803e4bbb886b5776121804b2
|
||||
timeCreated: 1600231143
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Destroys this game object after a timeout
|
||||
/// </summary>
|
||||
public class HVRDestroyTimer : MonoBehaviour
|
||||
{
|
||||
public void StartTimer(float timeout)
|
||||
{
|
||||
StartCoroutine(Cleanup(timeout));
|
||||
}
|
||||
|
||||
private IEnumerator Cleanup(float timeout)
|
||||
{
|
||||
yield return new WaitForSeconds(timeout);
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6751180565d247fba4285903a5b605aa
|
||||
timeCreated: 1601087539
|
||||
@@ -0,0 +1,75 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper component that spawns a prefab game object when the Destroy function is called.
|
||||
/// If the spawned game object has a rigidbodies then they will have force added to them based on the
|
||||
/// fields provided.
|
||||
/// </summary>
|
||||
public class HVRDestructible : MonoBehaviour
|
||||
{
|
||||
public GameObject DestroyedVersion;
|
||||
|
||||
public float ExplosionRadius = .1f;
|
||||
public float ExplosionPower = 1;
|
||||
public float ExplosionUpwardsPower = 1;
|
||||
|
||||
public bool RemoveDebris = true;
|
||||
public float RemoveDebrisTimerUpper = 10f;
|
||||
public float RemoveDebrisTimerLower = 5f;
|
||||
|
||||
public bool IgnorePlayerCollision = true;
|
||||
|
||||
public bool Destroyed { get; protected set; }
|
||||
|
||||
public virtual void Destroy()
|
||||
{
|
||||
if (Destroyed) return;
|
||||
|
||||
if (DestroyedVersion)
|
||||
{
|
||||
var destroyed = Instantiate(DestroyedVersion, transform.position, transform.rotation);
|
||||
|
||||
foreach (var rigidBody in destroyed.GetComponentsInChildren<Rigidbody>())
|
||||
{
|
||||
var v = new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f));
|
||||
rigidBody.AddForce(v * ExplosionPower, ForceMode.VelocityChange);
|
||||
|
||||
if (RemoveDebris)
|
||||
{
|
||||
var delay = Random.Range(RemoveDebrisTimerLower, RemoveDebrisTimerUpper);
|
||||
if (delay < .1f)
|
||||
{
|
||||
delay = 3f;
|
||||
}
|
||||
|
||||
var timer = rigidBody.gameObject.AddComponent<HVRDestroyTimer>();
|
||||
timer.StartTimer(delay);
|
||||
}
|
||||
|
||||
if (IgnorePlayerCollision)
|
||||
{
|
||||
var colliders = rigidBody.gameObject.GetComponentsInChildren<Collider>();
|
||||
HVRManager.Instance?.IgnorePlayerCollision(colliders);
|
||||
}
|
||||
|
||||
rigidBody.transform.parent = null;
|
||||
}
|
||||
|
||||
if (RemoveDebris)
|
||||
{
|
||||
var timer = destroyed.gameObject.AddComponent<HVRDestroyTimer>();
|
||||
var delay = RemoveDebrisTimerUpper;
|
||||
if (delay <= .1f)
|
||||
delay = 3f;
|
||||
timer.StartTimer(delay);
|
||||
}
|
||||
}
|
||||
|
||||
Destroyed = true;
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66f0a0ab295247a681b1b569944a2bf9
|
||||
timeCreated: 1599957568
|
||||
244
Assets/HurricaneVR/Framework/Scripts/Components/HVRDial.cs
Normal file
244
Assets/HurricaneVR/Framework/Scripts/Components/HVRDial.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Deprecated and left in for older projects. Superceded by HVRPhysicsDial and HVRRotationTracker
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(HVRGrabbable))]
|
||||
public class HVRDial : MonoBehaviour
|
||||
{
|
||||
public DialSteppedEvent DialStepChanged = new DialSteppedEvent();
|
||||
public DialTurnedEvent DialTurned = new DialTurnedEvent();
|
||||
|
||||
public Transform RotationTarget;
|
||||
public int Steps;
|
||||
public bool SnapTarget = true;
|
||||
public bool ClampMaxAngle;
|
||||
public float MaximumAngle = 360f;
|
||||
public AudioClip AudioClip;
|
||||
public float Deadzone = 1f;
|
||||
public Vector3 LocalRotationAxis;
|
||||
public Vector3 LocalAxisStart;
|
||||
public bool DiscardAngle;
|
||||
|
||||
public float StepSize;
|
||||
|
||||
private float _previousAngle;
|
||||
private Vector3 _originalVector;
|
||||
private Rigidbody _rigidBody;
|
||||
private Rigidbody _targetRigidBody;
|
||||
private float _previousAngleFromStart;
|
||||
|
||||
public int Step { get; protected set; }
|
||||
|
||||
public HVRGrabbable Grabbable { get; private set; }
|
||||
public HVRHandGrabber PrimaryGrabber { get; private set; }
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
_rigidBody = transform.GetComponent<Rigidbody>();
|
||||
_targetRigidBody = RotationTarget.GetComponent<Rigidbody>();
|
||||
|
||||
if (Steps <= 1)
|
||||
StepSize = 0f;
|
||||
else if (Steps > 1 && Mathf.Approximately(StepSize, 0f))
|
||||
StepSize = MaximumAngle / Steps;
|
||||
|
||||
LocalAxisStart.Normalize();
|
||||
LocalRotationAxis.Normalize();
|
||||
|
||||
_originalVector = transform.localRotation * LocalAxisStart;
|
||||
|
||||
Grabbable = GetComponent<HVRGrabbable>();
|
||||
Grabbable.Grabbed.AddListener(OnGrabbed);
|
||||
Grabbable.Released.AddListener(OnReleased);
|
||||
|
||||
|
||||
_previousAngle = 0f;
|
||||
_previousAngleFromStart = 0f;
|
||||
}
|
||||
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
//Debug.DrawLine(transform.position, transform.position + transform.TransformDirection(currentVector).normalized * 1f, Color.red);
|
||||
CheckForRotation();
|
||||
}
|
||||
|
||||
|
||||
protected void CheckForRotation(bool force = false)
|
||||
{
|
||||
if (force || PrimaryGrabber)
|
||||
{
|
||||
if (!force && Mathf.Abs(PrimaryGrabber.HVRTrackedController.DeltaEulerZ) < Deadzone)
|
||||
return;
|
||||
|
||||
var currentVector = transform.localRotation * LocalAxisStart;
|
||||
var rotationAxis = LocalRotationAxis;
|
||||
|
||||
var controllerRotation = new Vector3(
|
||||
PrimaryGrabber.HVRTrackedController.DeltaEulerZ,
|
||||
PrimaryGrabber.HVRTrackedController.DeltaEulerZ,
|
||||
PrimaryGrabber.HVRTrackedController.DeltaEulerZ);
|
||||
|
||||
controllerRotation.Scale(-rotationAxis);
|
||||
|
||||
var rotation = Quaternion.Euler(controllerRotation);
|
||||
|
||||
var newRotation = transform.localRotation * rotation;
|
||||
|
||||
var newVector = newRotation * LocalAxisStart;
|
||||
|
||||
var delta = -PrimaryGrabber.HVRTrackedController.DeltaEulerZ;
|
||||
|
||||
var angleFromStart = Vector3.SignedAngle(_originalVector, newVector, rotationAxis);
|
||||
|
||||
if (angleFromStart < 0)
|
||||
angleFromStart = 360 + angleFromStart;
|
||||
|
||||
var clockWise = delta >= 0f;
|
||||
|
||||
if (ClampMaxAngle)
|
||||
{
|
||||
|
||||
if (clockWise && _previousAngleFromStart + delta >= MaximumAngle - .1)
|
||||
{
|
||||
angleFromStart = MaximumAngle;
|
||||
}
|
||||
else if (!clockWise && _previousAngleFromStart + delta <= 0.1)
|
||||
{
|
||||
angleFromStart = 0;
|
||||
}
|
||||
else if (angleFromStart > MaximumAngle)
|
||||
{
|
||||
float upDiff = 360 - angleFromStart;
|
||||
float lowerDiff = angleFromStart - MaximumAngle;
|
||||
|
||||
if (upDiff < lowerDiff) angleFromStart = 0;
|
||||
else angleFromStart = MaximumAngle;
|
||||
}
|
||||
}
|
||||
|
||||
var stepAngle = angleFromStart;
|
||||
if (Steps > 1)
|
||||
{
|
||||
Step = Mathf.RoundToInt(angleFromStart / StepSize);
|
||||
stepAngle = Step * StepSize;
|
||||
if (Mathf.Approximately(stepAngle, 360))
|
||||
{
|
||||
Step = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var finalVector = Quaternion.AngleAxis(angleFromStart, rotationAxis) * _originalVector;
|
||||
var syncAngle = Vector3.SignedAngle(currentVector, finalVector, rotationAxis);
|
||||
var syncRotation = Quaternion.AngleAxis(syncAngle, rotationAxis) * transform.localRotation;
|
||||
|
||||
if (Steps > 1)
|
||||
{
|
||||
if (!Mathf.Approximately(stepAngle, _previousAngle))
|
||||
{
|
||||
OnStepChanged(Step, true);
|
||||
_previousAngle = stepAngle;
|
||||
|
||||
if (SnapTarget)
|
||||
{
|
||||
var percent = Mathf.Approximately(0f, MaximumAngle) ? 0f : stepAngle / MaximumAngle;
|
||||
OnAngleChanged(stepAngle, syncAngle, percent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!SnapTarget && !Mathf.Approximately(_previousAngleFromStart, angleFromStart))
|
||||
{
|
||||
var percent = Mathf.Approximately(0f, MaximumAngle) ? 0f : angleFromStart / MaximumAngle;
|
||||
OnAngleChanged(angleFromStart, syncAngle, angleFromStart / percent, true);
|
||||
}
|
||||
|
||||
var steppedVector = Quaternion.AngleAxis(stepAngle, rotationAxis) * _originalVector;
|
||||
var steppedAngle = Vector3.SignedAngle(currentVector, steppedVector, rotationAxis);
|
||||
var steppedRotation = Quaternion.AngleAxis(steppedAngle, rotationAxis) * transform.localRotation;
|
||||
|
||||
var targetRotation = SnapTarget ? steppedRotation : syncRotation;
|
||||
|
||||
//if (_targetRigidBody)
|
||||
//{
|
||||
// _targetRigidBody.MoveRotation(_targetRigidBody.rotation * targetRotation);
|
||||
//}
|
||||
//else
|
||||
{
|
||||
RotationTarget.localRotation = targetRotation;
|
||||
}
|
||||
|
||||
//if (_rigidBody)
|
||||
//{
|
||||
// _rigidBody.MoveRotation(_rigidBody.rotation * syncRotation);
|
||||
//}
|
||||
//else
|
||||
{
|
||||
transform.localRotation = syncRotation;
|
||||
}
|
||||
|
||||
_previousAngleFromStart = angleFromStart;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void OnGrabbed(HVRGrabberBase grabber, HVRGrabbable hvrGrabbable)
|
||||
{
|
||||
PrimaryGrabber = grabber as HVRHandGrabber;
|
||||
|
||||
if (DiscardAngle)
|
||||
{
|
||||
if (_rigidBody)
|
||||
{
|
||||
_rigidBody.MoveRotation(RotationTarget.rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.localRotation = RotationTarget.localRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnReleased(HVRGrabberBase grabber, HVRGrabbable hvrGrabbable)
|
||||
{
|
||||
PrimaryGrabber = null;
|
||||
|
||||
if (DiscardAngle)
|
||||
{
|
||||
if (_rigidBody)
|
||||
{
|
||||
_rigidBody.MoveRotation(RotationTarget.rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.localRotation = RotationTarget.localRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnStepChanged(int step, bool raiseEvents)
|
||||
{
|
||||
if (AudioClip)
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFXRandomPitch(AudioClip, transform.position, .9f, 1.1f);
|
||||
if (raiseEvents)
|
||||
DialStepChanged.Invoke(step);
|
||||
}
|
||||
|
||||
protected virtual void OnAngleChanged(float angle, float delta, float percent, bool raiseEvents)
|
||||
{
|
||||
if (raiseEvents)
|
||||
DialTurned.Invoke(angle, delta, percent);
|
||||
}
|
||||
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a95f97577cc01a746a9d0a3e11b90b8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public class HVRDontDestroy : MonoBehaviour
|
||||
{
|
||||
private void Awake()
|
||||
{
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e5b279a1a044cee9d64e0ca5d85f175
|
||||
timeCreated: 1601039791
|
||||
@@ -0,0 +1,34 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public abstract class HVRGrabbableHoverBase : MonoBehaviour
|
||||
{
|
||||
public HVRHoverPosition HoverPosition = HVRHoverPosition.GrabPoint;
|
||||
public bool LookAtCamera = true;
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public abstract void Hover();
|
||||
|
||||
public abstract void Unhover();
|
||||
|
||||
public abstract void Enable();
|
||||
public abstract void Disable();
|
||||
}
|
||||
|
||||
public enum HVRHoverPosition
|
||||
{
|
||||
GrabPoint,
|
||||
Self,
|
||||
Transform
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c25cecd1cd34cd7a4346c955a0add93
|
||||
timeCreated: 1600204770
|
||||
@@ -0,0 +1,28 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
|
||||
public class HVRGrabbableImpactHaptics : HVRImpactHapticsBase
|
||||
{
|
||||
public HVRGrabbable Grabbable;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
if (!Grabbable) TryGetComponent(out Grabbable);
|
||||
}
|
||||
|
||||
protected override void Vibrate(float duration, float amplitude, float frequency)
|
||||
{
|
||||
for (var i = 0; i < Grabbable.HandGrabbers.Count; i++)
|
||||
{
|
||||
var h = Grabbable.HandGrabbers[i];
|
||||
if (!h.IsMine) break;
|
||||
|
||||
h.Controller.Vibrate(amplitude, Data.Duration, Data.Frequency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77dbe74f0338a6c438b0af580dd1253e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Core.Player;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public class HVRHandImpactHaptics : HVRImpactHapticsBase
|
||||
{
|
||||
public HVRHandGrabber Hand;
|
||||
|
||||
[Tooltip("If true and the hand is holding something, haptics will not play.")]
|
||||
public bool HandGrabbingPrevents = true;
|
||||
|
||||
[Tooltip("If true the max force for the haptic amplitude calc will use the hand's default max force.")]
|
||||
public bool UseHandMaxStrength = true;
|
||||
|
||||
private HVRJointHand _hand;
|
||||
|
||||
public override float MaxForce
|
||||
{
|
||||
get
|
||||
{
|
||||
if (UseHandMaxStrength)
|
||||
{
|
||||
if ( _hand && _hand.JointSettings)
|
||||
return _hand.JointSettings.XDrive.MaxForce;
|
||||
}
|
||||
|
||||
return base.MaxForce;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
if (!Hand) TryGetComponent(out Hand);
|
||||
|
||||
TryGetComponent(out _hand);
|
||||
}
|
||||
|
||||
protected override void Vibrate(float duration, float amplitude, float frequency)
|
||||
{
|
||||
if (HandGrabbingPrevents && Hand.IsGrabbing) return;
|
||||
Hand.Controller.Vibrate(amplitude, duration, frequency);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 735256ec9b08e024a8efea6924dd44b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.HandPoser;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public class HVRHandPoseRecorder : MonoBehaviour
|
||||
{
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
public KeyCode LeftHandSaveKey = KeyCode.L;
|
||||
public KeyCode RightHandSaveKey = KeyCode.R;
|
||||
#endif
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
|
||||
public Key LeftSaveKey = Key.L;
|
||||
public Key RightSaveKey = Key.R;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
public HVRPosableHand LeftHand;
|
||||
public HVRPosableHand RightHand;
|
||||
|
||||
public HVRHandPhysics LeftPhysics;
|
||||
public HVRHandPhysics RightPhysics;
|
||||
|
||||
public float FadeTimer = 10f;
|
||||
public bool RemoveClones = true;
|
||||
|
||||
public bool DisablePhysics;
|
||||
|
||||
private bool _previousDisable;
|
||||
|
||||
public string Folder;
|
||||
public int Counter = 0;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Folder = DateTime.Now.ToString("yyyyMMdd_HH_mm");
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
void Update()
|
||||
{
|
||||
|
||||
|
||||
if (DisablePhysics && !_previousDisable)
|
||||
{
|
||||
if (LeftPhysics)
|
||||
{
|
||||
LeftPhysics.DisableCollision();
|
||||
}
|
||||
|
||||
if (RightPhysics)
|
||||
{
|
||||
RightPhysics.DisableCollision();
|
||||
}
|
||||
}
|
||||
else if (!DisablePhysics && _previousDisable)
|
||||
{
|
||||
if (LeftPhysics)
|
||||
{
|
||||
LeftPhysics.EnableCollision();
|
||||
}
|
||||
|
||||
if (RightPhysics)
|
||||
{
|
||||
RightPhysics.EnableCollision();
|
||||
}
|
||||
}
|
||||
|
||||
_previousDisable = DisablePhysics;
|
||||
|
||||
CheckSnapshot();
|
||||
|
||||
}
|
||||
#endif
|
||||
private void CheckSnapshot()
|
||||
{
|
||||
HVRPosableHand hand = null;
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
if (Input.GetKeyDown(LeftHandSaveKey))
|
||||
{
|
||||
hand = LeftHand;
|
||||
}
|
||||
else if (Input.GetKeyDown(RightHandSaveKey))
|
||||
{
|
||||
hand = RightHand;
|
||||
}
|
||||
else
|
||||
return;
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
|
||||
if (Keyboard.current[LeftSaveKey].wasPressedThisFrame)
|
||||
{
|
||||
hand = LeftHand;
|
||||
}
|
||||
else if (Keyboard.current[RightSaveKey].wasPressedThisFrame)
|
||||
{
|
||||
hand = RightHand;
|
||||
}
|
||||
else
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!hand)
|
||||
return;
|
||||
|
||||
Snapshot(hand);
|
||||
}
|
||||
|
||||
public void SnapshotLeft()
|
||||
{
|
||||
if (!gameObject.activeSelf)
|
||||
return;
|
||||
if (LeftHand)
|
||||
{
|
||||
Snapshot(LeftHand);
|
||||
}
|
||||
}
|
||||
|
||||
public void SnapshotRight()
|
||||
{
|
||||
if (!gameObject.activeSelf)
|
||||
return;
|
||||
|
||||
if (RightHand)
|
||||
{
|
||||
Snapshot(RightHand);
|
||||
}
|
||||
}
|
||||
|
||||
private void Snapshot(HVRPosableHand hand)
|
||||
{
|
||||
|
||||
#if UNITY_EDITOR
|
||||
var pose = hand.CreateFullHandPoseWorld(hand.MirrorAxis);
|
||||
|
||||
HVRSettings.Instance.SaveRunTimePose(pose, Counter++.ToString(), Folder);
|
||||
|
||||
var clone = Instantiate(HVRSettings.Instance.GetPoserHand(hand.Side));
|
||||
|
||||
var posableHand = clone.GetComponent<HVRPosableHand>();
|
||||
if (posableHand != null)
|
||||
{
|
||||
posableHand.Pose(pose.GetPose(hand.Side));
|
||||
clone.transform.position = hand.transform.position;
|
||||
clone.transform.rotation = hand.transform.rotation;
|
||||
}
|
||||
|
||||
var colliders = clone.GetComponentsInChildren<Collider>();
|
||||
foreach (var c in colliders)
|
||||
{
|
||||
c.enabled = false;
|
||||
}
|
||||
|
||||
if (RemoveClones)
|
||||
{
|
||||
StartCoroutine(RemoveClone(clone));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public IEnumerator RemoveClone(GameObject clone)
|
||||
{
|
||||
yield return new WaitForSeconds(FadeTimer);
|
||||
Destroy(clone);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60ac0a61a75ecf64e8c54dcb82a08821
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
|
||||
[CreateAssetMenu(menuName = "HurricaneVR/Impact Haptics", fileName = "ImpactHaptics")]
|
||||
public class HVRImpactHaptics : ScriptableObject
|
||||
{
|
||||
public float Timeout = .3f;
|
||||
|
||||
[Tooltip("Collision Velocity Square Magnitude cut off filter")]
|
||||
public float SqrMagThreshold = .30f;
|
||||
|
||||
[Tooltip("Collision force divided by this and fed into the AmpCurve. ")]
|
||||
public float MaxForce = 300f;
|
||||
|
||||
public AnimationCurve AmpCurve;
|
||||
|
||||
[Tooltip("Duration fed into haptics API.")]
|
||||
public float Duration = .25f;
|
||||
|
||||
[Tooltip("Frequency fed into haptics API")]
|
||||
public float Frequency = 150f;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Frequency = 150f;
|
||||
Duration = .25f;
|
||||
MaxForce = 600f;
|
||||
SqrMagThreshold = .30f;
|
||||
Timeout = .3f;
|
||||
|
||||
AmpCurve = new AnimationCurve(new Keyframe(0f, .35f, 0f, 0f, 0f, 0f)
|
||||
{
|
||||
weightedMode = WeightedMode.None
|
||||
}, new Keyframe(1f, 1f, 2f, 2f, 0f, 0f)
|
||||
{
|
||||
weightedMode = WeightedMode.None
|
||||
});
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
//unity bugged Reset conext menu on some versions
|
||||
[MenuItem("CONTEXT/ImpactHaptics/Reset (Custom)")]
|
||||
static void CReset(MenuCommand command)
|
||||
{
|
||||
(command.context as HVRImpactHaptics)?.Reset();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b775075551dfdd947bebcfce71c1a7c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public abstract class HVRImpactHapticsBase : MonoBehaviour
|
||||
{
|
||||
public HVRImpactHaptics Data;
|
||||
|
||||
[Header("Debug")]
|
||||
public float Force;
|
||||
|
||||
private float _lastHaptic;
|
||||
private Rigidbody Rb;
|
||||
|
||||
public virtual float MaxForce => Data.MaxForce;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
TryGetComponent(out Rb);
|
||||
|
||||
if (!Data)
|
||||
{
|
||||
Data = ScriptableObject.CreateInstance<HVRImpactHaptics>();
|
||||
Data.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnCollisionEnter(Collision other)
|
||||
{
|
||||
if (!Rb) TryGetComponent(out Rb);
|
||||
|
||||
if (!Rb || Rb.velocity.sqrMagnitude < Data.SqrMagThreshold)
|
||||
return;
|
||||
|
||||
if (Time.realtimeSinceStartup - _lastHaptic < Data.Timeout)
|
||||
return;
|
||||
|
||||
float impulse;
|
||||
|
||||
if (other.impulse.sqrMagnitude > 0f)
|
||||
{
|
||||
impulse = other.impulse.magnitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
impulse = other.relativeVelocity.magnitude * Rb.mass;
|
||||
}
|
||||
|
||||
Force = impulse / Time.fixedDeltaTime;
|
||||
|
||||
var amp = Data.AmpCurve.Evaluate(Force / MaxForce);
|
||||
|
||||
Vibrate(Data.Duration, amp, Data.Frequency);
|
||||
|
||||
_lastHaptic = Time.realtimeSinceStartup;
|
||||
}
|
||||
|
||||
protected virtual void Vibrate(float duration, float amplitude, float frequency)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38a18e75cd9699f428ac9902c039394c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
246
Assets/HurricaneVR/Framework/Scripts/Components/HVRLever.cs
Normal file
246
Assets/HurricaneVR/Framework/Scripts/Components/HVRLever.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Depecrecated and left in for older projects, superceded by HVRPhysicsLever and HVRRotationTracker
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(HVRGrabbable))]
|
||||
[RequireComponent(typeof(HingeJoint))]
|
||||
public class HVRLever : MonoBehaviour
|
||||
{
|
||||
[Header("Transforms")]
|
||||
[Tooltip("Target transform to rotate if the visual handle is not this object")]
|
||||
public Transform RotationTarget;
|
||||
|
||||
[Tooltip("Used to track the delta angle change, use with TrackerAxis.")]
|
||||
public Transform Tracker;
|
||||
|
||||
[Header("Settings")]
|
||||
|
||||
[Tooltip("When the lever is released with Snap mode, should the grabbable handle snap to the RotationTarget")]
|
||||
public bool DiscardAngle;
|
||||
|
||||
[Tooltip("Amount of steps the lever will click")]
|
||||
public int Steps;
|
||||
|
||||
[Tooltip("Rotation Target snaps to the step angle size")]
|
||||
public bool SnapTarget = true;
|
||||
|
||||
[Tooltip("Angle offset the lever starts in relation to LocalAxisStart field")]
|
||||
public float Offset;
|
||||
|
||||
[Tooltip("Vector of the starting 0 angle of the lever.")]
|
||||
public Vector3 LocalAxisStart;
|
||||
[Tooltip("Choose an axis that isn't the same as the hinge axis")]
|
||||
public Vector3 TrackerAxis = new Vector3(0, 1, 0);
|
||||
|
||||
|
||||
[Tooltip("SFX to play whenever the lever snaps")]
|
||||
public AudioClip AudioClip;
|
||||
|
||||
protected HingeJoint HingeJoint;
|
||||
|
||||
[Header("Debug")]
|
||||
public float MinAngle;
|
||||
public float MaxAngle;
|
||||
public Vector3 LocalRotationAxis;
|
||||
public float StepSize;
|
||||
public int CurrentStep;
|
||||
public float CurrentAngle;
|
||||
|
||||
public LeverMovedEvent Moved = new LeverMovedEvent();
|
||||
public LeverSteppedEvent Stepped = new LeverSteppedEvent();
|
||||
|
||||
private float _previousAngle;
|
||||
private Vector3 _previousVector;
|
||||
private Vector3 _originalVector;
|
||||
private float _previousAngleFromStart;
|
||||
|
||||
public HVRGrabbable Grabbable { get; private set; }
|
||||
public Rigidbody Rigidbody => Grabbable.Rigidbody;
|
||||
public HVRGrabberBase PrimaryGrabber => Grabbable.PrimaryGrabber;
|
||||
|
||||
public float Range { get; set; }
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
if (!RotationTarget)
|
||||
RotationTarget = transform;
|
||||
|
||||
Grabbable = GetComponent<HVRGrabbable>();
|
||||
|
||||
HingeJoint = GetComponent<HingeJoint>();
|
||||
|
||||
MinAngle = HingeJoint.limits.min;
|
||||
MaxAngle = HingeJoint.limits.max;
|
||||
|
||||
Range = MaxAngle - MinAngle;
|
||||
|
||||
LocalRotationAxis = HingeJoint.axis;
|
||||
|
||||
if (Steps <= 1)
|
||||
{
|
||||
StepSize = 0f;
|
||||
}
|
||||
else if (Steps > 1 && Mathf.Approximately(StepSize, 0f))
|
||||
{
|
||||
StepSize = Range / Steps;
|
||||
}
|
||||
|
||||
_originalVector = transform.TransformDirection(LocalAxisStart);
|
||||
|
||||
_previousVector = LocalAxisStart;
|
||||
|
||||
SetupStartRotation();
|
||||
|
||||
transform.rotation = RotationTarget.rotation;
|
||||
|
||||
Grabbable.Grabbed.AddListener(OnGrabbed);
|
||||
Grabbable.Released.AddListener(OnReleased);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
CheckForRotation();
|
||||
}
|
||||
|
||||
private void CheckForRotation(bool force = false)
|
||||
{
|
||||
if (!force && Rigidbody.isKinematic && !PrimaryGrabber)
|
||||
return;
|
||||
|
||||
var currentVector = Tracker.TransformDirection(TrackerAxis);
|
||||
var worldRotationAxis = transform.TransformDirection(LocalRotationAxis);
|
||||
|
||||
var angleFromStart = Vector3.SignedAngle(_originalVector, currentVector, worldRotationAxis);
|
||||
angleFromStart += Offset;
|
||||
if ((int)angleFromStart < 0)
|
||||
angleFromStart = 360 + angleFromStart;
|
||||
|
||||
var deltaAngle = Vector3.SignedAngle(_previousVector, currentVector, worldRotationAxis);
|
||||
|
||||
CurrentAngle = angleFromStart;
|
||||
var stepAngle = angleFromStart;
|
||||
if (Steps > 1)
|
||||
{
|
||||
CurrentStep = Mathf.RoundToInt(angleFromStart / StepSize);
|
||||
stepAngle = CurrentStep * StepSize;
|
||||
|
||||
if (!Mathf.Approximately(stepAngle, _previousAngle))
|
||||
{
|
||||
OnStepChanged(CurrentStep);
|
||||
_previousAngle = stepAngle;
|
||||
|
||||
if (SnapTarget)
|
||||
{
|
||||
var percent = Mathf.Approximately(0f, Range) ? 0f : stepAngle / Range;
|
||||
OnAngleChanged(stepAngle, deltaAngle, percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_previousVector = currentVector;
|
||||
|
||||
var steppedVector = Quaternion.AngleAxis(stepAngle - Offset, worldRotationAxis) * _originalVector;
|
||||
var steppedAngle = Vector3.SignedAngle(currentVector, steppedVector, worldRotationAxis);
|
||||
var steppedRotation = Quaternion.AngleAxis(steppedAngle, worldRotationAxis) * transform.rotation;
|
||||
|
||||
if (!SnapTarget && !Mathf.Approximately(_previousAngleFromStart, angleFromStart))
|
||||
{
|
||||
var percent = Mathf.Approximately(0f, Range) ? 0f : angleFromStart / Range;
|
||||
OnAngleChanged(angleFromStart, deltaAngle, percent);
|
||||
}
|
||||
|
||||
if (SnapTarget)
|
||||
{
|
||||
RotationTarget.rotation = steppedRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
RotationTarget.rotation = transform.rotation;
|
||||
}
|
||||
|
||||
_previousAngleFromStart = angleFromStart;
|
||||
}
|
||||
|
||||
private void SetupStartRotation()
|
||||
{
|
||||
var currentVector = transform.TransformDirection(TrackerAxis);
|
||||
var worldRotationAxis = transform.TransformDirection(LocalRotationAxis);
|
||||
|
||||
var angleFromStart = Vector3.SignedAngle(_originalVector, currentVector, worldRotationAxis);
|
||||
angleFromStart += Offset;
|
||||
if ((int)angleFromStart < 0)
|
||||
angleFromStart = 360 + angleFromStart;
|
||||
|
||||
CurrentAngle = angleFromStart;
|
||||
var stepAngle = angleFromStart;
|
||||
if (Steps > 1)
|
||||
{
|
||||
CurrentStep = Mathf.RoundToInt(angleFromStart / StepSize);
|
||||
stepAngle = CurrentStep * StepSize;
|
||||
|
||||
if (!Mathf.Approximately(stepAngle, _previousAngle))
|
||||
{
|
||||
_previousAngle = stepAngle;
|
||||
}
|
||||
}
|
||||
|
||||
_previousVector = currentVector;
|
||||
|
||||
var steppedVector = Quaternion.AngleAxis(stepAngle - Offset, worldRotationAxis) * _originalVector;
|
||||
var steppedAngle = Vector3.SignedAngle(currentVector, steppedVector, worldRotationAxis);
|
||||
var steppedRotation = Quaternion.AngleAxis(steppedAngle, worldRotationAxis) * transform.rotation;
|
||||
|
||||
if (SnapTarget)
|
||||
{
|
||||
RotationTarget.rotation = steppedRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
RotationTarget.rotation = transform.rotation;
|
||||
}
|
||||
|
||||
_previousAngleFromStart = angleFromStart;
|
||||
}
|
||||
|
||||
protected void OnGrabbed(HVRGrabberBase grabber, HVRGrabbable hvrGrabbable)
|
||||
{
|
||||
if (DiscardAngle)
|
||||
{
|
||||
transform.rotation = RotationTarget.rotation;
|
||||
transform.position = RotationTarget.position;
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnReleased(HVRGrabberBase grabber, HVRGrabbable hvrGrabbable)
|
||||
{
|
||||
if (DiscardAngle)
|
||||
{
|
||||
transform.rotation = RotationTarget.rotation;
|
||||
transform.position = RotationTarget.position;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnStepChanged(int step, bool raiseEvents = true)
|
||||
{
|
||||
if (AudioClip)
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFXRandomPitch(AudioClip, transform.position, .9f, 1.1f);
|
||||
if (raiseEvents)
|
||||
Stepped.Invoke(step);
|
||||
}
|
||||
|
||||
protected virtual void OnAngleChanged(float angle, float delta, float percent, bool raiseEvents = true)
|
||||
{
|
||||
if (raiseEvents)
|
||||
Moved.Invoke(angle, delta, percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e395cf0cf494656baa6b1eddceceb24
|
||||
timeCreated: 1600542387
|
||||
@@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
public class HVRMeshGlowHighlight : HVRGrabbableHoverBase
|
||||
{
|
||||
private readonly HashSet<GameObject> _highlightObjects = new HashSet<GameObject>();
|
||||
private readonly HashSet<MeshRenderer> _renderers = new HashSet<MeshRenderer>();
|
||||
|
||||
void Awake()
|
||||
{
|
||||
var meshes = GetComponentsInChildren<MeshFilter>();
|
||||
|
||||
foreach (var mesh in meshes)
|
||||
{
|
||||
var go = mesh.gameObject;
|
||||
var meshRenderer = go.GetComponent<MeshRenderer>();
|
||||
if (meshRenderer)
|
||||
{
|
||||
_renderers.Add(meshRenderer);
|
||||
}
|
||||
var highlightObj = new GameObject("HighlightMesh");
|
||||
highlightObj.transform.SetParent(go.transform, false);
|
||||
|
||||
var clone = highlightObj.AddComponent<MeshFilter>();
|
||||
clone.sharedMesh = mesh.sharedMesh;
|
||||
var newRenderer = highlightObj.AddComponent<MeshRenderer>();
|
||||
newRenderer.sharedMaterial = Resources.Load<Material>("GrabbableHighlight");
|
||||
|
||||
_highlightObjects.Add(highlightObj);
|
||||
highlightObj.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Hover()
|
||||
{
|
||||
foreach (var highlight in _highlightObjects)
|
||||
{
|
||||
highlight.SetActive(true);
|
||||
}
|
||||
|
||||
foreach (var r in _renderers)
|
||||
{
|
||||
r.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Unhover()
|
||||
{
|
||||
foreach (var highlight in _highlightObjects)
|
||||
{
|
||||
highlight.SetActive(false);
|
||||
}
|
||||
|
||||
foreach (var r in _renderers)
|
||||
{
|
||||
r.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e7c9a97934caec4897562447669e7e7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
[RequireComponent(typeof(MeshRenderer))]
|
||||
public class HVRMeshRendererHighlight : HVRGrabbableHoverBase
|
||||
{
|
||||
public MeshRenderer Renderer { get; private set; }
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
Renderer = GetComponent<MeshRenderer>();
|
||||
|
||||
}
|
||||
|
||||
public override void Hover()
|
||||
{
|
||||
Renderer.enabled = true;
|
||||
}
|
||||
|
||||
public override void Unhover()
|
||||
{
|
||||
Renderer.enabled = false;
|
||||
}
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
Renderer.enabled = true;
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
Renderer.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86ae87a96c3b7dd4c8c15912e79812f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper component to parent this transform to the assigned transform on game start
|
||||
/// </summary>
|
||||
public class HVRParentOnStart : MonoBehaviour
|
||||
{
|
||||
public Transform Parent;
|
||||
public bool WorldPositionStays = true;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (Parent)
|
||||
{
|
||||
transform.SetParent(Parent, WorldPositionStays);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b06dd533ee37487db0603f3b328f972f
|
||||
timeCreated: 1602523768
|
||||
@@ -0,0 +1,197 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Core.ScriptableObjects;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a joint constrained along one axis with limits based on start and end points defined in the inspector editor.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRPhysicsButton : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
|
||||
[Tooltip("Axis the button will travel on in local space.")]
|
||||
public HVRAxis Axis;
|
||||
|
||||
[Tooltip("Rigidbody this button will connect to with a joint.")]
|
||||
public Rigidbody ConnectedBody;
|
||||
|
||||
[Tooltip("Spring value of the joint")]
|
||||
public float Spring = 1000f;
|
||||
|
||||
[Tooltip("Damper of the joint")]
|
||||
public float Damper = 50f;
|
||||
|
||||
|
||||
|
||||
[Header("Button Positions")]
|
||||
[Tooltip("How far the button must travel to become pressed.")]
|
||||
public float DownThreshold;
|
||||
|
||||
[Tooltip("Threshold to hit on the return to allow the button to be pressed again.")]
|
||||
public float ResetThreshold;
|
||||
|
||||
[Tooltip("The resting position of the button")]
|
||||
public Vector3 StartPosition;
|
||||
|
||||
[Tooltip("Furthest position the button can travel")]
|
||||
public Vector3 EndPosition;
|
||||
|
||||
|
||||
|
||||
[Header("SFX")]
|
||||
public AudioClip SFXButtonDown;
|
||||
public AudioClip SFXButtonUp;
|
||||
|
||||
public HVRButtonEvent ButtonDown = new HVRButtonEvent();
|
||||
public HVRButtonEvent ButtonUp = new HVRButtonEvent();
|
||||
|
||||
[Header("Debug")]
|
||||
public bool IsPressed = false;
|
||||
public bool InvokeButtonDown;
|
||||
public bool UpdateSpring;
|
||||
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
private Vector3 _axis;
|
||||
private ConfigurableJoint _joint;
|
||||
private ConfigurableJoint _limitJoint;
|
||||
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
transform.localPosition = StartPosition;
|
||||
Rigidbody = GetComponent<Rigidbody>();
|
||||
_axis = Axis.GetVector();
|
||||
Rigidbody.useGravity = false;
|
||||
SetupJoint();
|
||||
}
|
||||
|
||||
private void SetupJoint()
|
||||
{
|
||||
var worldStartPosition = StartPosition;
|
||||
if (transform.parent)
|
||||
worldStartPosition = transform.parent.TransformPoint(StartPosition);
|
||||
|
||||
var worldEndPosition = EndPosition;
|
||||
if (transform.parent)
|
||||
worldEndPosition = transform.parent.TransformPoint(EndPosition);
|
||||
|
||||
_joint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
_joint.autoConfigureConnectedAnchor = false;
|
||||
_joint.connectedBody = ConnectedBody;
|
||||
_joint.anchor = Vector3.zero;
|
||||
|
||||
|
||||
|
||||
if (ConnectedBody)
|
||||
{
|
||||
_joint.connectedAnchor = ConnectedBody.transform.InverseTransformPoint(worldStartPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
_joint.connectedAnchor = worldStartPosition;
|
||||
}
|
||||
|
||||
_joint.SetXDrive(Spring, Damper, Spring);
|
||||
|
||||
_joint.LimitXMotion();
|
||||
_joint.LockYMotion();
|
||||
_joint.LockZMotion();
|
||||
_joint.LockAllAngularMotion();
|
||||
_joint.axis = _axis;
|
||||
_joint.secondaryAxis = _joint.axis.OrthogonalVector();
|
||||
_joint.SetLinearLimit(Vector3.Distance(StartPosition, EndPosition));
|
||||
|
||||
_limitJoint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
_limitJoint.autoConfigureConnectedAnchor = false;
|
||||
_limitJoint.connectedBody = ConnectedBody;
|
||||
_limitJoint.anchor = Vector3.zero;
|
||||
|
||||
|
||||
if (ConnectedBody)
|
||||
{
|
||||
_limitJoint.connectedAnchor = ConnectedBody.transform.InverseTransformPoint(worldEndPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
_limitJoint.connectedAnchor = worldEndPosition;
|
||||
}
|
||||
|
||||
_limitJoint.LockYMotion();
|
||||
_limitJoint.LockZMotion();
|
||||
_limitJoint.LockAllAngularMotion();
|
||||
_limitJoint.axis = _axis;
|
||||
_limitJoint.secondaryAxis = _joint.axis.OrthogonalVector();
|
||||
_limitJoint.LimitXMotion();
|
||||
_limitJoint.SetLinearLimit(Vector3.Distance(StartPosition, EndPosition));
|
||||
}
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (UpdateSpring)
|
||||
{
|
||||
_joint.SetXDrive(Spring, Damper, Spring);
|
||||
UpdateSpring = false;
|
||||
}
|
||||
|
||||
var distance = Mathf.Abs(GetDistance());
|
||||
|
||||
if (!IsPressed && distance >= DownThreshold || InvokeButtonDown)
|
||||
{
|
||||
InvokeButtonDown = false;
|
||||
IsPressed = true;
|
||||
OnButtonDown();
|
||||
}
|
||||
else if (IsPressed && distance < ResetThreshold)
|
||||
{
|
||||
IsPressed = false;
|
||||
OnButtonUp();
|
||||
}
|
||||
}
|
||||
|
||||
private float GetDistance()
|
||||
{
|
||||
switch (Axis)
|
||||
{
|
||||
case HVRAxis.X:
|
||||
case HVRAxis.NegX:
|
||||
return transform.localPosition.x - StartPosition.x;
|
||||
case HVRAxis.Y:
|
||||
case HVRAxis.NegY:
|
||||
return transform.localPosition.y - StartPosition.y;
|
||||
case HVRAxis.Z:
|
||||
case HVRAxis.NegZ:
|
||||
return transform.localPosition.z - StartPosition.z;
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
protected virtual void OnButtonDown()
|
||||
{
|
||||
if (SFXButtonDown)
|
||||
{
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXButtonDown, transform.position);
|
||||
}
|
||||
|
||||
ButtonDown.Invoke(this);
|
||||
}
|
||||
|
||||
protected virtual void OnButtonUp()
|
||||
{
|
||||
if (SFXButtonUp)
|
||||
{
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXButtonUp, transform.position);
|
||||
}
|
||||
ButtonUp.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class HVRButtonEvent : UnityEvent<HVRPhysicsButton> { }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fb388898ff2f814f84c5cfa8b56235f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,188 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Core.ScriptableObjects;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple component to help setup a joint constrained on one axis. With bonus rotation friction option when held.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRPhysicsDial : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
[Tooltip("Local axis of rotation")]
|
||||
public HVRAxis Axis;
|
||||
|
||||
[Tooltip("Rigidbody to connect the joint to")]
|
||||
public Rigidbody ConnectedBody;
|
||||
|
||||
[Tooltip("If true the angular velocity will be zero'd out on release.")]
|
||||
public bool StopOnRelease = true;
|
||||
|
||||
[Tooltip("Defaults to true to prevent rotation when not held")]
|
||||
public bool DisableGravity = true;
|
||||
|
||||
[Header("Joint Limits")]
|
||||
public bool LimitRotation;
|
||||
|
||||
[Tooltip("Minimum Angle about the axis of rotation")]
|
||||
public float MinAngle;
|
||||
|
||||
[Tooltip("Maximum rotation about the axis of rotation")]
|
||||
public float MaxAngle;
|
||||
|
||||
[Header("Joint Settings")]
|
||||
[Tooltip("Angular Damper when the dial is grabbed")]
|
||||
public float GrabbedDamper = 3;
|
||||
|
||||
[Tooltip("Angular Damper when the dial is not grabbed")]
|
||||
public float Damper = 3;
|
||||
|
||||
[Tooltip("Optional spring value of the joint to return to starting rotation if desired")]
|
||||
public float Spring;
|
||||
|
||||
[Header("Editor")]
|
||||
[SerializeField]
|
||||
protected Quaternion JointStartRotation;
|
||||
|
||||
[Header("Debugging Tools")]
|
||||
public float TargetAngularVelocity = 0f;
|
||||
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
public HVRGrabbable Grabbable { get; private set; }
|
||||
|
||||
public ConfigurableJoint Joint { get; set; }
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Rigidbody = this.GetRigidbody();
|
||||
|
||||
Rigidbody.useGravity = !DisableGravity;
|
||||
|
||||
Grabbable = GetComponent<HVRGrabbable>();
|
||||
if (Grabbable)
|
||||
{
|
||||
Grabbable.HandGrabbed.AddListener(OnDialGrabbed);
|
||||
Grabbable.HandReleased.AddListener(OnDialReleased);
|
||||
}
|
||||
|
||||
FixAngle(ref MinAngle, ref MaxAngle);
|
||||
|
||||
SetupJoint();
|
||||
AfterJointCreated(Joint);
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (TargetAngularVelocity > 0f || TargetAngularVelocity < 0f) Joint.targetAngularVelocity = new Vector3(TargetAngularVelocity, 0f, 0f);
|
||||
}
|
||||
|
||||
protected virtual void OnDialReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
|
||||
{
|
||||
Joint.SetAngularXDrive(Spring, Damper, 10000f);
|
||||
if (StopOnRelease)
|
||||
{
|
||||
Rigidbody.angularVelocity = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDialGrabbed(HVRHandGrabber arg0, HVRGrabbable arg1)
|
||||
{
|
||||
Joint.SetAngularXDrive(0f, GrabbedDamper, 10000f);
|
||||
}
|
||||
|
||||
protected virtual void SetupJoint()
|
||||
{
|
||||
var currentRotation = transform.localRotation;
|
||||
transform.localRotation = JointStartRotation;
|
||||
Joint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
Joint.connectedBody = ConnectedBody;
|
||||
Joint.LockLinearMotion();
|
||||
Joint.LockAngularYMotion();
|
||||
Joint.LockAngularZMotion();
|
||||
Joint.anchor = Vector3.zero;
|
||||
Joint.axis = Axis.GetVector();
|
||||
|
||||
if (LimitRotation)
|
||||
{
|
||||
ResetLimits();
|
||||
}
|
||||
else
|
||||
{
|
||||
Joint.angularXMotion = ConfigurableJointMotion.Free;
|
||||
}
|
||||
|
||||
Joint.secondaryAxis = Joint.axis.OrthogonalVector();
|
||||
Joint.SetAngularXDrive(Spring, Damper, 10000f);
|
||||
Joint.projectionAngle = 1f;
|
||||
Joint.projectionDistance = .01f;
|
||||
Joint.projectionMode = JointProjectionMode.PositionAndRotation;
|
||||
transform.localRotation = currentRotation;
|
||||
}
|
||||
|
||||
protected virtual void AfterJointCreated(ConfigurableJoint joint)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the rotation limits on the Joint's main rotation axis
|
||||
/// </summary>
|
||||
public void SetLimits(float minAngle, float maxAngle)
|
||||
{
|
||||
FixAngle(ref minAngle, ref maxAngle);
|
||||
|
||||
Joint.LimitAngularXMotion();
|
||||
Joint.SetAngularXHighLimit(minAngle);
|
||||
Joint.SetAngularXLowLimit(maxAngle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the limit's to the -MinAngle and MaxAngle values of this component.
|
||||
/// </summary>
|
||||
public void ResetLimits()
|
||||
{
|
||||
Joint.LimitAngularXMotion();
|
||||
Joint.SetAngularXHighLimit(-MinAngle);
|
||||
Joint.SetAngularXLowLimit(-MaxAngle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Frees the axis of rotation
|
||||
/// </summary>
|
||||
public void RemoveLimits()
|
||||
{
|
||||
Joint.angularXMotion = ConfigurableJointMotion.Free;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sanity check on the angles for the joint high and low settings
|
||||
/// </summary>
|
||||
private void FixAngle(ref float min, ref float max)
|
||||
{
|
||||
if (min > 0)
|
||||
{
|
||||
min *= -1;
|
||||
}
|
||||
|
||||
if (max < 0)
|
||||
{
|
||||
max *= -1;
|
||||
}
|
||||
|
||||
min = Mathf.Clamp(min, min, 0);
|
||||
max = Mathf.Clamp(max, 0, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cd0e73266090f94ea7927da1368c184
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,422 @@
|
||||
using System.Collections;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.ScriptableObjects;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// This component helps setup the basic functionality of a hinged door.
|
||||
/// Includes locking and latching capability. Handle required rotation for unlatching.
|
||||
/// </summary>
|
||||
[HelpURL("https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/components/door.html")]
|
||||
[RequireComponent(typeof(HVRRotationTracker))]
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRPhysicsDoor : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")] [Tooltip("Local axis of rotation")]
|
||||
public HVRAxis Axis;
|
||||
|
||||
[Tooltip("Door's rigidbody mass.")] public float Mass = 10f;
|
||||
|
||||
public bool DisableGravity = true;
|
||||
|
||||
[Tooltip("If true the door and it's handle will have their joint limit's locked on start.")]
|
||||
public bool StartLocked;
|
||||
|
||||
[Tooltip("Rigidbody to connect the joint to")]
|
||||
public Rigidbody ConnectedBody;
|
||||
|
||||
[Header("Door Closing Settings")] [Tooltip("Angle threshold to determine if the door is closed or not.")]
|
||||
public float CloseAngle = 5f;
|
||||
|
||||
[Tooltip("The door will automatically shut over this amount of time once it's close enough to be closed.")]
|
||||
public float CloseOverTime = .25f;
|
||||
|
||||
[Tooltip("How long the door angle must be below 'CloseAngle' to become closed.")]
|
||||
public float CloseDetectionTime = .5f;
|
||||
|
||||
[Header("SFX")] [Tooltip("Angle threshold to play opening and closing sound effects.")]
|
||||
public float SFXThresholdAngle = 2.5f;
|
||||
|
||||
public float SFXResetThreshold = 1f;
|
||||
public AudioClip SFXOpened;
|
||||
public AudioClip SFXClosed;
|
||||
|
||||
[Tooltip("Delay before the open / close sfx can be played again")]
|
||||
public float SFXTimeout = 1f;
|
||||
|
||||
[Tooltip("Optional transform to define the position of the open / close sound fx.")]
|
||||
public Transform SFXPosition;
|
||||
|
||||
[Header("Handle")] [Tooltip("If true the handle must rotate beyond 'HandThreshold' amount of degrees before it will unlatch, if false the door will not latch automatically.")]
|
||||
public bool HandleRequiresRotation;
|
||||
|
||||
[Tooltip("Required handle rotation to unlatch the door.")]
|
||||
public float HandleThreshold = 45f;
|
||||
|
||||
[Tooltip("The rotation tracker that reports the amount of rotation of the handle.")]
|
||||
public HVRRotationTracker HandleRotationTracker;
|
||||
|
||||
[Tooltip("If provided (and held) the door will not automatically shut when it is below 'CloseAngle' in degrees.")]
|
||||
public HVRGrabbable HandleGrabbable;
|
||||
|
||||
[Tooltip("Rotational physics component that let's this door component lock the door handle's rotation when the door locks.")]
|
||||
public HVRPhysicsDial DoorKnob;
|
||||
|
||||
|
||||
[Tooltip("The rotation tracker that reports the amount of rotation of the handle.")]
|
||||
public HVRRotationTracker SecondHandleRotationTracker;
|
||||
|
||||
[Tooltip("If provided (and held) the door will not automatically shut when it is below 'CloseAngle' in degrees.")]
|
||||
public HVRGrabbable SecondHandleGrabbable;
|
||||
|
||||
[Tooltip("Rotational physics component that let's this door component lock the door handle's rotation when the door locks.")]
|
||||
public HVRPhysicsDial SecondDoorKnob;
|
||||
|
||||
[Header("Joint Limits")] public bool LimitRotation = true;
|
||||
|
||||
[Tooltip("Minimum Angle about the axis of rotation")]
|
||||
public float MinAngle;
|
||||
|
||||
[Tooltip("Maximum rotation about the axis of rotation")]
|
||||
public float MaxAngle;
|
||||
|
||||
[Header("Joint Settings")] [Tooltip("Angular Damper of the door hinge.")]
|
||||
public float Damper = 10;
|
||||
|
||||
[Tooltip("Angular Spring that will return the door to it's starting rotation")]
|
||||
public float Spring;
|
||||
|
||||
//[Header("Editor")]
|
||||
//[SerializeField]
|
||||
//protected Quaternion JointStartRotation;
|
||||
|
||||
[Header("Debugging")] public float TargetAngularVelocity = 0f;
|
||||
public bool DoorLatched;
|
||||
public bool DoorClosed;
|
||||
public bool Opened;
|
||||
public bool Closed;
|
||||
public bool PreviousDoorLatched;
|
||||
public bool PreviousClosed;
|
||||
public bool VerboseLogging;
|
||||
public bool Locked;
|
||||
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
public HVRRotationTracker Tracker { get; private set; }
|
||||
|
||||
protected ConfigurableJoint Joint { get; set; }
|
||||
|
||||
private Quaternion _startRotation;
|
||||
private bool _doorClosing;
|
||||
private float _detectionTimer;
|
||||
private float _lastClosedSFXTime;
|
||||
private float _lastOpenedSFXTime;
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
Rigidbody = this.GetRigidbody();
|
||||
Rigidbody.mass = Mass;
|
||||
Rigidbody.useGravity = !DisableGravity;
|
||||
|
||||
Tracker = GetComponent<HVRRotationTracker>();
|
||||
|
||||
if (MinAngle > 0)
|
||||
{
|
||||
MinAngle *= -1;
|
||||
}
|
||||
|
||||
if (MaxAngle < 0)
|
||||
{
|
||||
MaxAngle *= -1;
|
||||
}
|
||||
|
||||
MinAngle = Mathf.Clamp(MinAngle, MinAngle, 0);
|
||||
MaxAngle = Mathf.Clamp(MaxAngle, 0, MaxAngle);
|
||||
|
||||
if (HandleRequiresRotation)
|
||||
{
|
||||
if (!HandleRotationTracker)
|
||||
{
|
||||
Debug.LogError("HandleRotationTracker not assigned.");
|
||||
}
|
||||
|
||||
DoorLatched = true;
|
||||
}
|
||||
|
||||
DoorClosed = true;
|
||||
PreviousDoorLatched = DoorLatched;
|
||||
PreviousClosed = DoorClosed;
|
||||
|
||||
SetupJoint();
|
||||
|
||||
_startRotation = transform.localRotation;
|
||||
|
||||
if (DoorLatched)
|
||||
{
|
||||
LockDoorJoint();
|
||||
}
|
||||
|
||||
if (StartLocked)
|
||||
{
|
||||
Lock();
|
||||
}
|
||||
|
||||
//set initial values to prevent sfx on start
|
||||
if (Tracker.UnsignedAngle < SFXThresholdAngle)
|
||||
{
|
||||
Closed = true;
|
||||
}
|
||||
else if (Tracker.UnsignedAngle > SFXThresholdAngle)
|
||||
{
|
||||
Opened = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
Joint.targetAngularVelocity = new Vector3(TargetAngularVelocity, 0f, 0f);
|
||||
|
||||
if (_doorClosing)
|
||||
return;
|
||||
|
||||
if (Tracker.UnsignedAngle < CloseAngle)
|
||||
{
|
||||
_detectionTimer += Time.deltaTime;
|
||||
}
|
||||
else if (Tracker.UnsignedAngle >= CloseAngle)
|
||||
{
|
||||
_detectionTimer = 0f;
|
||||
DoorClosed = false;
|
||||
}
|
||||
|
||||
if (HandleGrabbable && HandleGrabbable.IsBeingHeld || SecondHandleGrabbable && SecondHandleGrabbable.IsBeingHeld)
|
||||
{
|
||||
_detectionTimer = 0f;
|
||||
}
|
||||
|
||||
if (_detectionTimer > CloseDetectionTime)
|
||||
{
|
||||
DoorClosed = true;
|
||||
}
|
||||
|
||||
if (!PreviousClosed && DoorClosed)
|
||||
{
|
||||
OnDoorClosed();
|
||||
}
|
||||
else if (PreviousClosed && !DoorClosed)
|
||||
{
|
||||
OnDoorOpened();
|
||||
}
|
||||
|
||||
var reset = SFXResetThreshold;
|
||||
if (SFXResetThreshold > SFXThresholdAngle)
|
||||
{
|
||||
reset = SFXThresholdAngle * .5f;
|
||||
}
|
||||
|
||||
if (!Opened && Tracker.UnsignedAngle > SFXThresholdAngle && Time.time - _lastOpenedSFXTime > SFXTimeout)
|
||||
{
|
||||
_lastOpenedSFXTime = Time.time;
|
||||
Opened = true;
|
||||
PlayOpenedSFX();
|
||||
}
|
||||
else if (!Closed && Tracker.UnsignedAngle < SFXThresholdAngle && Time.time - _lastClosedSFXTime > SFXTimeout)
|
||||
{
|
||||
_lastClosedSFXTime = Time.time;
|
||||
Closed = true;
|
||||
PlayClosedSFX();
|
||||
}
|
||||
else if (Opened && Tracker.UnsignedAngle < SFXThresholdAngle - reset)
|
||||
{
|
||||
Opened = false;
|
||||
}
|
||||
else if (Closed && Tracker.UnsignedAngle > SFXThresholdAngle + reset)
|
||||
{
|
||||
Closed = false;
|
||||
}
|
||||
|
||||
if (HandleRequiresRotation)
|
||||
{
|
||||
if (HandleRotationTracker.UnsignedAngle >= HandleThreshold ||
|
||||
(SecondHandleRotationTracker && SecondHandleRotationTracker.UnsignedAngle >= HandleThreshold))
|
||||
{
|
||||
DoorLatched = false;
|
||||
}
|
||||
else if (HandleRotationTracker.UnsignedAngle < HandleThreshold &&
|
||||
(!SecondHandleRotationTracker || SecondHandleRotationTracker.UnsignedAngle < HandleThreshold) &&
|
||||
Tracker.UnsignedAngle < CloseAngle)
|
||||
{
|
||||
DoorLatched = true;
|
||||
}
|
||||
|
||||
if (!Locked)
|
||||
{
|
||||
if (PreviousDoorLatched && !DoorLatched)
|
||||
{
|
||||
OnDoorUnLatched();
|
||||
}
|
||||
else if (!PreviousDoorLatched && DoorLatched)
|
||||
{
|
||||
OnDoorLatched();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PreviousDoorLatched = DoorLatched;
|
||||
PreviousClosed = DoorClosed;
|
||||
}
|
||||
|
||||
protected virtual Vector3 GetSFXPosition()
|
||||
{
|
||||
var position = transform.position;
|
||||
if (SFXPosition)
|
||||
{
|
||||
position = SFXPosition.position;
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
protected virtual void PlayClosedSFX()
|
||||
{
|
||||
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXClosed, GetSFXPosition());
|
||||
}
|
||||
|
||||
|
||||
protected virtual void PlayOpenedSFX()
|
||||
{
|
||||
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXOpened, GetSFXPosition());
|
||||
}
|
||||
|
||||
public virtual void OnDoorUnLatched()
|
||||
{
|
||||
if (VerboseLogging)
|
||||
Debug.Log($"OnDoorUnLatched");
|
||||
UnlockDoorJoint();
|
||||
}
|
||||
|
||||
public virtual void OnDoorLatched()
|
||||
{
|
||||
if (VerboseLogging)
|
||||
Debug.Log($"OnDoorLatched");
|
||||
LockDoorJoint();
|
||||
}
|
||||
|
||||
// ReSharper disable Unity.PerformanceAnalysis
|
||||
protected virtual void OnDoorClosed()
|
||||
{
|
||||
if (VerboseLogging)
|
||||
Debug.Log($"OnDoorClosed");
|
||||
|
||||
StartCoroutine(DoorCloseRoutine());
|
||||
}
|
||||
|
||||
// ReSharper disable Unity.PerformanceAnalysis
|
||||
protected virtual void OnDoorOpened()
|
||||
{
|
||||
if (VerboseLogging)
|
||||
Debug.Log($"OnDoorOpened");
|
||||
}
|
||||
|
||||
protected virtual void LockDoorJoint()
|
||||
{
|
||||
if (!LimitRotation)
|
||||
return;
|
||||
|
||||
Joint.SetAngularXHighLimit(0);
|
||||
Joint.SetAngularXLowLimit(0);
|
||||
}
|
||||
|
||||
protected virtual void UnlockDoorJoint()
|
||||
{
|
||||
Joint.SetAngularXHighLimit(-MinAngle);
|
||||
Joint.SetAngularXLowLimit(-MaxAngle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks the door joint, and the door knob's joint.
|
||||
/// </summary>
|
||||
public virtual void Lock()
|
||||
{
|
||||
Locked = true;
|
||||
LockDoorJoint();
|
||||
LockDoorKnob();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks the door and allows the door handle to rotate.
|
||||
/// </summary>
|
||||
public virtual void Unlock()
|
||||
{
|
||||
Locked = false;
|
||||
|
||||
if (!DoorLatched)
|
||||
{
|
||||
UnlockDoorJoint();
|
||||
}
|
||||
|
||||
UnlockDoorKnob();
|
||||
}
|
||||
|
||||
protected virtual void LockDoorKnob()
|
||||
{
|
||||
if (DoorKnob) DoorKnob.SetLimits(0, 0);
|
||||
if (SecondDoorKnob) SecondDoorKnob.SetLimits(0, 0);
|
||||
}
|
||||
|
||||
protected virtual void UnlockDoorKnob()
|
||||
{
|
||||
if (DoorKnob) DoorKnob.ResetLimits();
|
||||
if (SecondDoorKnob) SecondDoorKnob.ResetLimits();
|
||||
}
|
||||
|
||||
protected IEnumerator DoorCloseRoutine()
|
||||
{
|
||||
_doorClosing = true;
|
||||
var startRotation = transform.localRotation;
|
||||
var elapsed = 0f;
|
||||
while (elapsed < CloseOverTime)
|
||||
{
|
||||
transform.localRotation = Quaternion.Lerp(startRotation, _startRotation, elapsed / CloseOverTime);
|
||||
elapsed += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
transform.localRotation = _startRotation;
|
||||
_doorClosing = false;
|
||||
}
|
||||
|
||||
protected virtual void SetupJoint()
|
||||
{
|
||||
var currentRotation = transform.localRotation;
|
||||
//transform.localRotation = JointStartRotation;
|
||||
Joint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
Joint.connectedBody = ConnectedBody;
|
||||
Joint.LockLinearMotion();
|
||||
Joint.LockAngularYMotion();
|
||||
Joint.LockAngularZMotion();
|
||||
Joint.anchor = Vector3.zero;
|
||||
Joint.axis = Axis.GetVector();
|
||||
|
||||
if (LimitRotation)
|
||||
{
|
||||
Joint.LimitAngularXMotion();
|
||||
Joint.SetAngularXHighLimit(-MinAngle);
|
||||
Joint.SetAngularXLowLimit(-MaxAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Joint.angularXMotion = ConfigurableJointMotion.Free;
|
||||
}
|
||||
|
||||
Joint.secondaryAxis = Joint.axis.OrthogonalVector();
|
||||
Joint.SetAngularXDrive(Spring, Damper, 10000f);
|
||||
|
||||
transform.localRotation = currentRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4eeb3f37d2fe3e547a9a248b2bbf0139
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Core.ScriptableObjects;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper component to constrain a drawer along the desired movement axis handling the joint creation and limiting for you.
|
||||
/// Joint is constrained between the start and end position which is defined in the component inspector.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRPhysicsDrawer : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
[Tooltip("Axis the drawer will travel on in local space.")]
|
||||
public HVRAxis Axis;
|
||||
|
||||
[Tooltip("Rigidbody to joint to.")]
|
||||
public Rigidbody ConnectedBody;
|
||||
|
||||
[Tooltip("Optional spring that will return to the starting position")]
|
||||
public float Spring = 0;
|
||||
|
||||
[Tooltip("Damper to provide 'friction' to the drawer.")]
|
||||
public float Damper = 10;
|
||||
|
||||
[Header("SFX")]
|
||||
public float SFXResetThreshold = .02f;
|
||||
public AudioClip SFXOpened;
|
||||
public AudioClip SFXClosed;
|
||||
|
||||
[Header("Editor Fields")]
|
||||
[Tooltip("The resting position of the button")]
|
||||
public Vector3 StartPosition;
|
||||
|
||||
[Tooltip("Furthest position the button can travel")]
|
||||
public Vector3 EndPosition;
|
||||
|
||||
public Vector3 OpenPosition;
|
||||
|
||||
|
||||
[Header("Debug")]
|
||||
public bool UpdateSpring;
|
||||
public bool PreviousOpened;
|
||||
public bool Opened;
|
||||
public bool PreviousClosed;
|
||||
public bool Closed;
|
||||
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
private Vector3 _axis;
|
||||
private ConfigurableJoint _joint;
|
||||
private ConfigurableJoint _limitJoint;
|
||||
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
transform.localPosition = StartPosition;
|
||||
Rigidbody = GetComponent<Rigidbody>();
|
||||
_axis = Axis.GetVector();
|
||||
Rigidbody.useGravity = false;
|
||||
SetupJoint();
|
||||
|
||||
//set initial values to prevent sfx on start
|
||||
GetValues(out var distance, out var openedDistance, out var resetThreshold);
|
||||
|
||||
if (distance > openedDistance)
|
||||
{
|
||||
Opened = true;
|
||||
}
|
||||
else if (distance < openedDistance)
|
||||
{
|
||||
Closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupJoint()
|
||||
{
|
||||
_joint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
_joint.connectedBody = ConnectedBody;
|
||||
_joint.autoConfigureConnectedAnchor = false;
|
||||
_joint.anchor = Vector3.zero;
|
||||
|
||||
var worldStartPosition = StartPosition;
|
||||
if (transform.parent)
|
||||
worldStartPosition = transform.parent.TransformPoint(StartPosition);
|
||||
|
||||
var worldEndPosition = EndPosition;
|
||||
if (transform.parent)
|
||||
worldEndPosition = transform.parent.TransformPoint(EndPosition);
|
||||
|
||||
|
||||
if (ConnectedBody)
|
||||
{
|
||||
_joint.connectedAnchor = ConnectedBody.transform.InverseTransformPoint(worldStartPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
_joint.connectedAnchor = worldStartPosition;
|
||||
}
|
||||
|
||||
_joint.SetXDrive(Spring, Damper, Spring);
|
||||
|
||||
_joint.LimitXMotion();
|
||||
_joint.LockYMotion();
|
||||
_joint.LockZMotion();
|
||||
_joint.LockAllAngularMotion();
|
||||
_joint.axis = _axis;
|
||||
_joint.secondaryAxis = _joint.axis.OrthogonalVector();
|
||||
_joint.SetLinearLimit(Vector3.Distance(StartPosition, EndPosition));
|
||||
|
||||
_limitJoint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
_limitJoint.connectedBody = ConnectedBody;
|
||||
_limitJoint.autoConfigureConnectedAnchor = false;
|
||||
_limitJoint.anchor = Vector3.zero;
|
||||
|
||||
if (ConnectedBody)
|
||||
{
|
||||
_limitJoint.connectedAnchor = ConnectedBody.transform.InverseTransformPoint(worldEndPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
_limitJoint.connectedAnchor = worldEndPosition;
|
||||
}
|
||||
|
||||
_limitJoint.LockYMotion();
|
||||
_limitJoint.LockZMotion();
|
||||
_limitJoint.LockAllAngularMotion();
|
||||
_limitJoint.axis = _axis;
|
||||
_limitJoint.secondaryAxis = _joint.axis.OrthogonalVector();
|
||||
_limitJoint.LimitXMotion();
|
||||
_limitJoint.SetLinearLimit(Vector3.Distance(StartPosition, EndPosition));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
GetValues(out var distance, out var openedDistance, out var resetThreshold);
|
||||
|
||||
var closeReset = openedDistance + resetThreshold;
|
||||
var openReset = openedDistance - resetThreshold;
|
||||
|
||||
if (!Opened && distance > openedDistance)
|
||||
{
|
||||
Opened = true;
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXOpened, transform.position);
|
||||
}
|
||||
else if (!Closed && distance < openedDistance)
|
||||
{
|
||||
Closed = true;
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXClosed, transform.position);
|
||||
}
|
||||
else if (Opened && distance < openReset)
|
||||
{
|
||||
Opened = false;
|
||||
}
|
||||
else if (Closed && distance > closeReset)
|
||||
{
|
||||
Closed = false;
|
||||
}
|
||||
|
||||
PreviousClosed = Closed;
|
||||
PreviousOpened = Opened;
|
||||
}
|
||||
|
||||
private void GetValues(out float distance, out float openDistance, out float resetDelta)
|
||||
{
|
||||
distance = 0f;
|
||||
openDistance = 0f;
|
||||
resetDelta = SFXResetThreshold;
|
||||
switch (Axis)
|
||||
{
|
||||
case HVRAxis.X:
|
||||
case HVRAxis.NegX:
|
||||
distance = transform.localPosition.x - StartPosition.x;
|
||||
openDistance = OpenPosition.x - StartPosition.x;
|
||||
break;
|
||||
case HVRAxis.Y:
|
||||
case HVRAxis.NegY:
|
||||
distance = transform.localPosition.y - StartPosition.y;
|
||||
openDistance = OpenPosition.y - StartPosition.y;
|
||||
break;
|
||||
case HVRAxis.Z:
|
||||
case HVRAxis.NegZ:
|
||||
distance = transform.localPosition.z - StartPosition.z;
|
||||
openDistance = OpenPosition.z - StartPosition.z;
|
||||
break;
|
||||
}
|
||||
|
||||
distance = Mathf.Abs(distance);
|
||||
openDistance = Mathf.Abs(openDistance);
|
||||
|
||||
if (resetDelta > openDistance)
|
||||
{
|
||||
resetDelta = openDistance * .5f;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
var forward = (EndPosition - StartPosition).normalized;
|
||||
var closeReset = transform.parent.TransformPoint(OpenPosition + (forward * SFXResetThreshold));
|
||||
var openReset = transform.parent.TransformPoint(OpenPosition - (forward * SFXResetThreshold));
|
||||
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireSphere(closeReset, .005f);
|
||||
Gizmos.color = Color.green;
|
||||
Gizmos.DrawWireSphere(openReset, .005f);
|
||||
Gizmos.color = Color.blue;
|
||||
Gizmos.DrawWireSphere(transform.parent.TransformPoint(OpenPosition), .005f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 465d464c79597514bb491631782942cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Lever behaves similar to the dial in rigidbody joint behaviour at this time...
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRPhysicsLever : HVRPhysicsDial
|
||||
{
|
||||
public bool DrawGizmos = true;
|
||||
|
||||
|
||||
public void OnDrawGizmosSelected()
|
||||
{
|
||||
//if (DrawGizmos)
|
||||
//{
|
||||
// var minVector = Quaternion.Euler(MinAngle * _axis) * _orthogonal;
|
||||
// var maxVector = Quaternion.Euler(MaxAngle * _axis) * _orthogonal;
|
||||
|
||||
// Gizmos.color = Color.green;
|
||||
// Gizmos.DrawLine(transform.position, transform.position + transform.TransformDirection(minVector) * .3f);
|
||||
// Gizmos.color = Color.yellow;
|
||||
// Gizmos.DrawLine(transform.position, transform.position + transform.TransformDirection(maxVector) * .3f);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93ae46635261c874188443083a8deee5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
using Assets.HurricaneVR.Framework.Shared.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper component to override various rigidbody properties
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class HVRRigidBodyOverrides : MonoBehaviour
|
||||
{
|
||||
|
||||
public bool OverrideCOM;
|
||||
public bool OverrideRotation;
|
||||
public bool OverrideTensor;
|
||||
public bool OverrideAngularSpeed;
|
||||
public bool OverrideMaxDepenetration;
|
||||
|
||||
public Vector3 CenterOfMass;
|
||||
public Vector3 InertiaTensorRotation;
|
||||
public Vector3 InertiaTensor;
|
||||
public float MaxAngularVelocity;
|
||||
public float MaxDepenetration;
|
||||
|
||||
[Header("Debug")]
|
||||
public Vector3 COMGizmoSize = new Vector3(.02f, .02f, .02f);
|
||||
public bool LiveUpdate;
|
||||
public bool ShowCOMGizmo;
|
||||
public Rigidbody Rigidbody;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (!Rigidbody)
|
||||
{
|
||||
Rigidbody = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
this.ExecuteNextUpdate(ApplyOverrides);
|
||||
}
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
if (!Rigidbody) TryGetComponent(out Rigidbody);
|
||||
}
|
||||
|
||||
public void ApplyOverrides()
|
||||
{
|
||||
if (OverrideCOM)
|
||||
{
|
||||
Rigidbody.centerOfMass = CenterOfMass;
|
||||
}
|
||||
|
||||
if (OverrideTensor)
|
||||
{
|
||||
Rigidbody.inertiaTensor = InertiaTensor;
|
||||
}
|
||||
|
||||
if (OverrideRotation)
|
||||
{
|
||||
Rigidbody.inertiaTensorRotation = Quaternion.Euler(InertiaTensorRotation);
|
||||
}
|
||||
|
||||
if (OverrideAngularSpeed)
|
||||
{
|
||||
Rigidbody.maxAngularVelocity = MaxAngularVelocity;
|
||||
}
|
||||
|
||||
if (OverrideMaxDepenetration) Rigidbody.maxDepenetrationVelocity = MaxDepenetration;
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
if (LiveUpdate)
|
||||
{
|
||||
ApplyOverrides();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
if (ShowCOMGizmo)
|
||||
{
|
||||
Gizmos.color = Color.yellow;
|
||||
if (OverrideCOM)
|
||||
{
|
||||
Gizmos.DrawCube(transform.TransformPoint(CenterOfMass), COMGizmoSize);
|
||||
}
|
||||
else if(Rigidbody)
|
||||
{
|
||||
Gizmos.DrawCube(Rigidbody.worldCenterOfMass, COMGizmoSize);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1a0e712065e5ec4484d6ca15e0f4563
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Helps constrain loose joints on the desired axis.
|
||||
/// </summary>
|
||||
public class HVRRigidbodyLocker : MonoBehaviour
|
||||
{
|
||||
public LockOptions Locks;
|
||||
|
||||
private Vector3 _position;
|
||||
private Vector3 _rotation;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_position = transform.localPosition;
|
||||
_rotation = transform.localEulerAngles;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
Lock();
|
||||
}
|
||||
|
||||
private void Lock()
|
||||
{
|
||||
var position = transform.localPosition;
|
||||
var rotation = transform.localEulerAngles;
|
||||
|
||||
if ((Locks & LockOptions.PosX) == LockOptions.PosX)
|
||||
{
|
||||
position.x = _position.x;
|
||||
}
|
||||
|
||||
if ((Locks & LockOptions.PosY) == LockOptions.PosY)
|
||||
{
|
||||
position.y = _position.y;
|
||||
}
|
||||
|
||||
if ((Locks & LockOptions.PosZ) == LockOptions.PosZ)
|
||||
{
|
||||
position.z = _position.z;
|
||||
}
|
||||
|
||||
if ((Locks & LockOptions.RotX) == LockOptions.RotX)
|
||||
{
|
||||
rotation.x = _rotation.x;
|
||||
}
|
||||
|
||||
if ((Locks & LockOptions.RotY) == LockOptions.RotY)
|
||||
{
|
||||
rotation.y = _rotation.y;
|
||||
}
|
||||
|
||||
if ((Locks & LockOptions.RotZ) == LockOptions.RotZ)
|
||||
{
|
||||
rotation.z = _rotation.z;
|
||||
}
|
||||
|
||||
transform.localPosition = position;
|
||||
transform.localEulerAngles = rotation;
|
||||
}
|
||||
|
||||
public void LateUpdate()
|
||||
{
|
||||
Lock();
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum LockOptions
|
||||
{
|
||||
None = 0,
|
||||
PosX = 1,
|
||||
PosY = 2,
|
||||
PosZ = 4,
|
||||
RotX = 8,
|
||||
RotY = 16,
|
||||
RotZ = 32
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f268fd1aeab764742be311a0d06b49d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
[RequireComponent(typeof(MeshRenderer))]
|
||||
public class HVRRingHighlight : HVRScaleHighlight
|
||||
{
|
||||
public Transform Camera;
|
||||
|
||||
[Header("Settings")]
|
||||
|
||||
[Tooltip("Ring must be within this distance from the camera to be displayed")]
|
||||
public float Distance = 5f;
|
||||
|
||||
|
||||
[Header("Line of Sight Settings")]
|
||||
|
||||
[Tooltip("Use ray cast to the camera collider to determine if we should show")]
|
||||
public bool RequireLineOfSight = true;
|
||||
|
||||
[Tooltip("Layer mask for checking line of sight, include the layer of the camera(default is Player)")]
|
||||
public LayerMask LayerMask;
|
||||
|
||||
[Tooltip("Check line of sight only if distance greater than this")]
|
||||
public float LineOfSightThreshold = 1.5f;
|
||||
|
||||
[Tooltip("Timeout to check line of sight")]
|
||||
public float Delay = 1f;
|
||||
|
||||
public MeshRenderer Ring { get; private set; }
|
||||
|
||||
private bool _hasCamera;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
if (!Camera && HVRManager.Instance)
|
||||
{
|
||||
Camera = HVRManager.Instance.Camera;
|
||||
}
|
||||
|
||||
_hasCamera = Camera;
|
||||
|
||||
Ring = GetComponent<MeshRenderer>();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!_hasCamera)
|
||||
return;
|
||||
|
||||
transform.LookAt(Camera);
|
||||
|
||||
if (!RequireLineOfSight)
|
||||
{
|
||||
var distance = Vector3.Distance(transform.position, Camera.position);
|
||||
if (distance > Distance)
|
||||
{
|
||||
Ring.enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ring.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (!RequireLineOfSight || !_hasCamera)
|
||||
return;
|
||||
|
||||
var distance = Vector3.Distance(transform.position, Camera.position);
|
||||
if (distance > Distance)
|
||||
{
|
||||
Ring.enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (distance < LineOfSightThreshold)
|
||||
{
|
||||
Ring.enabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Physics.Raycast(transform.position, (Camera.position - transform.position).normalized, out var hit, Distance, LayerMask, QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
Ring.enabled = hit.collider.gameObject == Camera.transform.gameObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ring.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
base.Enable();
|
||||
Ring.enabled = true;
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
base.Disable();
|
||||
Ring.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f12566bd4f6404580f543211008456c
|
||||
timeCreated: 1600292559
|
||||
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Core.ScriptableObjects;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to limit rotations beyond the default Physx limit of 177 degrees. Joint is recreated at certain thresholds to allow the wider
|
||||
/// range of motion, only use this if you need range of motion beyond 177 degrees.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
[RequireComponent(typeof(HVRRotationTracker))]
|
||||
public class HVRRotationLimiter : MonoBehaviour
|
||||
{
|
||||
public const float PhysxMaxLimit = 177f;
|
||||
|
||||
[Tooltip("Connected Body of the Joint")]
|
||||
public Rigidbody ConnectedBody;
|
||||
|
||||
[Tooltip("Minimum angle of rotation")]
|
||||
public int MinAngle;
|
||||
|
||||
[Tooltip("Maximum angle of rotation")]
|
||||
public int MaxAngle;
|
||||
|
||||
[Tooltip("Distance traveled before the joint is recreated with new limits")]
|
||||
public float JointResetThreshold = 90f;
|
||||
|
||||
|
||||
public Rigidbody Rigidbody { get; private set; }
|
||||
|
||||
public HVRRotationTracker Tracker { get; private set; }
|
||||
|
||||
private ConfigurableJoint _joint;
|
||||
private float _angleAtCreation;
|
||||
|
||||
[Header("Debugging")]
|
||||
public float maxDelta;
|
||||
public float minDelta;
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
Rigidbody = this.GetRigidbody();
|
||||
Tracker = GetComponent<HVRRotationTracker>();
|
||||
|
||||
if (MinAngle > 0)
|
||||
{
|
||||
MinAngle *= -1;
|
||||
}
|
||||
|
||||
if (MaxAngle < 0)
|
||||
{
|
||||
MaxAngle *= -1;
|
||||
}
|
||||
|
||||
MinAngle = Mathf.Clamp(MinAngle, MinAngle, 0);
|
||||
MaxAngle = Mathf.Clamp(MaxAngle, 0, MaxAngle);
|
||||
}
|
||||
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
var angle = Mathf.Clamp(Tracker.Angle, MinAngle, MaxAngle);
|
||||
minDelta = Math.Abs(MinAngle - angle);
|
||||
maxDelta = MaxAngle - angle;
|
||||
|
||||
var force = false;
|
||||
if (_joint)
|
||||
{
|
||||
var angleFromJointCreation = angle - _angleAtCreation;
|
||||
var angleDelta = Mathf.Abs(angleFromJointCreation);
|
||||
|
||||
if (angleDelta > JointResetThreshold)
|
||||
{
|
||||
Destroy(_joint);
|
||||
force = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_joint || force)
|
||||
{
|
||||
if (minDelta < PhysxMaxLimit || maxDelta < PhysxMaxLimit)
|
||||
{
|
||||
_joint = gameObject.AddComponent<ConfigurableJoint>();
|
||||
_joint.axis = Tracker.AxisOfRotation;
|
||||
_joint.secondaryAxis = Tracker.AxisOfRotation.OrthogonalVector();
|
||||
_joint.LimitAngularXMotion();
|
||||
_joint.connectedBody = ConnectedBody;
|
||||
|
||||
_angleAtCreation = Tracker.Angle;
|
||||
|
||||
if (minDelta < PhysxMaxLimit)
|
||||
{
|
||||
_joint.SetAngularXHighLimit(minDelta);
|
||||
}
|
||||
else
|
||||
{
|
||||
_joint.SetAngularXHighLimit(PhysxMaxLimit);
|
||||
}
|
||||
|
||||
if (maxDelta < PhysxMaxLimit)
|
||||
{
|
||||
_joint.SetAngularXLowLimit(-maxDelta);
|
||||
}
|
||||
else
|
||||
{
|
||||
_joint.SetAngularXLowLimit(-PhysxMaxLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02aeadf9b7915034d999c6e3161257f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,56 @@
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Used in conjunction with the HVRRotationTracker to play SFX based on rotation amount.
|
||||
/// </summary>
|
||||
public class HVRRotationSFX : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Tracker required to know how far something has rotated")]
|
||||
public HVRRotationTracker Tracker;
|
||||
|
||||
[Tooltip("Clip chosen at random from this list when rotated beyond 'AngleThreshold'")]
|
||||
public AudioClip[] SFX;
|
||||
|
||||
[Tooltip("Rotation distance must exceed this to play another sfx clip")]
|
||||
public float AngleThreshold = 30f;
|
||||
|
||||
[Header("Debug")]
|
||||
public float AngleAccumulated;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (Tracker)
|
||||
{
|
||||
Tracker = GetComponent<HVRRotationTracker>();
|
||||
}
|
||||
|
||||
if (Tracker)
|
||||
{
|
||||
Tracker.AngleChanged.AddListener(OnAngleChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAngleChanged(float angle, float delta)
|
||||
{
|
||||
if (SFX != null && SFX.Length > 0)
|
||||
{
|
||||
AngleAccumulated += Mathf.Abs(delta);
|
||||
if (AngleAccumulated > AngleThreshold)
|
||||
{
|
||||
var index = Random.Range(0, SFX.Length);
|
||||
var sfx = SFX[index];
|
||||
AngleAccumulated = 0;
|
||||
PlaySFX(sfx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void PlaySFX(AudioClip sfx)
|
||||
{
|
||||
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(sfx, transform.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50bacb0498a77b04b867c1791becba25
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Utils;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to track the rotation in degrees about a defined axis of rotation.
|
||||
/// Degrees are reported from the starting rotation of the transform.
|
||||
/// </summary>
|
||||
public class HVRRotationTracker : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Local axis of rotation")]
|
||||
public HVRAxis Axis;
|
||||
|
||||
[Tooltip("Number of Steps")]
|
||||
public int Steps;
|
||||
|
||||
[Tooltip("Threshold to reach to fire the Angle changed method and events")]
|
||||
public float AngleThreshold = 1f;
|
||||
|
||||
[Tooltip("Max angle for Step Size calculation, should match limits set on whatever is controlling the rotational limits of this object")]
|
||||
public float MaximumAngle = 360f;
|
||||
|
||||
public RotationTrackerStepEvent StepChanged = new RotationTrackerStepEvent();
|
||||
public RotationTrackerAngleEvent AngleChanged = new RotationTrackerAngleEvent();
|
||||
|
||||
[Header("Debug")]
|
||||
|
||||
public float StepSize;
|
||||
public int Step;
|
||||
|
||||
private Vector3 _angleVector;
|
||||
private float _previousAngle;
|
||||
private Vector3 _trackAxis;
|
||||
private Vector3 _startVector;
|
||||
|
||||
[SerializeField]
|
||||
private float _clampedAngle;
|
||||
[SerializeField]
|
||||
private float _angleFromStart;
|
||||
|
||||
public float ClampedAngle { get; private set; }
|
||||
public float Angle { get; private set; }
|
||||
|
||||
public float UnsignedAngle => Mathf.Abs(Angle);
|
||||
|
||||
public Vector3 AxisOfRotation { get; private set; }
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
AxisOfRotation = Axis.GetVector();
|
||||
AxisOfRotation.Normalize();
|
||||
_trackAxis = AxisOfRotation.OrthogonalVector();
|
||||
|
||||
_startVector = transform.localRotation * _trackAxis;
|
||||
|
||||
if (Steps <= 1)
|
||||
{
|
||||
StepSize = 0f;
|
||||
}
|
||||
else if (Steps > 1 && Mathf.Approximately(StepSize, 0f))
|
||||
{
|
||||
StepSize = MaximumAngle / Steps;
|
||||
}
|
||||
|
||||
_angleVector = _startVector;
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
var currentVector = transform.localRotation * _trackAxis;
|
||||
|
||||
ClampedAngle = Vector3.SignedAngle(_startVector, currentVector, AxisOfRotation);
|
||||
|
||||
if (ClampedAngle < 0)
|
||||
{
|
||||
ClampedAngle += 360;
|
||||
}
|
||||
|
||||
var angleDelta = Vector3.SignedAngle(_angleVector, currentVector, AxisOfRotation);
|
||||
if (Mathf.Abs(angleDelta) > AngleThreshold)
|
||||
{
|
||||
_angleVector = currentVector;
|
||||
Angle += angleDelta;
|
||||
OnAngleChanged(ClampedAngle, angleDelta);
|
||||
}
|
||||
|
||||
var stepAngle = ClampedAngle;
|
||||
if (Steps > 1)
|
||||
{
|
||||
Step = Mathf.RoundToInt(ClampedAngle / StepSize);
|
||||
stepAngle = Step * StepSize;
|
||||
if (Mathf.Approximately(stepAngle, 360))
|
||||
{
|
||||
Step = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Steps > 1)
|
||||
{
|
||||
if (!Mathf.Approximately(stepAngle, _previousAngle))
|
||||
{
|
||||
OnStepChanged(Step, true);
|
||||
_previousAngle = stepAngle;
|
||||
}
|
||||
}
|
||||
|
||||
_angleFromStart = Angle;
|
||||
_clampedAngle = ClampedAngle;
|
||||
}
|
||||
|
||||
protected virtual void OnStepChanged(int step, bool raiseEvents)
|
||||
{
|
||||
StepChanged.Invoke(step);
|
||||
}
|
||||
|
||||
protected virtual void OnAngleChanged(float angle, float delta)
|
||||
{
|
||||
AngleChanged.Invoke(angle, delta);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class RotationTrackerAngleEvent : UnityEvent<float, float> { }
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class RotationTrackerStepEvent : UnityEvent<int> { }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80e9f8f507f775b4aa48c08844126549
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Specialized hover behaviour that scales this transform over time when a hand or force grabber is hovering it.
|
||||
/// </summary>
|
||||
public class HVRScaleHighlight : HVRGrabbableHoverBase
|
||||
{
|
||||
public Vector3 HoverScale = new Vector3(1.3f, 1.3f, 1.3f);
|
||||
public Vector3 UnhoverScale = new Vector3(.1f, .1f, .1f);
|
||||
public float ScaleSpeed = .05f;
|
||||
|
||||
private Vector3 _targetScale;
|
||||
private Vector3 _originalScale;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_originalScale = transform.localScale;
|
||||
_targetScale = _originalScale;
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
transform.localScale = Vector3.Lerp(transform.localScale, _targetScale, ScaleSpeed);
|
||||
}
|
||||
|
||||
public override void Hover()
|
||||
{
|
||||
_targetScale = HoverScale;
|
||||
}
|
||||
|
||||
public override void Unhover()
|
||||
{
|
||||
_targetScale = UnhoverScale;
|
||||
}
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
_targetScale = UnhoverScale;
|
||||
}
|
||||
|
||||
public override void Disable()
|
||||
{
|
||||
_targetScale = Vector3.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74b910c8c3f34ee5bb44c0358f637ecc
|
||||
timeCreated: 1600274255
|
||||
@@ -0,0 +1,67 @@
|
||||
using HurricaneVR.Framework.ControllerInput;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to define center of mass of the controller relative to the hand for bonus throwing velocity calculations
|
||||
/// </summary>
|
||||
public class HVRThrowingCenterOfMass : MonoBehaviour
|
||||
{
|
||||
public HVRHandSide HandSide;
|
||||
public Transform Oculus;
|
||||
public Transform Vive;
|
||||
public Transform WMR;
|
||||
public Transform Knuckles;
|
||||
public Transform Fallback;
|
||||
|
||||
public Transform CenterOfMass;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (HandSide == HVRHandSide.Left)
|
||||
{
|
||||
if (HVRInputManager.Instance.LeftController)
|
||||
ControllerConnected(HVRInputManager.Instance.LeftController);
|
||||
HVRInputManager.Instance.LeftControllerConnected.AddListener(ControllerConnected);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HVRInputManager.Instance.RightController)
|
||||
ControllerConnected(HVRInputManager.Instance.RightController);
|
||||
HVRInputManager.Instance.RightControllerConnected.AddListener(ControllerConnected);
|
||||
}
|
||||
}
|
||||
|
||||
private void ControllerConnected(HVRController controller)
|
||||
{
|
||||
|
||||
switch (controller.ControllerType)
|
||||
{
|
||||
case HVRControllerType.Pico:
|
||||
case HVRControllerType.Oculus:
|
||||
CenterOfMass = Oculus;
|
||||
break;
|
||||
case HVRControllerType.ReverbG2:
|
||||
case HVRControllerType.WMR:
|
||||
CenterOfMass = WMR;
|
||||
break;
|
||||
case HVRControllerType.Vive:
|
||||
CenterOfMass = Vive;
|
||||
break;
|
||||
case HVRControllerType.Knuckles:
|
||||
CenterOfMass = Knuckles;
|
||||
break;
|
||||
default:
|
||||
CenterOfMass = Fallback;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!CenterOfMass)
|
||||
CenterOfMass = Fallback;
|
||||
if (!CenterOfMass)
|
||||
CenterOfMass = transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f52676b29554048a64664a7a53a126e
|
||||
timeCreated: 1601260700
|
||||
@@ -0,0 +1,77 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.Components
|
||||
{
|
||||
//Useful if this grabbable is a single handed grabbable attached to another.
|
||||
//If the other grabbable is grabbed this one will have it's two handed settings forced to be used
|
||||
|
||||
[RequireComponent(typeof(HVRGrabbable))]
|
||||
public class HVRTwoHandStrength : MonoBehaviour
|
||||
{
|
||||
public HVRGrabbable[] Others;
|
||||
|
||||
public HVRGrabbable Grabbable { get; private set; }
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Grabbable = GetComponent<HVRGrabbable>();
|
||||
|
||||
Grabbable.HandGrabbed.AddListener(OnHandGrabbed);
|
||||
Grabbable.HandReleased.AddListener(OnHandReleased);
|
||||
|
||||
if (Others != null)
|
||||
{
|
||||
foreach (var other in Others)
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
other.HandGrabbed.AddListener(OnOtherGrabbableHandGrabbed);
|
||||
other.HandReleased.AddListener(OnOtherGrabbableHandReleased);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHandReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
|
||||
{
|
||||
Grabbable.ForceTwoHandSettings = false;
|
||||
}
|
||||
|
||||
private void OnHandGrabbed(HVRHandGrabber arg0, HVRGrabbable arg1)
|
||||
{
|
||||
foreach (var other in Others)
|
||||
{
|
||||
if (other.HandGrabbers.Count > 0)
|
||||
{
|
||||
Grabbable.ForceTwoHandSettings = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnOtherGrabbableHandReleased(HVRHandGrabber arg0, HVRGrabbable g)
|
||||
{
|
||||
//handle scenario if two "others" are held, then one was released.
|
||||
var force = false;
|
||||
for (int i = 0; i < Others.Length; i++)
|
||||
{
|
||||
var other = Others[i];
|
||||
if (other == g || other.HandGrabbers.Count == 0)
|
||||
continue;
|
||||
|
||||
force = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!force)
|
||||
Grabbable.ForceTwoHandSettings = false;
|
||||
}
|
||||
|
||||
private void OnOtherGrabbableHandGrabbed(HVRHandGrabber arg0, HVRGrabbable arg1)
|
||||
{
|
||||
Grabbable.ForceTwoHandSettings = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a09a78d26498d0459d4d698c39e3a28
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0c3b4fd1ff88ab4ebcc76efa7ad486a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,472 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace HurricaneVR.Framework.ControllerInput
|
||||
{
|
||||
public class HVRControllerEvents : MonoBehaviour
|
||||
{
|
||||
public static HVRControllerEvents Instance { get; private set; }
|
||||
|
||||
public UnityEvent LeftGripActivated = new UnityEvent();
|
||||
public UnityEvent LeftGripDeactivated = new UnityEvent();
|
||||
public UnityEvent RightGripActivated = new UnityEvent();
|
||||
public UnityEvent RightGripDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftTriggerActivated = new UnityEvent();
|
||||
public UnityEvent LeftTriggerDeactivated = new UnityEvent();
|
||||
public UnityEvent RightTriggerActivated = new UnityEvent();
|
||||
public UnityEvent RightTriggerDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftPrimaryActivated = new UnityEvent();
|
||||
public UnityEvent LeftPrimaryDeactivated = new UnityEvent();
|
||||
public UnityEvent RightPrimaryActivated = new UnityEvent();
|
||||
public UnityEvent RightPrimaryDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftSecondaryActivated = new UnityEvent();
|
||||
public UnityEvent LeftSecondaryDeactivated = new UnityEvent();
|
||||
public UnityEvent RightSecondaryActivated = new UnityEvent();
|
||||
public UnityEvent RightSecondaryDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftMenuActivated = new UnityEvent();
|
||||
public UnityEvent LeftMenuDeactivated = new UnityEvent();
|
||||
public UnityEvent RightMenuActivated = new UnityEvent();
|
||||
public UnityEvent RightMenuDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftPrimaryTouchActivated = new UnityEvent();
|
||||
public UnityEvent LeftPrimaryTouchDeactivated = new UnityEvent();
|
||||
public UnityEvent RightPrimaryTouchActivated = new UnityEvent();
|
||||
public UnityEvent RightPrimaryTouchDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftSecondaryTouchActivated = new UnityEvent();
|
||||
public UnityEvent LeftSecondaryTouchDeactivated = new UnityEvent();
|
||||
public UnityEvent RightSecondaryTouchActivated = new UnityEvent();
|
||||
public UnityEvent RightSecondaryTouchDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftJoystickActivated = new UnityEvent();
|
||||
public UnityEvent LeftJoystickDeactivated = new UnityEvent();
|
||||
public UnityEvent RightJoystickActivated = new UnityEvent();
|
||||
public UnityEvent RightJoystickDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftTrackpadActivated = new UnityEvent();
|
||||
public UnityEvent LeftTrackpadDeactivated = new UnityEvent();
|
||||
public UnityEvent RightTrackpadActivated = new UnityEvent();
|
||||
public UnityEvent RightTrackpadDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftJoystickTouchActivated = new UnityEvent();
|
||||
public UnityEvent LeftJoystickTouchDeactivated = new UnityEvent();
|
||||
public UnityEvent RightJoystickTouchActivated = new UnityEvent();
|
||||
public UnityEvent RightJoystickTouchDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftTrackPadTouchActivated = new UnityEvent();
|
||||
public UnityEvent LeftTrackPadTouchDeactivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadTouchActivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadTouchDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftTriggerTouchActivated = new UnityEvent();
|
||||
public UnityEvent LeftTriggerTouchDeactivated = new UnityEvent();
|
||||
public UnityEvent RightTriggerTouchActivated = new UnityEvent();
|
||||
public UnityEvent RightTriggerTouchDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftThumbTouchActivated = new UnityEvent();
|
||||
public UnityEvent LeftThumbTouchDeactivated = new UnityEvent();
|
||||
public UnityEvent RightThumbTouchActivated = new UnityEvent();
|
||||
public UnityEvent RightThumbTouchDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftTrackPadUpActivated = new UnityEvent();
|
||||
public UnityEvent LeftTrackPadUpDeactivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadUpActivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadUpDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftTrackPadLeftActivated = new UnityEvent();
|
||||
public UnityEvent LeftTrackPadLeftDeactivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadLeftActivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadLeftDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftTrackPadRightActivated = new UnityEvent();
|
||||
public UnityEvent LeftTrackPadRightDeactivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadRightActivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadRightDeactivated = new UnityEvent();
|
||||
|
||||
public UnityEvent LeftTrackPadDownActivated = new UnityEvent();
|
||||
public UnityEvent LeftTrackPadDownDeactivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadDownActivated = new UnityEvent();
|
||||
public UnityEvent RightTrackPadDownDeactivated = new UnityEvent();
|
||||
|
||||
|
||||
|
||||
private HVRGlobalInputs _globalInputs;
|
||||
private bool _hasInputs;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (!Instance)
|
||||
{
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(this.gameObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(this);
|
||||
return;
|
||||
}
|
||||
|
||||
//testing...
|
||||
//LeftGripActivated.AddListener(() => { Debug.Log("LeftGripActivated"); });
|
||||
//LeftGripDeactivated.AddListener(() => { Debug.Log("LeftGripDeactivated"); });
|
||||
//RightGripActivated.AddListener(() => { Debug.Log("RightGripActivated"); });
|
||||
//RightGripDeactivated.AddListener(() => { Debug.Log("RightGripDeactivated"); });
|
||||
//LeftTriggerActivated.AddListener(() => { Debug.Log("LeftTriggerActivated"); });
|
||||
//LeftTriggerDeactivated.AddListener(() => { Debug.Log("LeftTriggerDeactivated"); });
|
||||
//RightTriggerActivated.AddListener(() => { Debug.Log("RightTriggerActivated"); });
|
||||
//RightTriggerDeactivated.AddListener(() => { Debug.Log("RightTriggerDeactivated"); });
|
||||
//LeftPrimaryActivated.AddListener(() => { Debug.Log("LeftPrimaryActivated"); });
|
||||
//LeftPrimaryDeactivated.AddListener(() => { Debug.Log("LeftPrimaryDeactivated"); });
|
||||
//RightPrimaryActivated.AddListener(() => { Debug.Log("RightPrimaryActivated"); });
|
||||
//RightPrimaryDeactivated.AddListener(() => { Debug.Log("RightPrimaryDeactivated"); });
|
||||
//LeftSecondaryActivated.AddListener(() => { Debug.Log("LeftSecondaryActivated"); });
|
||||
//LeftSecondaryDeactivated.AddListener(() => { Debug.Log("LeftSecondaryDeactivated"); });
|
||||
//RightSecondaryActivated.AddListener(() => { Debug.Log("RightSecondaryActivated"); });
|
||||
//RightSecondaryDeactivated.AddListener(() => { Debug.Log("RightSecondaryDeactivated"); });
|
||||
//LeftMenuActivated.AddListener(() => { Debug.Log("LeftMenuActivated"); });
|
||||
//LeftMenuDeactivated.AddListener(() => { Debug.Log("LeftMenuDeactivated"); });
|
||||
//RightMenuActivated.AddListener(() => { Debug.Log("RightMenuActivated"); });
|
||||
//RightMenuDeactivated.AddListener(() => { Debug.Log("RightMenuDeactivated"); });
|
||||
//LeftPrimaryTouchActivated.AddListener(() => { Debug.Log("LeftPrimaryTouchActivated"); });
|
||||
//LeftPrimaryTouchDeactivated.AddListener(() => { Debug.Log("LeftPrimaryTouchDeactivated"); });
|
||||
//RightPrimaryTouchActivated.AddListener(() => { Debug.Log("RightPrimaryTouchActivated"); });
|
||||
//RightPrimaryTouchDeactivated.AddListener(() => { Debug.Log("RightPrimaryTouchDeactivated"); });
|
||||
//LeftSecondaryTouchActivated.AddListener(() => { Debug.Log("LeftSecondaryTouchActivated"); });
|
||||
//LeftSecondaryTouchDeactivated.AddListener(() => { Debug.Log("LeftSecondaryTouchDeactivated"); });
|
||||
//RightSecondaryTouchActivated.AddListener(() => { Debug.Log("RightSecondaryTouchActivated"); });
|
||||
//RightSecondaryTouchDeactivated.AddListener(() => { Debug.Log("RightSecondaryTouchDeactivated"); });
|
||||
//LeftJoystickActivated.AddListener(() => { Debug.Log("LeftJoystickActivated"); });
|
||||
//LeftJoystickDeactivated.AddListener(() => { Debug.Log("LeftJoystickDeactivated"); });
|
||||
//RightJoystickActivated.AddListener(() => { Debug.Log("RightJoystickActivated"); });
|
||||
//RightJoystickDeactivated.AddListener(() => { Debug.Log("RightJoystickDeactivated"); });
|
||||
//LeftTrackpadActivated.AddListener(() => { Debug.Log("LeftTrackpadActivated"); });
|
||||
//LeftTrackpadDeactivated.AddListener(() => { Debug.Log("LeftTrackpadDeactivated"); });
|
||||
//RightTrackpadActivated.AddListener(() => { Debug.Log("RightTrackpadActivated"); });
|
||||
//RightTrackpadDeactivated.AddListener(() => { Debug.Log("RightTrackpadDeactivated"); });
|
||||
//LeftJoystickTouchActivated.AddListener(() => { Debug.Log("LeftJoystickTouchActivated"); });
|
||||
//LeftJoystickTouchDeactivated.AddListener(() => { Debug.Log("LeftJoystickTouchDeactivated"); });
|
||||
//RightJoystickTouchActivated.AddListener(() => { Debug.Log("RightJoystickTouchActivated"); });
|
||||
//RightJoystickTouchDeactivated.AddListener(() => { Debug.Log("RightJoystickTouchDeactivated"); });
|
||||
//LeftTrackPadTouchActivated.AddListener(() => { Debug.Log("LeftTrackPadTouchActivated"); });
|
||||
//LeftTrackPadTouchDeactivated.AddListener(() => { Debug.Log("LeftTrackPadTouchDeactivated"); });
|
||||
//RightTrackPadTouchActivated.AddListener(() => { Debug.Log("RightTrackPadTouchActivated"); });
|
||||
//RightTrackPadTouchDeactivated.AddListener(() => { Debug.Log("RightTrackPadTouchDeactivated"); });
|
||||
//LeftTriggerTouchActivated.AddListener(() => { Debug.Log("LeftTriggerTouchActivated"); });
|
||||
//LeftTriggerTouchDeactivated.AddListener(() => { Debug.Log("LeftTriggerTouchDeactivated"); });
|
||||
//RightTriggerTouchActivated.AddListener(() => { Debug.Log("RightTriggerTouchActivated"); });
|
||||
//RightTriggerTouchDeactivated.AddListener(() => { Debug.Log("RightTriggerTouchDeactivated"); });
|
||||
//LeftThumbTouchActivated.AddListener(() => { Debug.Log("LeftThumbTouchActivated"); });
|
||||
//LeftThumbTouchDeactivated.AddListener(() => { Debug.Log("LeftThumbTouchDeactivated"); });
|
||||
//RightThumbTouchActivated.AddListener(() => { Debug.Log("RightThumbTouchActivated"); });
|
||||
//RightThumbTouchDeactivated.AddListener(() => { Debug.Log("RightThumbTouchDeactivated"); });
|
||||
//LeftTrackPadUpActivated.AddListener(() => { Debug.Log("LeftTrackPadUpActivated"); });
|
||||
//LeftTrackPadUpDeactivated.AddListener(() => { Debug.Log("LeftTrackPadUpDeactivated"); });
|
||||
//RightTrackPadUpActivated.AddListener(() => { Debug.Log("RightTrackPadUpActivated"); });
|
||||
//RightTrackPadUpDeactivated.AddListener(() => { Debug.Log("RightTrackPadUpDeactivated"); });
|
||||
//LeftTrackPadLeftActivated.AddListener(() => { Debug.Log("LeftTrackPadLeftActivated"); });
|
||||
//LeftTrackPadLeftDeactivated.AddListener(() => { Debug.Log("LeftTrackPadLeftDeactivated"); });
|
||||
//RightTrackPadLeftActivated.AddListener(() => { Debug.Log("RightTrackPadLeftActivated"); });
|
||||
//RightTrackPadLeftDeactivated.AddListener(() => { Debug.Log("RightTrackPadLeftDeactivated"); });
|
||||
//LeftTrackPadRightActivated.AddListener(() => { Debug.Log("LeftTrackPadRightActivated"); });
|
||||
//LeftTrackPadRightDeactivated.AddListener(() => { Debug.Log("LeftTrackPadRightDeactivated"); });
|
||||
//RightTrackPadRightActivated.AddListener(() => { Debug.Log("RightTrackPadRightActivated"); });
|
||||
//RightTrackPadRightDeactivated.AddListener(() => { Debug.Log("RightTrackPadRightDeactivated"); });
|
||||
//LeftTrackPadDownActivated.AddListener(() => { Debug.Log("LeftTrackPadDownActivated"); });
|
||||
//LeftTrackPadDownDeactivated.AddListener(() => { Debug.Log("LeftTrackPadDownDeactivated"); });
|
||||
//RightTrackPadDownActivated.AddListener(() => { Debug.Log("RightTrackPadDownActivated"); });
|
||||
//RightTrackPadDownDeactivated.AddListener(() => { Debug.Log("RightTrackPadDownDeactivated"); });
|
||||
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_globalInputs = HVRGlobalInputs.Instance;
|
||||
_hasInputs = _globalInputs;
|
||||
}
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_hasInputs)
|
||||
return;
|
||||
|
||||
if (_globalInputs.LeftGripButtonState.JustActivated)
|
||||
{
|
||||
LeftGripActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftGripButtonState.JustDeactivated)
|
||||
{
|
||||
LeftGripDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightGripButtonState.JustActivated)
|
||||
{
|
||||
RightGripActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightGripButtonState.JustDeactivated)
|
||||
{
|
||||
RightGripDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftTriggerButtonState.JustActivated)
|
||||
{
|
||||
LeftTriggerActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftTriggerButtonState.JustDeactivated)
|
||||
{
|
||||
LeftTriggerDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightTriggerButtonState.JustActivated)
|
||||
{
|
||||
RightTriggerActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightTriggerButtonState.JustDeactivated)
|
||||
{
|
||||
RightTriggerDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftPrimaryButtonState.JustActivated)
|
||||
{
|
||||
LeftPrimaryActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftPrimaryButtonState.JustDeactivated)
|
||||
{
|
||||
LeftPrimaryDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightPrimaryButtonState.JustActivated)
|
||||
{
|
||||
RightPrimaryActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightPrimaryButtonState.JustDeactivated)
|
||||
{
|
||||
RightPrimaryDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftSecondaryButtonState.JustActivated)
|
||||
{
|
||||
LeftSecondaryActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftSecondaryButtonState.JustDeactivated)
|
||||
{
|
||||
LeftSecondaryDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightSecondaryButtonState.JustActivated)
|
||||
{
|
||||
RightSecondaryActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightSecondaryButtonState.JustDeactivated)
|
||||
{
|
||||
RightSecondaryDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftMenuButtonState.JustActivated)
|
||||
{
|
||||
LeftMenuActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftMenuButtonState.JustDeactivated)
|
||||
{
|
||||
LeftMenuDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightMenuButtonState.JustActivated)
|
||||
{
|
||||
RightMenuActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightMenuButtonState.JustDeactivated)
|
||||
{
|
||||
RightMenuDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftPrimaryTouchButtonState.JustActivated)
|
||||
{
|
||||
LeftPrimaryTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftPrimaryTouchButtonState.JustDeactivated)
|
||||
{
|
||||
LeftPrimaryTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightPrimaryTouchButtonState.JustActivated)
|
||||
{
|
||||
RightPrimaryTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightPrimaryTouchButtonState.JustDeactivated)
|
||||
{
|
||||
RightPrimaryTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftSecondaryTouchButtonState.JustActivated)
|
||||
{
|
||||
LeftSecondaryTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftSecondaryTouchButtonState.JustDeactivated)
|
||||
{
|
||||
LeftSecondaryTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightSecondaryTouchButtonState.JustActivated)
|
||||
{
|
||||
RightSecondaryTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightSecondaryTouchButtonState.JustDeactivated)
|
||||
{
|
||||
RightSecondaryTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftJoystickButtonState.JustActivated)
|
||||
{
|
||||
LeftJoystickActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftJoystickButtonState.JustDeactivated)
|
||||
{
|
||||
LeftJoystickDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightJoystickButtonState.JustActivated)
|
||||
{
|
||||
RightJoystickActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightJoystickButtonState.JustDeactivated)
|
||||
{
|
||||
RightJoystickDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftTrackpadButtonState.JustActivated)
|
||||
{
|
||||
LeftTrackpadActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftTrackpadButtonState.JustDeactivated)
|
||||
{
|
||||
LeftTrackpadDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightTrackpadButtonState.JustActivated)
|
||||
{
|
||||
RightTrackpadActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightTrackpadButtonState.JustDeactivated)
|
||||
{
|
||||
RightTrackpadDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftJoystickTouchState.JustActivated)
|
||||
{
|
||||
LeftJoystickTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftJoystickTouchState.JustDeactivated)
|
||||
{
|
||||
LeftJoystickTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightJoystickTouchState.JustActivated)
|
||||
{
|
||||
RightJoystickTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightJoystickTouchState.JustDeactivated)
|
||||
{
|
||||
RightJoystickTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftTrackPadTouchState.JustActivated)
|
||||
{
|
||||
LeftTrackPadTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftTrackPadTouchState.JustDeactivated)
|
||||
{
|
||||
LeftTrackPadTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightTrackPadTouchState.JustActivated)
|
||||
{
|
||||
RightTrackPadTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightTrackPadTouchState.JustDeactivated)
|
||||
{
|
||||
RightTrackPadTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftTriggerTouchState.JustActivated)
|
||||
{
|
||||
LeftTriggerTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftTriggerTouchState.JustDeactivated)
|
||||
{
|
||||
LeftTriggerTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightTriggerTouchState.JustActivated)
|
||||
{
|
||||
RightTriggerTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightTriggerTouchState.JustDeactivated)
|
||||
{
|
||||
RightTriggerTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftThumbTouchState.JustActivated)
|
||||
{
|
||||
LeftThumbTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftThumbTouchState.JustDeactivated)
|
||||
{
|
||||
LeftThumbTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightThumbTouchState.JustActivated)
|
||||
{
|
||||
RightThumbTouchActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightThumbTouchState.JustDeactivated)
|
||||
{
|
||||
RightThumbTouchDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftTrackPadUp.JustActivated)
|
||||
{
|
||||
LeftTrackPadUpActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftTrackPadUp.JustDeactivated)
|
||||
{
|
||||
LeftTrackPadUpDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightTrackPadUp.JustActivated)
|
||||
{
|
||||
RightTrackPadUpActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightTrackPadUp.JustDeactivated)
|
||||
{
|
||||
RightTrackPadUpDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftTrackPadLeft.JustActivated)
|
||||
{
|
||||
LeftTrackPadLeftActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftTrackPadLeft.JustDeactivated)
|
||||
{
|
||||
LeftTrackPadLeftDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightTrackPadLeft.JustActivated)
|
||||
{
|
||||
RightTrackPadLeftActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightTrackPadLeft.JustDeactivated)
|
||||
{
|
||||
RightTrackPadLeftDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftTrackPadRight.JustActivated)
|
||||
{
|
||||
LeftTrackPadRightActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftTrackPadRight.JustDeactivated)
|
||||
{
|
||||
LeftTrackPadRightDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightTrackPadRight.JustActivated)
|
||||
{
|
||||
RightTrackPadRightActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightTrackPadRight.JustDeactivated)
|
||||
{
|
||||
RightTrackPadRightDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.LeftTrackPadDown.JustActivated)
|
||||
{
|
||||
LeftTrackPadDownActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.LeftTrackPadDown.JustDeactivated)
|
||||
{
|
||||
LeftTrackPadDownDeactivated.Invoke();
|
||||
}
|
||||
if (_globalInputs.RightTrackPadDown.JustActivated)
|
||||
{
|
||||
RightTrackPadDownActivated.Invoke();
|
||||
}
|
||||
else if (_globalInputs.RightTrackPadDown.JustDeactivated)
|
||||
{
|
||||
RightTrackPadDownDeactivated.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd07f8606d5a2184ca2bab0e57b64ef7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,147 @@
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.ControllerInput
|
||||
{
|
||||
public class HVRGlobalInputs : MonoBehaviour
|
||||
{
|
||||
public static HVRGlobalInputs Instance { get; private set; }
|
||||
|
||||
public float LeftTrigger;
|
||||
public float LeftGrip;
|
||||
public float RightTrigger;
|
||||
public float RightGrip;
|
||||
|
||||
public Vector2 LeftJoystickAxis;
|
||||
public Vector2 LeftTrackpadAxis;
|
||||
|
||||
public Vector2 RightJoystickAxis;
|
||||
public Vector2 RightTrackpadAxis;
|
||||
|
||||
public HVRButtonState LeftGripButtonState;
|
||||
public HVRButtonState LeftTriggerButtonState;
|
||||
public HVRButtonState LeftPrimaryButtonState;
|
||||
public HVRButtonState LeftSecondaryButtonState;
|
||||
public HVRButtonState LeftMenuButtonState;
|
||||
public HVRButtonState LeftPrimaryTouchButtonState;
|
||||
public HVRButtonState LeftSecondaryTouchButtonState;
|
||||
public HVRButtonState LeftJoystickButtonState;
|
||||
public HVRButtonState LeftTrackpadButtonState;
|
||||
|
||||
public HVRButtonState LeftJoystickTouchState;
|
||||
public HVRButtonState LeftTrackPadTouchState;
|
||||
public HVRButtonState LeftTriggerTouchState;
|
||||
public HVRButtonState LeftThumbTouchState;
|
||||
|
||||
public HVRButtonState LeftTriggerNearTouchState;
|
||||
public HVRButtonState LeftThumbNearTouchState;
|
||||
|
||||
public HVRButtonState LeftTrackPadUp;
|
||||
public HVRButtonState LeftTrackPadLeft;
|
||||
public HVRButtonState LeftTrackPadRight;
|
||||
public HVRButtonState LeftTrackPadDown;
|
||||
|
||||
|
||||
public HVRButtonState RightGripButtonState;
|
||||
public HVRButtonState RightTriggerButtonState;
|
||||
public HVRButtonState RightPrimaryButtonState;
|
||||
public HVRButtonState RightSecondaryButtonState;
|
||||
public HVRButtonState RightMenuButtonState;
|
||||
public HVRButtonState RightPrimaryTouchButtonState;
|
||||
public HVRButtonState RightSecondaryTouchButtonState;
|
||||
public HVRButtonState RightJoystickButtonState;
|
||||
public HVRButtonState RightTrackpadButtonState;
|
||||
|
||||
public HVRButtonState RightJoystickTouchState;
|
||||
public HVRButtonState RightTrackPadTouchState;
|
||||
public HVRButtonState RightTriggerTouchState;
|
||||
public HVRButtonState RightThumbTouchState;
|
||||
|
||||
public HVRButtonState RightTriggerNearTouchState;
|
||||
public HVRButtonState RightThumbNearTouchState;
|
||||
|
||||
public HVRButtonState RightTrackPadUp;
|
||||
public HVRButtonState RightTrackPadLeft;
|
||||
public HVRButtonState RightTrackPadRight;
|
||||
public HVRButtonState RightTrackPadDown;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (!Instance)
|
||||
{
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(this.gameObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var controller = HVRInputManager.Instance.LeftController;
|
||||
LeftTrigger = controller.Trigger;
|
||||
LeftGrip = controller.Grip;
|
||||
|
||||
LeftJoystickAxis = controller.JoystickAxis;
|
||||
LeftTrackpadAxis = controller.TrackpadAxis;
|
||||
|
||||
LeftGripButtonState = controller.GripButtonState;
|
||||
LeftTriggerButtonState = controller.TriggerButtonState;
|
||||
LeftPrimaryButtonState = controller.PrimaryButtonState;
|
||||
LeftSecondaryButtonState = controller.SecondaryButtonState;
|
||||
LeftMenuButtonState = controller.MenuButtonState;
|
||||
LeftPrimaryTouchButtonState = controller.PrimaryTouchButtonState;
|
||||
LeftSecondaryTouchButtonState = controller.SecondaryTouchButtonState;
|
||||
LeftJoystickButtonState = controller.JoystickButtonState;
|
||||
LeftTrackpadButtonState = controller.TrackpadButtonState;
|
||||
|
||||
LeftJoystickTouchState = controller.JoystickTouchState;
|
||||
LeftTrackPadTouchState = controller.TrackPadTouchState;
|
||||
LeftTriggerTouchState = controller.TriggerTouchState;
|
||||
LeftThumbTouchState = controller.ThumbTouchState;
|
||||
|
||||
LeftTriggerNearTouchState = controller.TriggerNearTouchState;
|
||||
LeftThumbNearTouchState = controller.ThumbNearTouchState;
|
||||
|
||||
LeftTrackPadUp = controller.TrackPadUp;
|
||||
LeftTrackPadLeft = controller.TrackPadLeft;
|
||||
LeftTrackPadRight = controller.TrackPadRight;
|
||||
LeftTrackPadDown = controller.TrackPadDown;
|
||||
|
||||
controller = HVRInputManager.Instance.RightController;
|
||||
|
||||
RightTrigger = controller.Trigger;
|
||||
RightGrip = controller.Grip;
|
||||
|
||||
RightJoystickAxis = controller.JoystickAxis;
|
||||
RightTrackpadAxis = controller.TrackpadAxis;
|
||||
|
||||
RightGripButtonState = controller.GripButtonState;
|
||||
RightTriggerButtonState = controller.TriggerButtonState;
|
||||
RightPrimaryButtonState = controller.PrimaryButtonState;
|
||||
RightSecondaryButtonState = controller.SecondaryButtonState;
|
||||
RightMenuButtonState = controller.MenuButtonState;
|
||||
RightPrimaryTouchButtonState = controller.PrimaryTouchButtonState;
|
||||
RightSecondaryTouchButtonState = controller.SecondaryTouchButtonState;
|
||||
RightJoystickButtonState = controller.JoystickButtonState;
|
||||
RightTrackpadButtonState = controller.TrackpadButtonState;
|
||||
|
||||
RightJoystickTouchState = controller.JoystickTouchState;
|
||||
RightTrackPadTouchState = controller.TrackPadTouchState;
|
||||
RightTriggerTouchState = controller.TriggerTouchState;
|
||||
RightThumbTouchState = controller.ThumbTouchState;
|
||||
|
||||
RightTriggerNearTouchState = controller.TriggerNearTouchState;
|
||||
RightThumbNearTouchState = controller.ThumbNearTouchState;
|
||||
|
||||
RightTrackPadUp = controller.TrackPadUp;
|
||||
RightTrackPadLeft = controller.TrackPadLeft;
|
||||
RightTrackPadRight = controller.TrackPadRight;
|
||||
RightTrackPadDown = controller.TrackPadDown;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4cbdb3f5a90abf442b512b58ce932e71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Core.Grabbers;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.ControllerInput
|
||||
{
|
||||
[RequireComponent(typeof(HVRGrabbable))]
|
||||
public abstract class HVRInputAction : MonoBehaviour
|
||||
{
|
||||
public HVRGrabbable Grabbable { get; private set; }
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Grabbable = GetComponent<HVRGrabbable>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
for (var i = 0; i < Grabbable.HandGrabbers.Count; i++)
|
||||
{
|
||||
var hand = Grabbable.HandGrabbers[i];
|
||||
var controller = HVRInputManager.Instance.GetController(hand.HandSide);
|
||||
CheckInput(controller);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void CheckInput(HVRController controller);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a934dfe7ddf4fb2a1ec98943c4bcd57
|
||||
timeCreated: 1604448529
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94e2703aa70f47be808cc7d516fced77
|
||||
timeCreated: 1600342873
|
||||
@@ -0,0 +1,167 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using HurricaneVR.Framework.Core;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
#if USING_OPENXR
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
#endif
|
||||
|
||||
namespace HurricaneVR.Framework.ControllerInput
|
||||
{
|
||||
|
||||
public class HVRInputSystemController : HVRController
|
||||
{
|
||||
public static HVRInputActions InputActions = null;
|
||||
private InputDevice _inputDevice;
|
||||
|
||||
public bool IsOpenXR;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
static void Cleanup()
|
||||
{
|
||||
if (InputActions != null)
|
||||
{
|
||||
InputActions.Disable();
|
||||
InputActions.Dispose();
|
||||
InputActions = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
if (InputActions == null)
|
||||
{
|
||||
InputActions = new HVRInputActions();
|
||||
InputActions.Enable();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
Init();
|
||||
|
||||
UnityEngine.InputSystem.InputSystem.onDeviceChange += OnDeviceChanged;
|
||||
}
|
||||
|
||||
private void OnDeviceChanged(InputDevice device, InputDeviceChange change)
|
||||
{
|
||||
if (change == InputDeviceChange.Added)
|
||||
{
|
||||
if (device.usages.Contains(CommonUsages.LeftHand) && Side == HVRHandSide.Left || device.usages.Contains(CommonUsages.RightHand) && Side == HVRHandSide.Right)
|
||||
{
|
||||
_inputDevice = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateInput()
|
||||
{
|
||||
if (Side == HVRHandSide.Left)
|
||||
{
|
||||
JoystickAxis = InputActions.LeftHand.Primary2DAxis.ReadValue<Vector2>();
|
||||
|
||||
SetBool(out JoystickClicked, InputActions.LeftHand.Primary2DAxisClick);
|
||||
SetBool(out TrackPadClicked, InputActions.LeftHand.Secondary2DAxisClick);
|
||||
|
||||
TrackpadAxis = InputActions.LeftHand.Secondary2DAxis.ReadValue<Vector2>();
|
||||
|
||||
Grip = InputActions.LeftHand.Grip.ReadValue<float>();
|
||||
GripForce = InputActions.LeftHand.GripForce.ReadValue<float>();
|
||||
Trigger = InputActions.LeftHand.Trigger.ReadValue<float>();
|
||||
|
||||
SetBool(out PrimaryButton, InputActions.LeftHand.PrimaryButton);
|
||||
SetBool(out SecondaryButton, InputActions.LeftHand.SecondaryButton);
|
||||
|
||||
SetBool(out PrimaryTouch, InputActions.LeftHand.PrimaryTouch);
|
||||
SetBool(out SecondaryTouch, InputActions.LeftHand.SecondaryTouch);
|
||||
|
||||
SetBool(out JoystickTouch, InputActions.LeftHand.Primary2DAxisTouch);
|
||||
SetBool(out TrackPadTouch, InputActions.LeftHand.Secondary2DAxisTouch);
|
||||
|
||||
SetBool(out TriggerTouch, InputActions.LeftHand.TriggerTouch);
|
||||
|
||||
SetBool(out MenuButton, InputActions.LeftHand.Menu);
|
||||
|
||||
SetBool(out GripButton, InputActions.LeftHand.GripPress);
|
||||
SetBool(out TriggerButton, InputActions.LeftHand.TriggerPress);
|
||||
}
|
||||
else
|
||||
{
|
||||
JoystickAxis = InputActions.RightHand.Primary2DAxis.ReadValue<Vector2>();
|
||||
|
||||
SetBool(out JoystickClicked, InputActions.RightHand.Primary2DAxisClick);
|
||||
SetBool(out TrackPadClicked, InputActions.RightHand.Secondary2DAxisClick);
|
||||
|
||||
TrackpadAxis = InputActions.RightHand.Secondary2DAxis.ReadValue<Vector2>();
|
||||
|
||||
Grip = InputActions.RightHand.Grip.ReadValue<float>();
|
||||
GripForce = InputActions.RightHand.GripForce.ReadValue<float>();
|
||||
Trigger = InputActions.RightHand.Trigger.ReadValue<float>();
|
||||
|
||||
SetBool(out PrimaryButton, InputActions.RightHand.PrimaryButton);
|
||||
SetBool(out SecondaryButton, InputActions.RightHand.SecondaryButton);
|
||||
|
||||
SetBool(out PrimaryTouch, InputActions.RightHand.PrimaryTouch);
|
||||
SetBool(out SecondaryTouch, InputActions.RightHand.SecondaryTouch);
|
||||
|
||||
SetBool(out JoystickTouch, InputActions.RightHand.Primary2DAxisTouch);
|
||||
SetBool(out TrackPadTouch, InputActions.RightHand.Secondary2DAxisTouch);
|
||||
|
||||
SetBool(out TriggerTouch, InputActions.RightHand.TriggerTouch);
|
||||
|
||||
SetBool(out MenuButton, InputActions.RightHand.Menu);
|
||||
|
||||
SetBool(out GripButton, InputActions.RightHand.GripPress);
|
||||
SetBool(out TriggerButton, InputActions.RightHand.TriggerPress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SetBool(out bool val, InputAction action)
|
||||
{
|
||||
val = false;
|
||||
if (action.activeControl != null)
|
||||
{
|
||||
var type = action.activeControl.valueType;
|
||||
if (type == typeof(bool))
|
||||
{
|
||||
val = action.ReadValue<bool>();
|
||||
}
|
||||
else if (type == typeof(float))
|
||||
{
|
||||
val = action.ReadValue<float>() > .5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Vibrate(float amplitude, float duration = 1, float frequency = 1)
|
||||
{
|
||||
if (HVRSettings.Instance.DisableHaptics) return;
|
||||
|
||||
#if USING_OPENXR
|
||||
|
||||
if (IsOpenXR)
|
||||
{
|
||||
var action = Side == HVRHandSide.Left ? InputActions.LeftHand.Haptics : InputActions.RightHand.Haptics;
|
||||
|
||||
if (action != null && _inputDevice != null)
|
||||
{
|
||||
OpenXRInput.SendHapticImpulse(action, amplitude, frequency, duration, _inputDevice);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
base.Vibrate(amplitude, duration, frequency);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e9db12adedf02d4797c05ee5c7cbacb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,112 @@
|
||||
#if USING_XRHANDS
|
||||
using System.Collections.Generic;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.Hands;
|
||||
|
||||
#endif
|
||||
|
||||
namespace HurricaneVR.Framework.ControllerInput
|
||||
{
|
||||
public static class HVROpenXRFingerCurls
|
||||
{
|
||||
#if USING_XRHANDS
|
||||
private static float minCurl = 0.15f;
|
||||
private static float maxCurl = 0.9f;
|
||||
|
||||
private static XRHandSubsystem system;
|
||||
private static readonly List<XRHandSubsystem> systems = new List<XRHandSubsystem>();
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
if (system == null || !system.running)
|
||||
{
|
||||
SubsystemManager.GetSubsystems(systems);
|
||||
for (var i = 0; i < systems.Count; ++i)
|
||||
{
|
||||
var handSubsystem = systems[i];
|
||||
if (handSubsystem.running)
|
||||
{
|
||||
system = handSubsystem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetCurls(HVRHandSide handSide, float[] curls)
|
||||
{
|
||||
if (system == null || !system.running)
|
||||
return false;
|
||||
|
||||
XRHand hand = default;
|
||||
|
||||
if (handSide == HVRHandSide.Left)
|
||||
{
|
||||
hand = system.leftHand;
|
||||
}
|
||||
else
|
||||
{
|
||||
hand = system.rightHand;
|
||||
}
|
||||
|
||||
return hand.isTracked && TryCalculateFingerCurvatures(hand, curls);
|
||||
}
|
||||
|
||||
static bool TryCalculateFingerCurvatures(XRHand hand, float[] curls)
|
||||
{
|
||||
Handedness handedness = hand.handedness;
|
||||
|
||||
if (!TryCalculateFingerCurvature(hand, handedness, XRHandJointID.ThumbMetacarpal, XRHandJointID.ThumbProximal, XRHandJointID.ThumbDistal, XRHandJointID.ThumbTip, out curls[0]))
|
||||
return false;
|
||||
if (!TryCalculateFingerCurvature(hand, handedness, XRHandJointID.IndexMetacarpal, XRHandJointID.IndexProximal, XRHandJointID.IndexIntermediate, XRHandJointID.IndexDistal, out curls[1]))
|
||||
return false;
|
||||
if (!TryCalculateFingerCurvature(hand, handedness, XRHandJointID.MiddleMetacarpal, XRHandJointID.MiddleProximal, XRHandJointID.MiddleIntermediate, XRHandJointID.MiddleDistal, out curls[2]))
|
||||
return false;
|
||||
if (!TryCalculateFingerCurvature(hand, handedness, XRHandJointID.RingMetacarpal, XRHandJointID.RingProximal, XRHandJointID.RingIntermediate, XRHandJointID.RingDistal, out curls[3]))
|
||||
return false;
|
||||
if (!TryCalculateFingerCurvature(hand, handedness, XRHandJointID.LittleMetacarpal, XRHandJointID.LittleProximal, XRHandJointID.LittleIntermediate, XRHandJointID.LittleDistal, out curls[4]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TryCalculateFingerCurvature(XRHand hand, Handedness handName, XRHandJointID metacarpalId, XRHandJointID proximalId, XRHandJointID intermediateId, XRHandJointID distalId, out float curl)
|
||||
{
|
||||
var metacarpalJoint = hand.GetJoint(metacarpalId);
|
||||
var proximalJoint = hand.GetJoint(proximalId);
|
||||
var intermediateJoint = hand.GetJoint(intermediateId);
|
||||
var distalJoint = hand.GetJoint(distalId);
|
||||
|
||||
if (metacarpalJoint.TryGetPose(out Pose metacarpalPose) &&
|
||||
proximalJoint.TryGetPose(out Pose proximalPose) &&
|
||||
intermediateJoint.TryGetPose(out Pose intermediatePose) &&
|
||||
distalJoint.TryGetPose(out Pose distalPose))
|
||||
{
|
||||
float curvature = CalculateCurvature(metacarpalPose, proximalPose, intermediatePose, distalPose);
|
||||
float remappedCurvature = Remap(curvature, minCurl, maxCurl, 0f, 1f);
|
||||
curl = remappedCurvature;
|
||||
return true;
|
||||
}
|
||||
|
||||
curl = 0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
static float CalculateCurvature(Pose metacarpal, Pose proximal, Pose intermediate, Pose distal)
|
||||
{
|
||||
float angle1 = Vector3.Angle(metacarpal.position - proximal.position, proximal.position - intermediate.position);
|
||||
float angle2 = Vector3.Angle(proximal.position - intermediate.position, intermediate.position - distal.position);
|
||||
float normalizedAngle = (angle1 + angle2) / 180.0f; // 180 degrees being the max angle (fully extended)
|
||||
return Mathf.Clamp01(normalizedAngle);
|
||||
}
|
||||
|
||||
static float Remap(float value, float from1, float to1, float from2, float to2)
|
||||
{
|
||||
value = Mathf.Clamp(value, minCurl, maxCurl);
|
||||
return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7033fdbdef534aeaaad3c868224922db
|
||||
timeCreated: 1718677714
|
||||
@@ -0,0 +1,501 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace HurricaneVR.Framework.ControllerInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the player controller, teleporter, and hand grabbing systems to drive their actions.
|
||||
/// Subclass and override the virtual methods if you wish to customize inputs per device.
|
||||
/// </summary>
|
||||
public class HVRPlayerInputs : MonoBehaviour
|
||||
{
|
||||
[Header("Grab Settings")]
|
||||
public bool CanDistanceGrab = true;
|
||||
|
||||
public bool CanTriggerGrab;
|
||||
|
||||
[Tooltip("For non flick style force grabber")]
|
||||
public HVRForceGrabActivation ForceGrabActivation = HVRForceGrabActivation.Grip;
|
||||
|
||||
[Range(0f, 1f)]
|
||||
public float TriggerGrabThreshold = .7f;
|
||||
|
||||
[Header("Inputs Debugging")]
|
||||
public Vector2 MovementAxis;
|
||||
|
||||
public Vector2 TurnAxis;
|
||||
|
||||
public bool IsTeleportActivated;
|
||||
public bool IsTeleportDeactivated;
|
||||
|
||||
public bool IsSprintingActivated;
|
||||
public bool SprintRequiresDoubleClick;
|
||||
|
||||
public bool IsCrouchActivated;
|
||||
public bool IsStandActivated;
|
||||
|
||||
public HVRButtonState JumpState;
|
||||
public HVRButtonState CrouchState;
|
||||
public HVRButtonState StandState;
|
||||
|
||||
public HVRButtonState LeftTriggerGrabState;
|
||||
public HVRButtonState RightTriggerGrabState;
|
||||
|
||||
public bool IsLeftGrabActivated;
|
||||
public bool IsLeftHoldActive;
|
||||
public bool IsLeftGripHoldActive;
|
||||
public bool IsLeftTriggerHoldActive;
|
||||
|
||||
public bool IsRightGrabActivated;
|
||||
public bool IsRightHoldActive;
|
||||
public bool IsRightGripHoldActive;
|
||||
public bool IsRightTriggerHoldActive;
|
||||
|
||||
public bool IsLeftForceGrabActive;
|
||||
public bool IsRightForceGrabActive;
|
||||
|
||||
public bool IsLeftForceGrabActivated;
|
||||
public bool IsRightForceGrabActivated;
|
||||
|
||||
public bool IsJumpActivated;
|
||||
|
||||
public HVRHandSide TeleportHandSide = HVRHandSide.Right;
|
||||
public bool SwapMovementAxis;
|
||||
|
||||
|
||||
[Header("Debugging")]
|
||||
public bool UseWASD;
|
||||
|
||||
public bool IsMouseDown;
|
||||
public Vector2 MouseAxis;
|
||||
|
||||
public bool UpdateInputs { get; set; } = true;
|
||||
|
||||
public HVRController RightController => HVRInputManager.Instance.RightController;
|
||||
public HVRController LeftController => HVRInputManager.Instance.LeftController;
|
||||
|
||||
public HVRControllerType RightControllerType => RightController.ControllerType;
|
||||
public HVRControllerType LeftControllerType => LeftController.ControllerType;
|
||||
|
||||
public HVRController TeleportController => TeleportHandSide == HVRHandSide.Left ? HVRInputManager.Instance.LeftController : HVRInputManager.Instance.RightController;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
UpdateInput();
|
||||
AfterInputUpdate();
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected virtual void UpdateInput()
|
||||
{
|
||||
if (!UpdateInputs)
|
||||
return;
|
||||
|
||||
ResetState(ref LeftTriggerGrabState);
|
||||
ResetState(ref RightTriggerGrabState);
|
||||
SetState(ref LeftTriggerGrabState, LeftController.Trigger > TriggerGrabThreshold);
|
||||
SetState(ref RightTriggerGrabState, RightController.Trigger > TriggerGrabThreshold);
|
||||
|
||||
MovementAxis = GetMovementAxis();
|
||||
TurnAxis = GetTurnAxis();
|
||||
IsTeleportActivated = GetTeleportActivated();
|
||||
IsTeleportDeactivated = GetTeleportDeactivated();
|
||||
IsSprintingActivated = GetSprinting();
|
||||
|
||||
IsCrouchActivated = GetCrouch();
|
||||
|
||||
IsLeftGrabActivated = GetIsLeftGrabActivated();
|
||||
IsLeftHoldActive = GetIsLeftHoldActive();
|
||||
|
||||
IsRightGrabActivated = GetIsRightGrabActivated();
|
||||
IsRightHoldActive = GetIsRightHoldActive();
|
||||
|
||||
GetForceGrabActivated(out IsLeftForceGrabActivated, out IsRightForceGrabActivated);
|
||||
GetForceGrabActive(out IsLeftForceGrabActive, out IsRightForceGrabActive);
|
||||
|
||||
IsJumpActivated = GetIsJumpActivated();
|
||||
IsStandActivated = GetStand();
|
||||
MouseAxis = GetMouse(out IsMouseDown);
|
||||
|
||||
ResetState(ref CrouchState);
|
||||
ResetState(ref StandState);
|
||||
ResetState(ref JumpState);
|
||||
|
||||
SetState(ref CrouchState, IsCrouchActivated);
|
||||
SetState(ref StandState, IsStandActivated);
|
||||
SetState(ref JumpState, IsJumpActivated);
|
||||
}
|
||||
|
||||
protected virtual void AfterInputUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected void ResetState(ref HVRButtonState buttonState)
|
||||
{
|
||||
buttonState.JustDeactivated = false;
|
||||
buttonState.JustActivated = false;
|
||||
buttonState.Value = 0f;
|
||||
}
|
||||
|
||||
protected void SetState(ref HVRButtonState buttonState, bool pressed)
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
if (!buttonState.Active)
|
||||
{
|
||||
buttonState.JustActivated = true;
|
||||
buttonState.Active = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buttonState.Active)
|
||||
{
|
||||
buttonState.Active = false;
|
||||
buttonState.JustDeactivated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected virtual bool GetStand()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual bool GetIsJumpActivated()
|
||||
{
|
||||
if (RightController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
return false; //todo
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void GetForceGrabActivated(out bool left, out bool right)
|
||||
{
|
||||
left = false;
|
||||
right = false;
|
||||
|
||||
if (!CanDistanceGrab)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ForceGrabActivation == HVRForceGrabActivation.Grip)
|
||||
{
|
||||
left = LeftController.GripButtonState.JustActivated;
|
||||
right = RightController.GripButtonState.JustActivated;
|
||||
}
|
||||
else if (ForceGrabActivation == HVRForceGrabActivation.GripAndTrigger)
|
||||
{
|
||||
left = LeftController.GripButtonState.Active && LeftTriggerGrabState.JustActivated || LeftTriggerGrabState.Active && LeftController.GripButtonState.JustActivated;
|
||||
right = RightController.GripButtonState.Active && RightTriggerGrabState.JustActivated || RightTriggerGrabState.Active && RightController.GripButtonState.JustActivated;
|
||||
}
|
||||
else if (ForceGrabActivation == HVRForceGrabActivation.Trigger)
|
||||
{
|
||||
left = LeftTriggerGrabState.JustActivated;
|
||||
right = RightTriggerGrabState.JustActivated;
|
||||
}
|
||||
else if (ForceGrabActivation == HVRForceGrabActivation.GripOrTrigger)
|
||||
{
|
||||
left = LeftController.GripButtonState.JustActivated || LeftTriggerGrabState.JustActivated;
|
||||
right = RightController.GripButtonState.JustActivated || RightTriggerGrabState.JustActivated;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected virtual void GetForceGrabActive(out bool left, out bool right)
|
||||
{
|
||||
left = false;
|
||||
right = false;
|
||||
|
||||
if (!CanDistanceGrab)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ForceGrabActivation == HVRForceGrabActivation.Grip)
|
||||
{
|
||||
left = LeftController.GripButtonState.Active;
|
||||
right = RightController.GripButtonState.Active;
|
||||
}
|
||||
else if (ForceGrabActivation == HVRForceGrabActivation.GripAndTrigger || ForceGrabActivation == HVRForceGrabActivation.GripOrTrigger)
|
||||
{
|
||||
left = LeftController.GripButtonState.Active || LeftTriggerGrabState.Active;
|
||||
right = RightController.GripButtonState.Active || RightTriggerGrabState.Active;
|
||||
}
|
||||
else if (ForceGrabActivation == HVRForceGrabActivation.Trigger)
|
||||
{
|
||||
left = LeftTriggerGrabState.Active;
|
||||
right = RightTriggerGrabState.Active;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public bool GetForceGrabActivated(HVRHandSide side)
|
||||
{
|
||||
if (!CanDistanceGrab)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return side == HVRHandSide.Left ? IsLeftForceGrabActivated : IsRightForceGrabActivated;
|
||||
}
|
||||
|
||||
public bool GetForceGrabActive(HVRHandSide side)
|
||||
{
|
||||
if (!CanDistanceGrab)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return side == HVRHandSide.Left ? IsLeftForceGrabActive : IsRightForceGrabActive;
|
||||
}
|
||||
|
||||
public bool GetGrabActivated(HVRHandSide side)
|
||||
{
|
||||
return side == HVRHandSide.Left ? IsLeftGrabActivated : IsRightGrabActivated;
|
||||
}
|
||||
|
||||
public bool GetGripHoldActive(HVRHandSide side)
|
||||
{
|
||||
return side == HVRHandSide.Left ? IsLeftGripHoldActive : IsRightGripHoldActive;
|
||||
}
|
||||
|
||||
public HVRButtonState GetTriggerGrabState(HVRHandSide side)
|
||||
{
|
||||
return side == HVRHandSide.Left ? LeftTriggerGrabState : RightTriggerGrabState;
|
||||
}
|
||||
|
||||
protected virtual bool GetIsLeftGrabActivated()
|
||||
{
|
||||
return LeftController.GripButtonState.JustActivated;
|
||||
}
|
||||
|
||||
|
||||
protected virtual bool GetIsLeftHoldActive()
|
||||
{
|
||||
IsLeftTriggerHoldActive = LeftController.Trigger > TriggerGrabThreshold;
|
||||
IsLeftGripHoldActive = LeftController.GripButtonState.Active;
|
||||
if (CanTriggerGrab && IsLeftTriggerHoldActive)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return LeftController.GripButtonState.Active;
|
||||
}
|
||||
|
||||
protected virtual bool GetIsRightGrabActivated()
|
||||
{
|
||||
return RightController.GripButtonState.JustActivated;
|
||||
}
|
||||
|
||||
|
||||
protected virtual bool GetIsRightHoldActive()
|
||||
{
|
||||
IsRightTriggerHoldActive = RightController.Trigger > TriggerGrabThreshold;
|
||||
IsRightGripHoldActive = RightController.GripButtonState.Active;
|
||||
if (CanTriggerGrab && IsRightTriggerHoldActive)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return RightController.GripButtonState.Active;
|
||||
}
|
||||
|
||||
protected virtual Vector2 GetMovementAxis()
|
||||
{
|
||||
if (UseWASD)
|
||||
{
|
||||
var wasd = CheckWASD();
|
||||
if (wasd.sqrMagnitude > 0f)
|
||||
return wasd;
|
||||
}
|
||||
|
||||
if (SwapMovementAxis)
|
||||
{
|
||||
if (RightController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
if (RightController.TrackpadButtonState.Active)
|
||||
return RightController.TrackpadAxis;
|
||||
return Vector2.zero;
|
||||
}
|
||||
|
||||
return RightController.JoystickAxis;
|
||||
}
|
||||
|
||||
if (LeftController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
if (LeftController.TrackpadButtonState.Active)
|
||||
return LeftController.TrackpadAxis;
|
||||
return Vector2.zero;
|
||||
}
|
||||
|
||||
return LeftController.JoystickAxis;
|
||||
}
|
||||
|
||||
private Vector2 CheckWASD()
|
||||
{
|
||||
var x = 0f;
|
||||
var y = 0f;
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
if (Input.GetKey(KeyCode.W))
|
||||
y += 1f;
|
||||
if (Input.GetKey(KeyCode.S))
|
||||
y -= 1f;
|
||||
if (Input.GetKey(KeyCode.A))
|
||||
x += -1f;
|
||||
if (Input.GetKey(KeyCode.D))
|
||||
x += 1f;
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current[Key.W].isPressed)
|
||||
y += 1f;
|
||||
if (Keyboard.current[Key.S].isPressed)
|
||||
y -= 1f;
|
||||
if (Keyboard.current[Key.A].isPressed)
|
||||
x += -1f;
|
||||
if (Keyboard.current[Key.D].isPressed)
|
||||
x += 1f;
|
||||
#endif
|
||||
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
protected virtual Vector2 GetTurnAxis()
|
||||
{
|
||||
if (SwapMovementAxis)
|
||||
{
|
||||
if (LeftController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
if (Mathf.Abs(LeftController.TrackpadAxis.y) > .6f)
|
||||
return Vector2.zero;
|
||||
|
||||
if (LeftController.TrackpadButtonState.Active)
|
||||
{
|
||||
return LeftController.TrackpadAxis;
|
||||
}
|
||||
|
||||
return Vector2.zero;
|
||||
}
|
||||
|
||||
return LeftController.JoystickAxis;
|
||||
}
|
||||
|
||||
if (RightController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
if (Mathf.Abs(RightController.TrackpadAxis.y) > .6f)
|
||||
return Vector2.zero;
|
||||
|
||||
if (RightController.TrackpadButtonState.Active)
|
||||
{
|
||||
return RightController.TrackpadAxis;
|
||||
}
|
||||
|
||||
return Vector2.zero;
|
||||
}
|
||||
|
||||
return RightController.JoystickAxis;
|
||||
}
|
||||
|
||||
protected virtual bool GetTeleportDeactivated()
|
||||
{
|
||||
if (HVRInputManager.Instance.RightController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
return HVRController.GetButtonState(HVRHandSide.Right, HVRButtons.Menu).JustDeactivated;
|
||||
}
|
||||
|
||||
return TeleportController.JoystickAxis.y > -.25f;
|
||||
}
|
||||
|
||||
protected virtual bool GetTeleportActivated()
|
||||
{
|
||||
if (HVRInputManager.Instance.RightController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
return HVRController.GetButtonState(HVRHandSide.Right, HVRButtons.Menu).Active;
|
||||
}
|
||||
|
||||
return TeleportController.JoystickAxis.y < -.5f && Mathf.Abs(TeleportController.JoystickAxis.x) < .30;
|
||||
}
|
||||
|
||||
protected virtual bool GetSprinting()
|
||||
{
|
||||
if (LeftController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
SprintRequiresDoubleClick = true;
|
||||
return LeftController.TrackpadButtonState.JustActivated;
|
||||
}
|
||||
|
||||
SprintRequiresDoubleClick = false;
|
||||
if (RightController.ControllerType == HVRControllerType.WMR)
|
||||
{
|
||||
return RightController.TrackPadRight.JustActivated;
|
||||
}
|
||||
|
||||
//controls that allow you to depress the joystick (wmr opens up steamvr)
|
||||
return LeftController.JoystickButtonState.JustActivated;
|
||||
}
|
||||
|
||||
protected virtual bool GetCrouch()
|
||||
{
|
||||
if (RightController.ControllerType == HVRControllerType.Vive)
|
||||
{
|
||||
return RightController.TrackPadUp.JustActivated;
|
||||
}
|
||||
|
||||
if (RightController.ControllerType == HVRControllerType.WMR)
|
||||
{
|
||||
return RightController.TrackPadDown.JustActivated;
|
||||
}
|
||||
|
||||
return RightController.SecondaryButtonState.JustActivated;
|
||||
}
|
||||
|
||||
protected virtual Vector2 GetMouse(out bool mouseDown)
|
||||
{
|
||||
mouseDown = false;
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
if (Input.GetMouseButton(1))
|
||||
{
|
||||
mouseDown = true;
|
||||
return new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
|
||||
}
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current.rightButton.isPressed)
|
||||
{
|
||||
mouseDown = true;
|
||||
return Mouse.current.delta.ReadValue();
|
||||
}
|
||||
#endif
|
||||
|
||||
return Vector2.zero;
|
||||
}
|
||||
}
|
||||
|
||||
public enum HVRForceGrabActivation
|
||||
{
|
||||
Grip,
|
||||
GripAndTrigger,
|
||||
Trigger,
|
||||
GripOrTrigger
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f258b67bcfea4b9782cfcdcd54058670
|
||||
timeCreated: 1603043879
|
||||
@@ -0,0 +1,38 @@
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HurricaneVR.Framework.ControllerInput
|
||||
{
|
||||
public class HVRTrackedController : MonoBehaviour
|
||||
{
|
||||
public HVRHandSide HandSide;
|
||||
|
||||
public float VelocityMagnitude;// { get; private set; }
|
||||
public float AngularVelocityMagnitude;// { get; private set; }
|
||||
|
||||
public Quaternion DeltaRotationZ { get; private set; }
|
||||
public float DeltaEulerZ { get; private set; }
|
||||
private Vector3 _previousUp;
|
||||
public float DeltaZDisplay;
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
var delta = Vector3.SignedAngle(_previousUp, transform.up, transform.forward);
|
||||
DeltaEulerZ = delta;
|
||||
DeltaRotationZ = Quaternion.Euler(0, 0, delta);
|
||||
_previousUp = transform.up;
|
||||
if (Mathf.Abs(DeltaEulerZ) > 2)
|
||||
{
|
||||
DeltaZDisplay = DeltaEulerZ;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
VelocityMagnitude = HVRInputManager.Instance.GetController(HandSide).VelocityMagnitude;
|
||||
AngularVelocityMagnitude = HVRInputManager.Instance.GetController(HandSide).AngularVelocityMagnitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44ea0e34f99846a4824b42b44d2e35cd
|
||||
timeCreated: 1600355474
|
||||
@@ -0,0 +1,211 @@
|
||||
using System;
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace HurricaneVR.Framework.ControllerInput
|
||||
{
|
||||
|
||||
|
||||
enum ButtonReadType
|
||||
{
|
||||
None = 0,
|
||||
Binary,
|
||||
Axis1D,
|
||||
Axis2DUp,
|
||||
Axis2DDown,
|
||||
Axis2DLeft,
|
||||
Axis2DRight
|
||||
}
|
||||
|
||||
struct ButtonInfo
|
||||
{
|
||||
public ButtonInfo(string name, ButtonReadType type)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public string name;
|
||||
public ButtonReadType type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class HVRXRInputController : HVRController
|
||||
{
|
||||
|
||||
static ButtonInfo[] s_ButtonData = new ButtonInfo[]
|
||||
{
|
||||
new ButtonInfo("", ButtonReadType.None),
|
||||
new ButtonInfo("MenuButton", ButtonReadType.Binary),
|
||||
new ButtonInfo("Trigger", ButtonReadType.Axis1D),
|
||||
new ButtonInfo("Grip", ButtonReadType.Axis1D),
|
||||
new ButtonInfo("TriggerPressed", ButtonReadType.Binary),
|
||||
new ButtonInfo("GripPressed", ButtonReadType.Binary),
|
||||
new ButtonInfo("PrimaryButton", ButtonReadType.Binary),
|
||||
new ButtonInfo("PrimaryTouch", ButtonReadType.Binary),
|
||||
new ButtonInfo("SecondaryButton", ButtonReadType.Binary),
|
||||
new ButtonInfo("SecondaryTouch", ButtonReadType.Binary),
|
||||
new ButtonInfo("Primary2DAxisTouch", ButtonReadType.Binary),
|
||||
new ButtonInfo("Primary2DAxisClick", ButtonReadType.Binary),
|
||||
new ButtonInfo("Secondary2DAxisTouch", ButtonReadType.Binary),
|
||||
new ButtonInfo("Secondary2DAxisClick", ButtonReadType.Binary),
|
||||
new ButtonInfo("Primary2DAxis", ButtonReadType.Axis2DUp),
|
||||
new ButtonInfo("Primary2DAxis", ButtonReadType.Axis2DDown),
|
||||
new ButtonInfo("Primary2DAxis", ButtonReadType.Axis2DLeft),
|
||||
new ButtonInfo("Primary2DAxis", ButtonReadType.Axis2DRight),
|
||||
new ButtonInfo("Secondary2DAxis", ButtonReadType.Axis2DUp),
|
||||
new ButtonInfo("Secondary2DAxis", ButtonReadType.Axis2DDown),
|
||||
new ButtonInfo("Secondary2DAxis", ButtonReadType.Axis2DLeft),
|
||||
new ButtonInfo("Secondary2DAxis", ButtonReadType.Axis2DRight),
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
protected virtual InputFeatureUsage<Vector2> JoystickAxisFeature => InputMap.JoystickAxis == InputAxes.Primary2DAxis ?
|
||||
CommonUsages.primary2DAxis : CommonUsages.secondary2DAxis;
|
||||
|
||||
protected virtual InputFeatureUsage<Vector2> TrackPadAxisFeature => InputMap.TrackPadAxis == InputAxes.Primary2DAxis ?
|
||||
CommonUsages.primary2DAxis : CommonUsages.secondary2DAxis;
|
||||
|
||||
|
||||
|
||||
protected override void UpdateInput()
|
||||
{
|
||||
if (InputMap)
|
||||
{
|
||||
Device.TryGetFeatureValue(JoystickAxisFeature, out JoystickAxis);
|
||||
Device.TryGetFeatureValue(TrackPadAxisFeature, out TrackpadAxis);
|
||||
|
||||
Device.TryGetFeatureValue(CommonUsages.grip, out Grip);
|
||||
Device.TryGetFeatureValue(CommonUsages.trigger, out Trigger);
|
||||
|
||||
PrimaryButton = IsPressed(Device, InputMap.Primary);
|
||||
PrimaryTouch = IsPressed(Device, InputMap.PrimaryTouch);
|
||||
|
||||
SecondaryButton = IsPressed(Device, InputMap.Secondary);
|
||||
SecondaryTouch = IsPressed(Device, InputMap.SecondaryTouch);
|
||||
|
||||
MenuButton = IsPressed(Device, InputMap.Menu);
|
||||
|
||||
JoystickClicked = IsPressed(Device, InputMap.JoystickButton);
|
||||
TrackPadClicked = IsPressed(Device, InputMap.TrackPadButton);
|
||||
|
||||
JoystickTouch = IsPressed(Device, InputMap.JoystickTouch);
|
||||
TrackPadTouch = IsPressed(Device, InputMap.TrackPadTouch);
|
||||
|
||||
#if USING_XR_MANAGEMENT
|
||||
Device.TryGetFeatureValue(indexTouch, out TriggerTouch);
|
||||
#else
|
||||
Device.TryGetFeatureValue(legacyIndexTouch, out var temp);
|
||||
|
||||
TriggerTouch = temp > 0f;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private readonly InputFeatureUsage<bool> indexTouch = new InputFeatureUsage<bool>("IndexTouch");
|
||||
private static InputFeatureUsage<float> legacyIndexTouch = new InputFeatureUsage<float>("IndexTouch");
|
||||
|
||||
protected override void AfterInputUpdate()
|
||||
{
|
||||
SetButtonState(HVRButtons.ThumbNearTouch, ref ThumbNearTouchState, ThumbTouch);
|
||||
SetButtonState(HVRButtons.TriggerNearTouch, ref TriggerNearTouchState, TriggerTouch);
|
||||
SetButtonState(HVRButtons.ThumbTouch, ref ThumbTouchState, PrimaryTouch || SecondaryTouch || TrackPadTouch || JoystickTouch);
|
||||
}
|
||||
|
||||
public bool CheckAdditionalFeature(HVRXRInputFeatures input)
|
||||
{
|
||||
if (input == HVRXRInputFeatures.SecondaryAxis2DUp ||
|
||||
input == HVRXRInputFeatures.SecondaryAxis2DDown ||
|
||||
input == HVRXRInputFeatures.SecondaryAxis2DLeft ||
|
||||
input == HVRXRInputFeatures.SecondaryAxis2DRight)
|
||||
{
|
||||
return IsPressed(Device, InputMap.TrackPadButton);
|
||||
}
|
||||
|
||||
if (input == HVRXRInputFeatures.PrimaryAxis2DUp ||
|
||||
input == HVRXRInputFeatures.PrimaryAxis2DDown ||
|
||||
input == HVRXRInputFeatures.PrimaryAxis2DLeft ||
|
||||
input == HVRXRInputFeatures.PrimaryAxis2DRight)
|
||||
{
|
||||
return IsPressed(Device, InputMap.TrackPadButton);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsPressed(InputDevice device, HVRXRInputFeatures inputFeature, float threshold = 0f)
|
||||
{
|
||||
if ((int)inputFeature >= s_ButtonData.Length)
|
||||
{
|
||||
throw new ArgumentException("[InputHelpers.IsPressed] The value of <button> is out or the supported range.");
|
||||
}
|
||||
|
||||
//button down check in addition to track pad check
|
||||
if (!CheckAdditionalFeature(inputFeature))
|
||||
return false;
|
||||
|
||||
var info = s_ButtonData[(int)inputFeature];
|
||||
switch (info.type)
|
||||
{
|
||||
case ButtonReadType.Binary:
|
||||
{
|
||||
if (device.TryGetFeatureValue(new InputFeatureUsage<bool>(info.name), out bool value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ButtonReadType.Axis1D:
|
||||
{
|
||||
if (device.TryGetFeatureValue(new InputFeatureUsage<float>(info.name), out float value))
|
||||
{
|
||||
return value >= threshold;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ButtonReadType.Axis2DUp:
|
||||
{
|
||||
if (device.TryGetFeatureValue(new InputFeatureUsage<Vector2>(info.name), out Vector2 value))
|
||||
{
|
||||
return value.y >= InputMap.Axis2DUpThreshold;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ButtonReadType.Axis2DDown:
|
||||
{
|
||||
if (device.TryGetFeatureValue(new InputFeatureUsage<Vector2>(info.name), out Vector2 value))
|
||||
{
|
||||
return value.y <= -InputMap.Axis2DDownThreshold;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ButtonReadType.Axis2DLeft:
|
||||
{
|
||||
if (device.TryGetFeatureValue(new InputFeatureUsage<Vector2>(info.name), out Vector2 value))
|
||||
{
|
||||
return value.x <= -InputMap.Axis2DLeftThreshold;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ButtonReadType.Axis2DRight:
|
||||
{
|
||||
if (device.TryGetFeatureValue(new InputFeatureUsage<Vector2>(info.name), out Vector2 value))
|
||||
{
|
||||
return value.x >= InputMap.Axis2DRighThreshold;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 783ea3a1358f4960b7aafcc2c2778559
|
||||
timeCreated: 1597711347
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d273bf0a8d63e942948e47c85ba070e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using HurricaneVR.Framework.Shared;
|
||||
using UnityEngine.Events;
|
||||
namespace HurricaneVR.Framework.ControllerInput.InputEvents
|
||||
{
|
||||
public class HVRGripButtonEvents : HVRInputAction
|
||||
{
|
||||
public UnityEvent Activated = new UnityEvent();
|
||||
public UnityEvent Deactivated = new UnityEvent();
|
||||
|
||||
public float Value;
|
||||
|
||||
protected override void CheckInput(HVRController controller)
|
||||
{
|
||||
Value = controller.Grip;
|
||||
|
||||
if (controller.GripButtonState.JustActivated)
|
||||
{
|
||||
Activated.Invoke();
|
||||
}
|
||||
else if (controller.GripButtonState.JustDeactivated)
|
||||
{
|
||||
Deactivated.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c773e81cb9c97548984b0405de96a04
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user