Replace UltimateXR with HurricaneVR

This commit is contained in:
2024-08-08 17:01:07 +02:00
parent e8658374d6
commit fb21dbbb73
5932 changed files with 358362 additions and 2174150 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 91ad5e85488a9994e8c254c2a88a77ad
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e538dc1865da2ed41b9f803e3e586405
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c1b17ef000f068b468782f079bd24ba6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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> { }
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 73f686e3f59dc0541a3a83773538b43f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ff48744587821344b5cc14739c2d16c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 123d9563fca44af1864835effb36ffbc
timeCreated: 1600399646

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 59ef9bc5899042d588a09adb8a254aa9
timeCreated: 1601145324

View File

@@ -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;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ab72751261f74e5ebaa6986a0464cd15
timeCreated: 1635035319

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d2fba50691c4c804ea3f345eb904cc95
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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)
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e49c8bf2db256ba438a090d0d46c85ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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()
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 029f5fabd456e3d4ca818afd570d575d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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>
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1d73b26c803e4bbb886b5776121804b2
timeCreated: 1600231143

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6751180565d247fba4285903a5b605aa
timeCreated: 1601087539

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 66f0a0ab295247a681b1b569944a2bf9
timeCreated: 1599957568

View 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()
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a95f97577cc01a746a9d0a3e11b90b8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using UnityEngine;
namespace HurricaneVR.Framework.Components
{
public class HVRDontDestroy : MonoBehaviour
{
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2e5b279a1a044cee9d64e0ca5d85f175
timeCreated: 1601039791

View File

@@ -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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6c25cecd1cd34cd7a4346c955a0add93
timeCreated: 1600204770

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 77dbe74f0338a6c438b0af580dd1253e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 735256ec9b08e024a8efea6924dd44b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 60ac0a61a75ecf64e8c54dcb82a08821
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b775075551dfdd947bebcfce71c1a7c1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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)
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38a18e75cd9699f428ac9902c039394c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e395cf0cf494656baa6b1eddceceb24
timeCreated: 1600542387

View File

@@ -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()
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4e7c9a97934caec4897562447669e7e7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 86ae87a96c3b7dd4c8c15912e79812f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b06dd533ee37487db0603f3b328f972f
timeCreated: 1602523768

View File

@@ -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> { }
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fb388898ff2f814f84c5cfa8b56235f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2cd0e73266090f94ea7927da1368c184
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4eeb3f37d2fe3e547a9a248b2bbf0139
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 465d464c79597514bb491631782942cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
//}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93ae46635261c874188443083a8deee5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f1a0e712065e5ec4484d6ca15e0f4563
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f268fd1aeab764742be311a0d06b49d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3f12566bd4f6404580f543211008456c
timeCreated: 1600292559

View File

@@ -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);
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 02aeadf9b7915034d999c6e3161257f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 50bacb0498a77b04b867c1791becba25
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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> { }
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 80e9f8f507f775b4aa48c08844126549
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 74b910c8c3f34ee5bb44c0358f637ecc
timeCreated: 1600274255

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5f52676b29554048a64664a7a53a126e
timeCreated: 1601260700

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a09a78d26498d0459d4d698c39e3a28
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b0c3b4fd1ff88ab4ebcc76efa7ad486a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd07f8606d5a2184ca2bab0e57b64ef7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4cbdb3f5a90abf442b512b58ce932e71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0a934dfe7ddf4fb2a1ec98943c4bcd57
timeCreated: 1604448529

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 94e2703aa70f47be808cc7d516fced77
timeCreated: 1600342873

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e9db12adedf02d4797c05ee5c7cbacb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7033fdbdef534aeaaad3c868224922db
timeCreated: 1718677714

View File

@@ -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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f258b67bcfea4b9782cfcdcd54058670
timeCreated: 1603043879

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 44ea0e34f99846a4824b42b44d2e35cd
timeCreated: 1600355474

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 783ea3a1358f4960b7aafcc2c2778559
timeCreated: 1597711347

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7d273bf0a8d63e942948e47c85ba070e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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();
}
}
}
}

View File

@@ -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