NEW HVR 2.9.1f

This commit is contained in:
2023-03-25 03:17:58 +03:00
parent f0bf64ed45
commit 91acc4d728
243 changed files with 16657 additions and 11137 deletions
@@ -5,6 +5,10 @@ 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
{
@@ -38,11 +42,6 @@ namespace HurricaneVR.Framework.Components
Rigidbody = GetComponent<Rigidbody>();
}
void Update()
{
}
private void FixedUpdate()
{
var distance = (StartPosition - transform.localPosition).magnitude;
@@ -2,18 +2,12 @@
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
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
}
@@ -4,6 +4,9 @@ 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")]
@@ -5,6 +5,10 @@ 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>
@@ -30,16 +34,20 @@ namespace HurricaneVR.Framework.Components
public Vector3 ControllerRotationOffset => _offsets != null ? _offsets.Rotation : Vector3.zero;
[Header("Debugging")]
public Vector3 TargetGrabPointPositionOffset;
public Vector3 TargetGrabPointRotationOffset;
public Vector3 GrabPointPositionOffset;
public Vector3 GrabPointRotationOffset;
public Vector3 MiscPositionOffset;
public Vector3 MiscRotationOffset;
[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;
@@ -15,10 +15,13 @@ namespace HurricaneVR.Framework.Components
{
[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;
@@ -27,11 +30,13 @@ namespace HurricaneVR.Framework.Components
[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)
{
@@ -47,7 +52,6 @@ namespace HurricaneVR.Framework.Components
switch (type)
{
case HVRControllerType.Oculus:
if (steamVR)
{
@@ -83,6 +87,7 @@ namespace HurricaneVR.Framework.Components
{
return ViveOpenXR;
}
break;
case HVRControllerType.Knuckles:
if (steamVR)
@@ -93,6 +98,7 @@ namespace HurricaneVR.Framework.Components
{
return KnucklesOpenXR;
}
break;
case HVRControllerType.Cosmos:
if (steamVR)
@@ -103,6 +109,7 @@ namespace HurricaneVR.Framework.Components
{
return CosmosOpenXR;
}
break;
case HVRControllerType.ReverbG2:
if (steamVR)
@@ -113,7 +120,14 @@ namespace HurricaneVR.Framework.Components
{
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;
@@ -124,7 +138,9 @@ namespace HurricaneVR.Framework.Components
public class HVRDevicePoseOffset
{
public Vector3 Position;
[FormerlySerializedAs("_rotation")] [SerializeField]
[FormerlySerializedAs("_rotation")]
[SerializeField]
public Vector3 Rotation;
}
}
@@ -13,8 +13,6 @@ namespace HurricaneVR.Framework.Components
public HVRDestructible Desctructible;
void Start()
{
Rigidbody = GetComponent<Rigidbody>();
@@ -4,6 +4,9 @@ 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();
@@ -3,6 +3,9 @@ using UnityEngine;
namespace HurricaneVR.Framework.Components
{
/// <summary>
/// Destroys this game object after a timeout
/// </summary>
public class HVRDestroyTimer : MonoBehaviour
{
public void StartTimer(float timeout)
@@ -3,6 +3,11 @@ 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;
@@ -17,8 +22,12 @@ namespace HurricaneVR.Framework.Components
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);
@@ -59,6 +68,7 @@ namespace HurricaneVR.Framework.Components
}
}
Destroyed = true;
Destroy(gameObject);
}
}
@@ -5,6 +5,9 @@ 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
{
@@ -1,18 +1,42 @@
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)
@@ -46,10 +46,10 @@ namespace HurricaneVR.Framework.Components
{
Folder = DateTime.Now.ToString("yyyyMMdd_HH_mm");
}
#if UNITY_EDITOR
void Update()
{
#if UNITY_EDITOR
if (DisablePhysics && !_previousDisable)
{
@@ -79,9 +79,9 @@ namespace HurricaneVR.Framework.Components
_previousDisable = DisablePhysics;
CheckSnapshot();
#endif
}
}
#endif
private void CheckSnapshot()
{
HVRPosableHand hand = null;
@@ -12,10 +12,19 @@ namespace HurricaneVR.Framework.Components
public class HVRImpactHaptics : ScriptableObject
{
public float Timeout = .3f;
[Tooltip("Collision Velocity Square Magnitude cut off filter")]
public float SqrMagThreshold = .30f;
public float MaxForce = 600f;
[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()
@@ -16,6 +16,8 @@ namespace HurricaneVR.Framework.Components
private float _lastHaptic;
private Rigidbody Rb;
public virtual float MaxForce => Data.MaxForce;
protected virtual void Awake()
{
TryGetComponent(out Rb);
@@ -50,7 +52,7 @@ namespace HurricaneVR.Framework.Components
Force = impulse / Time.fixedDeltaTime;
var amp = Data.AmpCurve.Evaluate(Force / Data.MaxForce);
var amp = Data.AmpCurve.Evaluate(Force / MaxForce);
Vibrate(Data.Duration, amp, Data.Frequency);
@@ -6,7 +6,9 @@ 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
@@ -2,6 +2,9 @@
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;
@@ -7,13 +7,24 @@ 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;
@@ -8,11 +8,12 @@ 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
{
[SerializeField] public HVRGrabbable Grabbable;
[Header("Settings")]
[Tooltip("Local axis of rotation")]
public HVRAxis Axis;
@@ -23,6 +24,7 @@ namespace HurricaneVR.Framework.Components
[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")]
@@ -41,6 +43,7 @@ namespace HurricaneVR.Framework.Components
[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")]
@@ -52,6 +55,8 @@ namespace HurricaneVR.Framework.Components
public Rigidbody Rigidbody { get; private set; }
public HVRGrabbable Grabbable { get; private set; }
public ConfigurableJoint Joint { get; set; }
protected virtual void Awake()
@@ -60,26 +65,14 @@ namespace HurricaneVR.Framework.Components
Rigidbody.useGravity = !DisableGravity;
if (!Grabbable) Grabbable = GetComponent<HVRGrabbable>();
Grabbable = GetComponent<HVRGrabbable>();
if (Grabbable)
{
Grabbable.HandGrabbed.AddListener(OnDialGrabbed);
Grabbable.HandReleased.AddListener(OnDialReleased);
}
if (MinAngle > 0)
{
MinAngle *= -1;
}
if (MaxAngle < 0)
{
MaxAngle *= -1;
}
MinAngle = Mathf.Clamp(MinAngle, MinAngle, 0);
MaxAngle = Mathf.Clamp(MaxAngle, 0, MaxAngle);
FixAngle(ref MinAngle, ref MaxAngle);
SetupJoint();
AfterJointCreated(Joint);
@@ -95,7 +88,7 @@ namespace HurricaneVR.Framework.Components
if (TargetAngularVelocity > 0f || TargetAngularVelocity < 0f) Joint.targetAngularVelocity = new Vector3(TargetAngularVelocity, 0f, 0f);
}
private void OnDialReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
protected virtual void OnDialReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
{
Joint.SetAngularXDrive(Spring, Damper, 10000f);
if (StopOnRelease)
@@ -104,7 +97,7 @@ namespace HurricaneVR.Framework.Components
}
}
private void OnDialGrabbed(HVRHandGrabber arg0, HVRGrabbable arg1)
protected virtual void OnDialGrabbed(HVRHandGrabber arg0, HVRGrabbable arg1)
{
Joint.SetAngularXDrive(0f, GrabbedDamper, 10000f);
}
@@ -143,18 +136,53 @@ namespace HurricaneVR.Framework.Components
}
/// <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);
}
}
}
@@ -7,42 +7,76 @@ 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")]
[Header("Settings")] [Tooltip("Local axis of rotation")]
public HVRAxis Axis;
public float Mass = 10f;
[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")]
[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")]
[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")]
[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;
[Header("Joint Limits")]
public bool LimitRotation = true;
[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;
@@ -50,19 +84,17 @@ namespace HurricaneVR.Framework.Components
[Tooltip("Maximum rotation about the axis of rotation")]
public float MaxAngle;
[Header("Joint Settings")]
[Tooltip("Angular Damper when the dial is not grabbed")]
[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;
[Header("Debugging")] public float TargetAngularVelocity = 0f;
public bool DoorLatched;
public bool DoorClosed;
public bool Opened;
@@ -161,7 +193,7 @@ namespace HurricaneVR.Framework.Components
DoorClosed = false;
}
if (HandleGrabbable && HandleGrabbable.IsBeingHeld)
if (HandleGrabbable && HandleGrabbable.IsBeingHeld || SecondHandleGrabbable && SecondHandleGrabbable.IsBeingHeld)
{
_detectionTimer = 0f;
}
@@ -209,11 +241,14 @@ namespace HurricaneVR.Framework.Components
if (HandleRequiresRotation)
{
if (HandleRotationTracker.UnsignedAngle >= HandleThreshold)
if (HandleRotationTracker.UnsignedAngle >= HandleThreshold ||
(SecondHandleRotationTracker && SecondHandleRotationTracker.UnsignedAngle >= HandleThreshold))
{
DoorLatched = false;
}
else if (HandleRotationTracker.UnsignedAngle < HandleThreshold && Tracker.UnsignedAngle < CloseAngle)
else if (HandleRotationTracker.UnsignedAngle < HandleThreshold &&
(!SecondHandleRotationTracker || SecondHandleRotationTracker.UnsignedAngle < HandleThreshold) &&
Tracker.UnsignedAngle < CloseAngle)
{
DoorLatched = true;
}
@@ -235,7 +270,7 @@ namespace HurricaneVR.Framework.Components
PreviousClosed = DoorClosed;
}
private Vector3 GetSFXPosition()
protected virtual Vector3 GetSFXPosition()
{
var position = transform.position;
if (SFXPosition)
@@ -248,31 +283,30 @@ namespace HurricaneVR.Framework.Components
protected virtual void PlayClosedSFX()
{
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXClosed, GetSFXPosition());
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXClosed, GetSFXPosition());
}
protected virtual void PlayOpenedSFX()
{
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXOpened, GetSFXPosition());
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(SFXOpened, GetSFXPosition());
}
protected virtual void OnDoorUnLatched()
public virtual void OnDoorUnLatched()
{
if (VerboseLogging)
Debug.Log($"OnDoorUnLatched");
UnlockDoorJoint();
}
protected virtual void OnDoorLatched()
public virtual void OnDoorLatched()
{
if (VerboseLogging)
Debug.Log($"OnDoorLatched");
LockDoorJoint();
}
// ReSharper disable Unity.PerformanceAnalysis
protected virtual void OnDoorClosed()
{
if (VerboseLogging)
@@ -281,6 +315,7 @@ namespace HurricaneVR.Framework.Components
StartCoroutine(DoorCloseRoutine());
}
// ReSharper disable Unity.PerformanceAnalysis
protected virtual void OnDoorOpened()
{
if (VerboseLogging)
@@ -302,6 +337,9 @@ namespace HurricaneVR.Framework.Components
Joint.SetAngularXLowLimit(-MaxAngle);
}
/// <summary>
/// Locks the door joint, and the door knob's joint.
/// </summary>
public virtual void Lock()
{
Locked = true;
@@ -309,6 +347,9 @@ namespace HurricaneVR.Framework.Components
LockDoorKnob();
}
/// <summary>
/// Unlocks the door and allows the door handle to rotate.
/// </summary>
public virtual void Unlock()
{
Locked = false;
@@ -323,18 +364,14 @@ namespace HurricaneVR.Framework.Components
protected virtual void LockDoorKnob()
{
if (DoorKnob)
{
DoorKnob.SetLimits(0, 0);
}
if (DoorKnob) DoorKnob.SetLimits(0, 0);
if (SecondDoorKnob) SecondDoorKnob.SetLimits(0, 0);
}
protected virtual void UnlockDoorKnob()
{
if (DoorKnob)
{
DoorKnob.ResetLimits();
}
if (DoorKnob) DoorKnob.ResetLimits();
if (SecondDoorKnob) SecondDoorKnob.ResetLimits();
}
protected IEnumerator DoorCloseRoutine()
@@ -353,7 +390,7 @@ namespace HurricaneVR.Framework.Components
_doorClosing = false;
}
private void SetupJoint()
protected virtual void SetupJoint()
{
var currentRotation = transform.localRotation;
//transform.localRotation = JointStartRotation;
@@ -362,7 +399,7 @@ namespace HurricaneVR.Framework.Components
Joint.LockLinearMotion();
Joint.LockAngularYMotion();
Joint.LockAngularZMotion();
Joint.anchor = Vector3.zero;
Joint.axis = Axis.GetVector();
if (LimitRotation)
@@ -6,16 +6,28 @@ 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;
[Header("SFX")]
public float SFXResetThreshold = .02f;
public AudioClip SFXOpened;
public AudioClip SFXClosed;
@@ -7,23 +7,14 @@ 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 ConfigurableJoint preJoint;
protected override void SetupJoint()
{
if(!preJoint)
{
base.SetupJoint();
}
else
{
Joint = preJoint;
}
}
public void OnDrawGizmosSelected()
{
@@ -3,6 +3,9 @@ using UnityEngine;
namespace HurricaneVR.Framework.Components
{
/// <summary>
/// Helper component to override various rigidbody properties
/// </summary>
[RequireComponent(typeof(Rigidbody))]
public class HVRRigidBodyOverrides : MonoBehaviour
{
@@ -22,7 +25,7 @@ namespace HurricaneVR.Framework.Components
[Header("Debug")]
public Vector3 COMGizmoSize = new Vector3(.02f, .02f, .02f);
public bool LiveUpdate;
public bool ShowCOMGizmo;
public Rigidbody Rigidbody;
void Awake()
@@ -75,7 +78,7 @@ namespace HurricaneVR.Framework.Components
void OnDrawGizmosSelected()
{
//if (OverrideCOM)
if (ShowCOMGizmo)
{
Gizmos.color = Color.yellow;
if (OverrideCOM)
@@ -3,6 +3,9 @@ using UnityEngine;
namespace HurricaneVR.Framework.Components
{
/// <summary>
/// Helps constrain loose joints on the desired axis.
/// </summary>
public class HVRRigidbodyLocker : MonoBehaviour
{
public LockOptions Locks;
@@ -10,17 +10,22 @@ namespace HurricaneVR.Framework.Components
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;
@@ -30,7 +35,7 @@ namespace HurricaneVR.Framework.Components
protected override void Start()
{
if (!Camera)
if (!Camera && HVRManager.Instance)
{
Camera = HVRManager.Instance.Camera;
}
@@ -7,15 +7,26 @@ 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;
@@ -3,11 +3,18 @@ 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")]
@@ -41,11 +48,6 @@ namespace HurricaneVR.Framework.Components
}
}
public void Update()
{
}
protected virtual void PlaySFX(AudioClip sfx)
{
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(sfx, transform.position);
@@ -7,6 +7,10 @@ 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")]
@@ -2,6 +2,9 @@
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);
@@ -4,6 +4,9 @@ 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;
@@ -36,6 +39,7 @@ namespace HurricaneVR.Framework.Components
switch (controller.ControllerType)
{
case HVRControllerType.Pico:
case HVRControllerType.Oculus:
CenterOfMass = Oculus;
break;
@@ -19,6 +19,7 @@ namespace HurricaneVR.Framework.Components
Grabbable = GetComponent<HVRGrabbable>();
Grabbable.HandGrabbed.AddListener(OnHandGrabbed);
Grabbable.HandReleased.AddListener(OnHandReleased);
if (Others != null)
{
@@ -33,6 +34,11 @@ namespace HurricaneVR.Framework.Components
}
}
private void OnHandReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
{
Grabbable.ForceTwoHandSettings = false;
}
private void OnHandGrabbed(HVRHandGrabber arg0, HVRGrabbable arg1)
{
foreach (var other in Others)
@@ -45,9 +51,22 @@ namespace HurricaneVR.Framework.Components
}
}
private void OnOtherGrabbableHandReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
private void OnOtherGrabbableHandReleased(HVRHandGrabber arg0, HVRGrabbable g)
{
Grabbable.ForceTwoHandSettings = false;
//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)
@@ -33,7 +33,9 @@ using Valve.VR;
namespace HurricaneVR.Framework.ControllerInput
{
[Serializable]
public class HVRControllerEvent : UnityEvent<HVRController> { }
public class HVRControllerEvent : UnityEvent<HVRController>
{
}
public class HVRInputManager : MonoBehaviour
{
@@ -50,15 +52,16 @@ namespace HurricaneVR.Framework.ControllerInput
public const string Reverb = "reverb";
public const string G2 = "g2";
public const string OpenXR_G2 = "hp reverb g2 controller";
public const string Pico = "pico";
public const string LegacyOpenVRName = "OpenVR";
public const string LegacyOculusName = "Oculus";
public const string LegacyNone = "None";
[Header("XR Plugin Detection Names")]
public string OpenVRLoader = "Open VR Loader";
public string OculusLoader = "Oculus Loader";
public string OpenXRLoader = "Open XR Loader";
public string WMRLoader = "Windows MR Loader";
@@ -70,9 +73,7 @@ namespace HurricaneVR.Framework.ControllerInput
public static HVRInputManager Instance { get; private set; }
[Header("Oculus - Requires Oculus Asset + Integration")]
[Tooltip("If true ovrinputs will be used")]
public bool UseOVRInputs;
@@ -84,10 +85,10 @@ namespace HurricaneVR.Framework.ControllerInput
[Header("SteamVR - Requires SteamVR + Integration")]
public bool InitializeSteamVR = true;
public bool InitializeSteamVRActions = true;
[Header("Input Settings")]
[Tooltip("If true uses the new input system bindings")]
public bool UseNewInputSystem;
@@ -105,8 +106,10 @@ namespace HurricaneVR.Framework.ControllerInput
[Header("Device Specific Settings")]
public HVRInputSettings WMRInputMap;
[FormerlySerializedAs("WMRWithButtonsInputMap")]
public HVRInputSettings ReverbG2InputMap;
public HVRInputSettings OculusInputMap;
public HVRInputSettings ViveInputMap;
public HVRInputSettings KnucklesInputMap;
@@ -178,8 +181,11 @@ namespace HurricaneVR.Framework.ControllerInput
public string RightManufacturer;
public string RightControllerName;
[SerializeField] private HVRControllerType LeftXRInputSystem = HVRControllerType.None;
[SerializeField] private HVRControllerType RightControllerType = HVRControllerType.None;
[SerializeField]
private HVRControllerType LeftControllerType = HVRControllerType.None;
[SerializeField]
private HVRControllerType RightControllerType = HVRControllerType.None;
public List<string> LeftFeatures = new List<string>();
public List<string> RightFeatures = new List<string>();
@@ -243,7 +249,6 @@ namespace HurricaneVR.Framework.ControllerInput
{
get
{
if (!HMDActive)
return false;
@@ -258,8 +263,6 @@ namespace HurricaneVR.Framework.ControllerInput
}
#elif !UNITY_2020_1_OR_NEWER
//https://stackoverflow.com/questions/51372771/how-to-check-if-a-hmd-in-unity-2018-is-in-use
#pragma warning disable 0618
//if xr management wasn't detected use the old API for legacy VR
@@ -287,6 +290,7 @@ namespace HurricaneVR.Framework.ControllerInput
}
private InputDevice _leftDevice;
public InputDevice LeftDevice
{
get
@@ -299,6 +303,7 @@ namespace HurricaneVR.Framework.ControllerInput
}
private InputDevice _rightDevice;
public InputDevice RightDevice
{
get
@@ -311,8 +316,6 @@ namespace HurricaneVR.Framework.ControllerInput
}
private bool _isHMDFirstActivationReported;
@@ -392,7 +395,7 @@ namespace HurricaneVR.Framework.ControllerInput
#if HVR_OCULUS
if (UseOVRInputs && ForceOVRInputUpdate && (LeftXRInputSystem == HVRControllerType.Oculus || RightControllerType == HVRControllerType.Oculus))
if (UseOVRInputs && ForceOVRInputUpdate && (LeftControllerType == HVRControllerType.Oculus || RightControllerType == HVRControllerType.Oculus))
{
HVROculusController.UpdateOVRInput();
}
@@ -552,7 +555,6 @@ namespace HurricaneVR.Framework.ControllerInput
RightController = UpdateController(RightControllerType, device, HVRHandSide.Right);
if (device.isValid)
RightControllerConnected.Invoke(RightController);
}
private void UpdateLeftController(InputDevice device)
@@ -574,8 +576,8 @@ namespace HurricaneVR.Framework.ControllerInput
}
}
LeftXRInputSystem = GetController(LeftDevice.manufacturer?.ToLower(), LeftDevice.name?.ToLower());
LeftController = UpdateController(LeftXRInputSystem, device, HVRHandSide.Left);
LeftControllerType = GetController(LeftDevice.manufacturer?.ToLower(), LeftDevice.name?.ToLower());
LeftController = UpdateController(LeftControllerType, device, HVRHandSide.Left);
if (device.isValid)
LeftControllerConnected.Invoke(LeftController);
}
@@ -613,6 +615,7 @@ namespace HurricaneVR.Framework.ControllerInput
inputMap = WMRInputMap;
deadZone = WMRDeadzone;
break;
case HVRControllerType.Pico:
case HVRControllerType.Oculus:
inputMap = OculusInputMap;
deadZone = OculusDeadzone;
@@ -801,7 +804,6 @@ namespace HurricaneVR.Framework.ControllerInput
}
if (manufaturerToLower.Contains(Oculus))
{
return HVRControllerType.Oculus;
@@ -832,6 +834,8 @@ namespace HurricaneVR.Framework.ControllerInput
return HVRControllerType.WMR;
}
if (nameToLower.Contains(Pico))
return HVRControllerType.Pico;
return HVRControllerType.None;
}
@@ -896,6 +900,7 @@ namespace HurricaneVR.Framework.ControllerInput
{
Debug.LogWarning($"HVR: {OpenVRLoader} active without SteamVR installed or HVR_STEAMVR define set.");
}
CurrentSDK = InputSDK.SteamVR;
return;
}
@@ -906,7 +911,7 @@ namespace HurricaneVR.Framework.ControllerInput
}
//legacy vr
if (LeftXRInputSystem == HVRControllerType.Oculus || RightControllerType == HVRControllerType.Oculus)
if (LeftControllerType == HVRControllerType.Oculus || RightControllerType == HVRControllerType.Oculus)
{
CurrentSDK = UseOVRInputs ? InputSDK.Oculus : InputSDK.XRInput;
return;
@@ -926,7 +931,6 @@ namespace HurricaneVR.Framework.ControllerInput
#if !OPENVR_DESKTOP && !OPENVR_XR
return false;
#else
#if OPENVR_DESKTOP
if (!Valve.VR.SteamVR.usingNativeSupport)
@@ -977,13 +981,12 @@ namespace HurricaneVR.Framework.ControllerInput
#else
loaders = string.Join(",", XRGeneralSettings.Instance.Manager.loaders.Select(e => e.name));
#endif
Debug.Log($"{ XRGeneralSettings.Instance.Manager.automaticLoading}");
Debug.Log($"XRGeneralSettings.Instance.Manager.isInitializationComplete { XRGeneralSettings.Instance.Manager.isInitializationComplete}");
Debug.Log($"{XRGeneralSettings.Instance.Manager.automaticLoading}");
Debug.Log($"XRGeneralSettings.Instance.Manager.isInitializationComplete {XRGeneralSettings.Instance.Manager.isInitializationComplete}");
Debug.Log($"XRPlugin Detected | XRSettings.enabled {XRSettings.enabled} | Loader : {XRPluginLoader} | Loaders Enabled: {loaders}");
XRPluginActive = XRSettings.enabled && XRGeneralSettings.Instance.Manager.isInitializationComplete;
#elif !UNITY_2020_1_OR_NEWER
var legacyDevices = "";
foreach (var t in XRSettings.supportedDevices)
{
@@ -1025,7 +1028,6 @@ namespace HurricaneVR.Framework.ControllerInput
}
public void StopXR()
{
#if USING_XR_MANAGEMENT
@@ -1059,10 +1061,8 @@ namespace HurricaneVR.Framework.ControllerInput
Debug.LogWarning($"XR Plugin Management is in use. Cannot load Legacy VR");
return;
#elif !UNITY_2020_1_OR_NEWER
StartCoroutine(LoadLegacy(callback));
#endif
}
@@ -1101,6 +1101,7 @@ namespace HurricaneVR.Framework.ControllerInput
{
callback(false);
}
LegacyActive = false;
}
}
@@ -1152,7 +1153,6 @@ namespace HurricaneVR.Framework.ControllerInput
IsSteamVR = true;
#endif
}
private void StopSteamVR()
@@ -1198,8 +1198,6 @@ namespace HurricaneVR.Framework.ControllerInput
}
#elif !UNITY_2020_1_OR_NEWER
if (originFlags == TrackingOriginModeFlags.Floor)
{
#pragma warning disable 0618
@@ -1220,7 +1218,6 @@ namespace HurricaneVR.Framework.ControllerInput
}
#endif
}
}
@@ -1229,5 +1226,4 @@ namespace HurricaneVR.Framework.ControllerInput
Legacy,
XRPlugin
}
}
}
@@ -16,6 +16,7 @@ namespace HurricaneVR.Framework.ControllerInput
{
[Header("Grab Settings")]
public bool CanDistanceGrab = true;
public bool CanTriggerGrab;
[Tooltip("For non flick style force grabber")]
@@ -26,6 +27,7 @@ namespace HurricaneVR.Framework.ControllerInput
[Header("Inputs Debugging")]
public Vector2 MovementAxis;
public Vector2 TurnAxis;
public bool IsTeleportActivated;
@@ -88,6 +90,15 @@ namespace HurricaneVR.Framework.ControllerInput
AfterInputUpdate();
}
protected virtual void OnEnable()
{
}
protected virtual void OnDisable()
{
}
protected virtual void UpdateInput()
{
if (!UpdateInputs)
@@ -130,11 +141,9 @@ namespace HurricaneVR.Framework.ControllerInput
protected virtual void AfterInputUpdate()
{
}
protected void ResetState(ref HVRButtonState buttonState)
{
buttonState.JustDeactivated = false;
@@ -172,7 +181,7 @@ namespace HurricaneVR.Framework.ControllerInput
{
if (RightController.ControllerType == HVRControllerType.Vive)
{
return false;//todo
return false; //todo
}
return false;
@@ -180,10 +189,11 @@ namespace HurricaneVR.Framework.ControllerInput
protected virtual void GetForceGrabActivated(out bool left, out bool right)
{
left = false;
right = false;
if (!CanDistanceGrab)
{
left = false;
right = false;
return;
}
@@ -192,24 +202,52 @@ namespace HurricaneVR.Framework.ControllerInput
left = LeftController.GripButtonState.JustActivated;
right = RightController.GripButtonState.JustActivated;
}
else
else if (ForceGrabActivation == HVRForceGrabActivation.GripAndTrigger)
{
left = LeftController.GripButtonState.Active && LeftController.TriggerButtonState.JustActivated || LeftController.TriggerButtonState.Active && LeftController.GripButtonState.JustActivated;
right = RightController.GripButtonState.Active && RightController.TriggerButtonState.JustActivated || RightController.TriggerButtonState.Active && RightController.GripButtonState.JustActivated;
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)
{
left = false;
right = false;
return;
}
left = LeftController.GripButtonState.Active;
right = RightController.GripButtonState.Active;
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)
@@ -237,11 +275,6 @@ namespace HurricaneVR.Framework.ControllerInput
return side == HVRHandSide.Left ? IsLeftGrabActivated : IsRightGrabActivated;
}
public bool GetHoldActive(HVRHandSide side)
{
return side == HVRHandSide.Left ? IsLeftHoldActive : IsRightHoldActive;
}
public bool GetGripHoldActive(HVRHandSide side)
{
return side == HVRHandSide.Left ? IsLeftGripHoldActive : IsRightGripHoldActive;
@@ -266,6 +299,7 @@ namespace HurricaneVR.Framework.ControllerInput
{
return true;
}
return LeftController.GripButtonState.Active;
}
@@ -283,6 +317,7 @@ namespace HurricaneVR.Framework.ControllerInput
{
return true;
}
return RightController.GripButtonState.Active;
}
@@ -358,6 +393,7 @@ namespace HurricaneVR.Framework.ControllerInput
{
return LeftController.TrackpadAxis;
}
return Vector2.zero;
}
@@ -371,9 +407,9 @@ namespace HurricaneVR.Framework.ControllerInput
if (RightController.TrackpadButtonState.Active)
{
return RightController.TrackpadAxis;
}
return Vector2.zero;
}
@@ -458,6 +494,8 @@ namespace HurricaneVR.Framework.ControllerInput
public enum HVRForceGrabActivation
{
Grip,
GripHoldTriggerPress
GripAndTrigger,
Trigger,
GripOrTrigger
}
}
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was auto-generated by com.unity.inputsystem:InputActionCodeGenerator
// version 1.3.0
// version 1.5.0
// from Assets/HurricaneVR/Framework/Scripts/ControllerInput/InputSystem/HVRInputActions.inputactions
//
// Changes to this file may cause incorrect behavior and will be lost if
@@ -15,7 +15,7 @@ using System.Collections.Generic;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
public partial class @HVRInputActions : IInputActionCollection2, IDisposable
public partial class @HVRInputActions: IInputActionCollection2, IDisposable
{
public InputActionAsset asset { get; }
public @HVRInputActions()
@@ -275,6 +275,28 @@ public partial class @HVRInputActions : IInputActionCollection2, IDisposable
""isComposite"": false,
""isPartOfComposite"": false
},
{
""name"": """",
""id"": ""692f48f9-3f21-406f-b2d5-5b5e0c4c2761"",
""path"": ""<OculusTouchController>{LeftHand}/menu"",
""interactions"": """",
""processors"": """",
""groups"": """",
""action"": ""Menu"",
""isComposite"": false,
""isPartOfComposite"": false
},
{
""name"": """",
""id"": ""d55f9044-c561-4b40-957b-ad0bd93adc50"",
""path"": ""<WMRSpatialController>{LeftHand}/menu"",
""interactions"": """",
""processors"": """",
""groups"": """",
""action"": ""Menu"",
""isComposite"": false,
""isPartOfComposite"": false
},
{
""name"": """",
""id"": ""54ac7ab0-8ca9-4cbc-a6d1-da5ee0b055cb"",
@@ -738,6 +760,17 @@ public partial class @HVRInputActions : IInputActionCollection2, IDisposable
""isComposite"": false,
""isPartOfComposite"": false
},
{
""name"": """",
""id"": ""0c608bc0-1dda-4d95-8e76-add87e298bcc"",
""path"": ""<WMRSpatialController>{LeftHand}/menu"",
""interactions"": """",
""processors"": """",
""groups"": """",
""action"": ""Menu"",
""isComposite"": false,
""isPartOfComposite"": false
},
{
""name"": """",
""id"": ""488857b2-965c-486c-b24e-e21628ad2a07"",
@@ -1167,12 +1200,14 @@ public partial class @HVRInputActions : IInputActionCollection2, IDisposable
{
asset.Disable();
}
public IEnumerable<InputBinding> bindings => asset.bindings;
public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false)
{
return asset.FindAction(actionNameOrId, throwIfNotFound);
}
public int FindBinding(InputBinding bindingMask, out InputAction action)
{
return asset.FindBinding(bindingMask, out action);
@@ -1180,7 +1215,7 @@ public partial class @HVRInputActions : IInputActionCollection2, IDisposable
// LeftHand
private readonly InputActionMap m_LeftHand;
private ILeftHandActions m_LeftHandActionsCallbackInterface;
private List<ILeftHandActions> m_LeftHandActionsCallbackInterfaces = new List<ILeftHandActions>();
private readonly InputAction m_LeftHand_TriggerPress;
private readonly InputAction m_LeftHand_Trigger;
private readonly InputAction m_LeftHand_PrimaryButton;
@@ -1230,142 +1265,155 @@ public partial class @HVRInputActions : IInputActionCollection2, IDisposable
public void Disable() { Get().Disable(); }
public bool enabled => Get().enabled;
public static implicit operator InputActionMap(LeftHandActions set) { return set.Get(); }
public void AddCallbacks(ILeftHandActions instance)
{
if (instance == null || m_Wrapper.m_LeftHandActionsCallbackInterfaces.Contains(instance)) return;
m_Wrapper.m_LeftHandActionsCallbackInterfaces.Add(instance);
@TriggerPress.started += instance.OnTriggerPress;
@TriggerPress.performed += instance.OnTriggerPress;
@TriggerPress.canceled += instance.OnTriggerPress;
@Trigger.started += instance.OnTrigger;
@Trigger.performed += instance.OnTrigger;
@Trigger.canceled += instance.OnTrigger;
@PrimaryButton.started += instance.OnPrimaryButton;
@PrimaryButton.performed += instance.OnPrimaryButton;
@PrimaryButton.canceled += instance.OnPrimaryButton;
@PrimaryTouch.started += instance.OnPrimaryTouch;
@PrimaryTouch.performed += instance.OnPrimaryTouch;
@PrimaryTouch.canceled += instance.OnPrimaryTouch;
@Menu.started += instance.OnMenu;
@Menu.performed += instance.OnMenu;
@Menu.canceled += instance.OnMenu;
@Primary2DAxis.started += instance.OnPrimary2DAxis;
@Primary2DAxis.performed += instance.OnPrimary2DAxis;
@Primary2DAxis.canceled += instance.OnPrimary2DAxis;
@Primary2DAxisClick.started += instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.performed += instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.canceled += instance.OnPrimary2DAxisClick;
@Primary2DAxisTouch.started += instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.performed += instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.canceled += instance.OnPrimary2DAxisTouch;
@Secondary2DAxis.started += instance.OnSecondary2DAxis;
@Secondary2DAxis.performed += instance.OnSecondary2DAxis;
@Secondary2DAxis.canceled += instance.OnSecondary2DAxis;
@Secondary2DAxisClick.started += instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.performed += instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.canceled += instance.OnSecondary2DAxisClick;
@Secondary2DAxisTouch.started += instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.performed += instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.canceled += instance.OnSecondary2DAxisTouch;
@Grip.started += instance.OnGrip;
@Grip.performed += instance.OnGrip;
@Grip.canceled += instance.OnGrip;
@GripPress.started += instance.OnGripPress;
@GripPress.performed += instance.OnGripPress;
@GripPress.canceled += instance.OnGripPress;
@GripForce.started += instance.OnGripForce;
@GripForce.performed += instance.OnGripForce;
@GripForce.canceled += instance.OnGripForce;
@SecondaryButton.started += instance.OnSecondaryButton;
@SecondaryButton.performed += instance.OnSecondaryButton;
@SecondaryButton.canceled += instance.OnSecondaryButton;
@SecondaryTouch.started += instance.OnSecondaryTouch;
@SecondaryTouch.performed += instance.OnSecondaryTouch;
@SecondaryTouch.canceled += instance.OnSecondaryTouch;
@TriggerTouch.started += instance.OnTriggerTouch;
@TriggerTouch.performed += instance.OnTriggerTouch;
@TriggerTouch.canceled += instance.OnTriggerTouch;
@ControllerPosition.started += instance.OnControllerPosition;
@ControllerPosition.performed += instance.OnControllerPosition;
@ControllerPosition.canceled += instance.OnControllerPosition;
@ControllerRotation.started += instance.OnControllerRotation;
@ControllerRotation.performed += instance.OnControllerRotation;
@ControllerRotation.canceled += instance.OnControllerRotation;
@Haptics.started += instance.OnHaptics;
@Haptics.performed += instance.OnHaptics;
@Haptics.canceled += instance.OnHaptics;
}
private void UnregisterCallbacks(ILeftHandActions instance)
{
@TriggerPress.started -= instance.OnTriggerPress;
@TriggerPress.performed -= instance.OnTriggerPress;
@TriggerPress.canceled -= instance.OnTriggerPress;
@Trigger.started -= instance.OnTrigger;
@Trigger.performed -= instance.OnTrigger;
@Trigger.canceled -= instance.OnTrigger;
@PrimaryButton.started -= instance.OnPrimaryButton;
@PrimaryButton.performed -= instance.OnPrimaryButton;
@PrimaryButton.canceled -= instance.OnPrimaryButton;
@PrimaryTouch.started -= instance.OnPrimaryTouch;
@PrimaryTouch.performed -= instance.OnPrimaryTouch;
@PrimaryTouch.canceled -= instance.OnPrimaryTouch;
@Menu.started -= instance.OnMenu;
@Menu.performed -= instance.OnMenu;
@Menu.canceled -= instance.OnMenu;
@Primary2DAxis.started -= instance.OnPrimary2DAxis;
@Primary2DAxis.performed -= instance.OnPrimary2DAxis;
@Primary2DAxis.canceled -= instance.OnPrimary2DAxis;
@Primary2DAxisClick.started -= instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.performed -= instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.canceled -= instance.OnPrimary2DAxisClick;
@Primary2DAxisTouch.started -= instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.performed -= instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.canceled -= instance.OnPrimary2DAxisTouch;
@Secondary2DAxis.started -= instance.OnSecondary2DAxis;
@Secondary2DAxis.performed -= instance.OnSecondary2DAxis;
@Secondary2DAxis.canceled -= instance.OnSecondary2DAxis;
@Secondary2DAxisClick.started -= instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.performed -= instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.canceled -= instance.OnSecondary2DAxisClick;
@Secondary2DAxisTouch.started -= instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.performed -= instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.canceled -= instance.OnSecondary2DAxisTouch;
@Grip.started -= instance.OnGrip;
@Grip.performed -= instance.OnGrip;
@Grip.canceled -= instance.OnGrip;
@GripPress.started -= instance.OnGripPress;
@GripPress.performed -= instance.OnGripPress;
@GripPress.canceled -= instance.OnGripPress;
@GripForce.started -= instance.OnGripForce;
@GripForce.performed -= instance.OnGripForce;
@GripForce.canceled -= instance.OnGripForce;
@SecondaryButton.started -= instance.OnSecondaryButton;
@SecondaryButton.performed -= instance.OnSecondaryButton;
@SecondaryButton.canceled -= instance.OnSecondaryButton;
@SecondaryTouch.started -= instance.OnSecondaryTouch;
@SecondaryTouch.performed -= instance.OnSecondaryTouch;
@SecondaryTouch.canceled -= instance.OnSecondaryTouch;
@TriggerTouch.started -= instance.OnTriggerTouch;
@TriggerTouch.performed -= instance.OnTriggerTouch;
@TriggerTouch.canceled -= instance.OnTriggerTouch;
@ControllerPosition.started -= instance.OnControllerPosition;
@ControllerPosition.performed -= instance.OnControllerPosition;
@ControllerPosition.canceled -= instance.OnControllerPosition;
@ControllerRotation.started -= instance.OnControllerRotation;
@ControllerRotation.performed -= instance.OnControllerRotation;
@ControllerRotation.canceled -= instance.OnControllerRotation;
@Haptics.started -= instance.OnHaptics;
@Haptics.performed -= instance.OnHaptics;
@Haptics.canceled -= instance.OnHaptics;
}
public void RemoveCallbacks(ILeftHandActions instance)
{
if (m_Wrapper.m_LeftHandActionsCallbackInterfaces.Remove(instance))
UnregisterCallbacks(instance);
}
public void SetCallbacks(ILeftHandActions instance)
{
if (m_Wrapper.m_LeftHandActionsCallbackInterface != null)
{
@TriggerPress.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTriggerPress;
@TriggerPress.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTriggerPress;
@TriggerPress.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTriggerPress;
@Trigger.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTrigger;
@Trigger.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTrigger;
@Trigger.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTrigger;
@PrimaryButton.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimaryButton;
@PrimaryButton.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimaryButton;
@PrimaryButton.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimaryButton;
@PrimaryTouch.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimaryTouch;
@PrimaryTouch.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimaryTouch;
@PrimaryTouch.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimaryTouch;
@Menu.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnMenu;
@Menu.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnMenu;
@Menu.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnMenu;
@Primary2DAxis.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxis;
@Primary2DAxis.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxis;
@Primary2DAxis.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxis;
@Primary2DAxisClick.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxisClick;
@Primary2DAxisClick.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxisClick;
@Primary2DAxisClick.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxisClick;
@Primary2DAxisTouch.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnPrimary2DAxisTouch;
@Secondary2DAxis.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxis;
@Secondary2DAxis.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxis;
@Secondary2DAxis.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxis;
@Secondary2DAxisClick.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxisClick;
@Secondary2DAxisClick.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxisClick;
@Secondary2DAxisClick.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxisClick;
@Secondary2DAxisTouch.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondary2DAxisTouch;
@Grip.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGrip;
@Grip.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGrip;
@Grip.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGrip;
@GripPress.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGripPress;
@GripPress.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGripPress;
@GripPress.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGripPress;
@GripForce.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGripForce;
@GripForce.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGripForce;
@GripForce.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnGripForce;
@SecondaryButton.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondaryButton;
@SecondaryButton.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondaryButton;
@SecondaryButton.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondaryButton;
@SecondaryTouch.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondaryTouch;
@SecondaryTouch.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondaryTouch;
@SecondaryTouch.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnSecondaryTouch;
@TriggerTouch.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTriggerTouch;
@TriggerTouch.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTriggerTouch;
@TriggerTouch.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnTriggerTouch;
@ControllerPosition.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnControllerPosition;
@ControllerPosition.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnControllerPosition;
@ControllerPosition.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnControllerPosition;
@ControllerRotation.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnControllerRotation;
@ControllerRotation.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnControllerRotation;
@ControllerRotation.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnControllerRotation;
@Haptics.started -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnHaptics;
@Haptics.performed -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnHaptics;
@Haptics.canceled -= m_Wrapper.m_LeftHandActionsCallbackInterface.OnHaptics;
}
m_Wrapper.m_LeftHandActionsCallbackInterface = instance;
if (instance != null)
{
@TriggerPress.started += instance.OnTriggerPress;
@TriggerPress.performed += instance.OnTriggerPress;
@TriggerPress.canceled += instance.OnTriggerPress;
@Trigger.started += instance.OnTrigger;
@Trigger.performed += instance.OnTrigger;
@Trigger.canceled += instance.OnTrigger;
@PrimaryButton.started += instance.OnPrimaryButton;
@PrimaryButton.performed += instance.OnPrimaryButton;
@PrimaryButton.canceled += instance.OnPrimaryButton;
@PrimaryTouch.started += instance.OnPrimaryTouch;
@PrimaryTouch.performed += instance.OnPrimaryTouch;
@PrimaryTouch.canceled += instance.OnPrimaryTouch;
@Menu.started += instance.OnMenu;
@Menu.performed += instance.OnMenu;
@Menu.canceled += instance.OnMenu;
@Primary2DAxis.started += instance.OnPrimary2DAxis;
@Primary2DAxis.performed += instance.OnPrimary2DAxis;
@Primary2DAxis.canceled += instance.OnPrimary2DAxis;
@Primary2DAxisClick.started += instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.performed += instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.canceled += instance.OnPrimary2DAxisClick;
@Primary2DAxisTouch.started += instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.performed += instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.canceled += instance.OnPrimary2DAxisTouch;
@Secondary2DAxis.started += instance.OnSecondary2DAxis;
@Secondary2DAxis.performed += instance.OnSecondary2DAxis;
@Secondary2DAxis.canceled += instance.OnSecondary2DAxis;
@Secondary2DAxisClick.started += instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.performed += instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.canceled += instance.OnSecondary2DAxisClick;
@Secondary2DAxisTouch.started += instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.performed += instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.canceled += instance.OnSecondary2DAxisTouch;
@Grip.started += instance.OnGrip;
@Grip.performed += instance.OnGrip;
@Grip.canceled += instance.OnGrip;
@GripPress.started += instance.OnGripPress;
@GripPress.performed += instance.OnGripPress;
@GripPress.canceled += instance.OnGripPress;
@GripForce.started += instance.OnGripForce;
@GripForce.performed += instance.OnGripForce;
@GripForce.canceled += instance.OnGripForce;
@SecondaryButton.started += instance.OnSecondaryButton;
@SecondaryButton.performed += instance.OnSecondaryButton;
@SecondaryButton.canceled += instance.OnSecondaryButton;
@SecondaryTouch.started += instance.OnSecondaryTouch;
@SecondaryTouch.performed += instance.OnSecondaryTouch;
@SecondaryTouch.canceled += instance.OnSecondaryTouch;
@TriggerTouch.started += instance.OnTriggerTouch;
@TriggerTouch.performed += instance.OnTriggerTouch;
@TriggerTouch.canceled += instance.OnTriggerTouch;
@ControllerPosition.started += instance.OnControllerPosition;
@ControllerPosition.performed += instance.OnControllerPosition;
@ControllerPosition.canceled += instance.OnControllerPosition;
@ControllerRotation.started += instance.OnControllerRotation;
@ControllerRotation.performed += instance.OnControllerRotation;
@ControllerRotation.canceled += instance.OnControllerRotation;
@Haptics.started += instance.OnHaptics;
@Haptics.performed += instance.OnHaptics;
@Haptics.canceled += instance.OnHaptics;
}
foreach (var item in m_Wrapper.m_LeftHandActionsCallbackInterfaces)
UnregisterCallbacks(item);
m_Wrapper.m_LeftHandActionsCallbackInterfaces.Clear();
AddCallbacks(instance);
}
}
public LeftHandActions @LeftHand => new LeftHandActions(this);
// RightHand
private readonly InputActionMap m_RightHand;
private IRightHandActions m_RightHandActionsCallbackInterface;
private List<IRightHandActions> m_RightHandActionsCallbackInterfaces = new List<IRightHandActions>();
private readonly InputAction m_RightHand_TriggerPress;
private readonly InputAction m_RightHand_Trigger;
private readonly InputAction m_RightHand_PrimaryButton;
@@ -1415,142 +1463,155 @@ public partial class @HVRInputActions : IInputActionCollection2, IDisposable
public void Disable() { Get().Disable(); }
public bool enabled => Get().enabled;
public static implicit operator InputActionMap(RightHandActions set) { return set.Get(); }
public void AddCallbacks(IRightHandActions instance)
{
if (instance == null || m_Wrapper.m_RightHandActionsCallbackInterfaces.Contains(instance)) return;
m_Wrapper.m_RightHandActionsCallbackInterfaces.Add(instance);
@TriggerPress.started += instance.OnTriggerPress;
@TriggerPress.performed += instance.OnTriggerPress;
@TriggerPress.canceled += instance.OnTriggerPress;
@Trigger.started += instance.OnTrigger;
@Trigger.performed += instance.OnTrigger;
@Trigger.canceled += instance.OnTrigger;
@PrimaryButton.started += instance.OnPrimaryButton;
@PrimaryButton.performed += instance.OnPrimaryButton;
@PrimaryButton.canceled += instance.OnPrimaryButton;
@PrimaryTouch.started += instance.OnPrimaryTouch;
@PrimaryTouch.performed += instance.OnPrimaryTouch;
@PrimaryTouch.canceled += instance.OnPrimaryTouch;
@Menu.started += instance.OnMenu;
@Menu.performed += instance.OnMenu;
@Menu.canceled += instance.OnMenu;
@Primary2DAxis.started += instance.OnPrimary2DAxis;
@Primary2DAxis.performed += instance.OnPrimary2DAxis;
@Primary2DAxis.canceled += instance.OnPrimary2DAxis;
@Primary2DAxisClick.started += instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.performed += instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.canceled += instance.OnPrimary2DAxisClick;
@Primary2DAxisTouch.started += instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.performed += instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.canceled += instance.OnPrimary2DAxisTouch;
@Secondary2DAxis.started += instance.OnSecondary2DAxis;
@Secondary2DAxis.performed += instance.OnSecondary2DAxis;
@Secondary2DAxis.canceled += instance.OnSecondary2DAxis;
@Secondary2DAxisClick.started += instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.performed += instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.canceled += instance.OnSecondary2DAxisClick;
@Secondary2DAxisTouch.started += instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.performed += instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.canceled += instance.OnSecondary2DAxisTouch;
@Grip.started += instance.OnGrip;
@Grip.performed += instance.OnGrip;
@Grip.canceled += instance.OnGrip;
@GripPress.started += instance.OnGripPress;
@GripPress.performed += instance.OnGripPress;
@GripPress.canceled += instance.OnGripPress;
@GripForce.started += instance.OnGripForce;
@GripForce.performed += instance.OnGripForce;
@GripForce.canceled += instance.OnGripForce;
@SecondaryButton.started += instance.OnSecondaryButton;
@SecondaryButton.performed += instance.OnSecondaryButton;
@SecondaryButton.canceled += instance.OnSecondaryButton;
@SecondaryTouch.started += instance.OnSecondaryTouch;
@SecondaryTouch.performed += instance.OnSecondaryTouch;
@SecondaryTouch.canceled += instance.OnSecondaryTouch;
@TriggerTouch.started += instance.OnTriggerTouch;
@TriggerTouch.performed += instance.OnTriggerTouch;
@TriggerTouch.canceled += instance.OnTriggerTouch;
@ControllerPosition.started += instance.OnControllerPosition;
@ControllerPosition.performed += instance.OnControllerPosition;
@ControllerPosition.canceled += instance.OnControllerPosition;
@ControllerRotation.started += instance.OnControllerRotation;
@ControllerRotation.performed += instance.OnControllerRotation;
@ControllerRotation.canceled += instance.OnControllerRotation;
@Haptics.started += instance.OnHaptics;
@Haptics.performed += instance.OnHaptics;
@Haptics.canceled += instance.OnHaptics;
}
private void UnregisterCallbacks(IRightHandActions instance)
{
@TriggerPress.started -= instance.OnTriggerPress;
@TriggerPress.performed -= instance.OnTriggerPress;
@TriggerPress.canceled -= instance.OnTriggerPress;
@Trigger.started -= instance.OnTrigger;
@Trigger.performed -= instance.OnTrigger;
@Trigger.canceled -= instance.OnTrigger;
@PrimaryButton.started -= instance.OnPrimaryButton;
@PrimaryButton.performed -= instance.OnPrimaryButton;
@PrimaryButton.canceled -= instance.OnPrimaryButton;
@PrimaryTouch.started -= instance.OnPrimaryTouch;
@PrimaryTouch.performed -= instance.OnPrimaryTouch;
@PrimaryTouch.canceled -= instance.OnPrimaryTouch;
@Menu.started -= instance.OnMenu;
@Menu.performed -= instance.OnMenu;
@Menu.canceled -= instance.OnMenu;
@Primary2DAxis.started -= instance.OnPrimary2DAxis;
@Primary2DAxis.performed -= instance.OnPrimary2DAxis;
@Primary2DAxis.canceled -= instance.OnPrimary2DAxis;
@Primary2DAxisClick.started -= instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.performed -= instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.canceled -= instance.OnPrimary2DAxisClick;
@Primary2DAxisTouch.started -= instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.performed -= instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.canceled -= instance.OnPrimary2DAxisTouch;
@Secondary2DAxis.started -= instance.OnSecondary2DAxis;
@Secondary2DAxis.performed -= instance.OnSecondary2DAxis;
@Secondary2DAxis.canceled -= instance.OnSecondary2DAxis;
@Secondary2DAxisClick.started -= instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.performed -= instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.canceled -= instance.OnSecondary2DAxisClick;
@Secondary2DAxisTouch.started -= instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.performed -= instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.canceled -= instance.OnSecondary2DAxisTouch;
@Grip.started -= instance.OnGrip;
@Grip.performed -= instance.OnGrip;
@Grip.canceled -= instance.OnGrip;
@GripPress.started -= instance.OnGripPress;
@GripPress.performed -= instance.OnGripPress;
@GripPress.canceled -= instance.OnGripPress;
@GripForce.started -= instance.OnGripForce;
@GripForce.performed -= instance.OnGripForce;
@GripForce.canceled -= instance.OnGripForce;
@SecondaryButton.started -= instance.OnSecondaryButton;
@SecondaryButton.performed -= instance.OnSecondaryButton;
@SecondaryButton.canceled -= instance.OnSecondaryButton;
@SecondaryTouch.started -= instance.OnSecondaryTouch;
@SecondaryTouch.performed -= instance.OnSecondaryTouch;
@SecondaryTouch.canceled -= instance.OnSecondaryTouch;
@TriggerTouch.started -= instance.OnTriggerTouch;
@TriggerTouch.performed -= instance.OnTriggerTouch;
@TriggerTouch.canceled -= instance.OnTriggerTouch;
@ControllerPosition.started -= instance.OnControllerPosition;
@ControllerPosition.performed -= instance.OnControllerPosition;
@ControllerPosition.canceled -= instance.OnControllerPosition;
@ControllerRotation.started -= instance.OnControllerRotation;
@ControllerRotation.performed -= instance.OnControllerRotation;
@ControllerRotation.canceled -= instance.OnControllerRotation;
@Haptics.started -= instance.OnHaptics;
@Haptics.performed -= instance.OnHaptics;
@Haptics.canceled -= instance.OnHaptics;
}
public void RemoveCallbacks(IRightHandActions instance)
{
if (m_Wrapper.m_RightHandActionsCallbackInterfaces.Remove(instance))
UnregisterCallbacks(instance);
}
public void SetCallbacks(IRightHandActions instance)
{
if (m_Wrapper.m_RightHandActionsCallbackInterface != null)
{
@TriggerPress.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTriggerPress;
@TriggerPress.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTriggerPress;
@TriggerPress.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTriggerPress;
@Trigger.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTrigger;
@Trigger.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTrigger;
@Trigger.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTrigger;
@PrimaryButton.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimaryButton;
@PrimaryButton.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimaryButton;
@PrimaryButton.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimaryButton;
@PrimaryTouch.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimaryTouch;
@PrimaryTouch.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimaryTouch;
@PrimaryTouch.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimaryTouch;
@Menu.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnMenu;
@Menu.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnMenu;
@Menu.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnMenu;
@Primary2DAxis.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxis;
@Primary2DAxis.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxis;
@Primary2DAxis.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxis;
@Primary2DAxisClick.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxisClick;
@Primary2DAxisClick.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxisClick;
@Primary2DAxisClick.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxisClick;
@Primary2DAxisTouch.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnPrimary2DAxisTouch;
@Secondary2DAxis.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxis;
@Secondary2DAxis.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxis;
@Secondary2DAxis.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxis;
@Secondary2DAxisClick.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxisClick;
@Secondary2DAxisClick.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxisClick;
@Secondary2DAxisClick.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxisClick;
@Secondary2DAxisTouch.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondary2DAxisTouch;
@Grip.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGrip;
@Grip.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGrip;
@Grip.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGrip;
@GripPress.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGripPress;
@GripPress.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGripPress;
@GripPress.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGripPress;
@GripForce.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGripForce;
@GripForce.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGripForce;
@GripForce.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnGripForce;
@SecondaryButton.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondaryButton;
@SecondaryButton.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondaryButton;
@SecondaryButton.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondaryButton;
@SecondaryTouch.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondaryTouch;
@SecondaryTouch.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondaryTouch;
@SecondaryTouch.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnSecondaryTouch;
@TriggerTouch.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTriggerTouch;
@TriggerTouch.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTriggerTouch;
@TriggerTouch.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnTriggerTouch;
@ControllerPosition.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnControllerPosition;
@ControllerPosition.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnControllerPosition;
@ControllerPosition.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnControllerPosition;
@ControllerRotation.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnControllerRotation;
@ControllerRotation.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnControllerRotation;
@ControllerRotation.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnControllerRotation;
@Haptics.started -= m_Wrapper.m_RightHandActionsCallbackInterface.OnHaptics;
@Haptics.performed -= m_Wrapper.m_RightHandActionsCallbackInterface.OnHaptics;
@Haptics.canceled -= m_Wrapper.m_RightHandActionsCallbackInterface.OnHaptics;
}
m_Wrapper.m_RightHandActionsCallbackInterface = instance;
if (instance != null)
{
@TriggerPress.started += instance.OnTriggerPress;
@TriggerPress.performed += instance.OnTriggerPress;
@TriggerPress.canceled += instance.OnTriggerPress;
@Trigger.started += instance.OnTrigger;
@Trigger.performed += instance.OnTrigger;
@Trigger.canceled += instance.OnTrigger;
@PrimaryButton.started += instance.OnPrimaryButton;
@PrimaryButton.performed += instance.OnPrimaryButton;
@PrimaryButton.canceled += instance.OnPrimaryButton;
@PrimaryTouch.started += instance.OnPrimaryTouch;
@PrimaryTouch.performed += instance.OnPrimaryTouch;
@PrimaryTouch.canceled += instance.OnPrimaryTouch;
@Menu.started += instance.OnMenu;
@Menu.performed += instance.OnMenu;
@Menu.canceled += instance.OnMenu;
@Primary2DAxis.started += instance.OnPrimary2DAxis;
@Primary2DAxis.performed += instance.OnPrimary2DAxis;
@Primary2DAxis.canceled += instance.OnPrimary2DAxis;
@Primary2DAxisClick.started += instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.performed += instance.OnPrimary2DAxisClick;
@Primary2DAxisClick.canceled += instance.OnPrimary2DAxisClick;
@Primary2DAxisTouch.started += instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.performed += instance.OnPrimary2DAxisTouch;
@Primary2DAxisTouch.canceled += instance.OnPrimary2DAxisTouch;
@Secondary2DAxis.started += instance.OnSecondary2DAxis;
@Secondary2DAxis.performed += instance.OnSecondary2DAxis;
@Secondary2DAxis.canceled += instance.OnSecondary2DAxis;
@Secondary2DAxisClick.started += instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.performed += instance.OnSecondary2DAxisClick;
@Secondary2DAxisClick.canceled += instance.OnSecondary2DAxisClick;
@Secondary2DAxisTouch.started += instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.performed += instance.OnSecondary2DAxisTouch;
@Secondary2DAxisTouch.canceled += instance.OnSecondary2DAxisTouch;
@Grip.started += instance.OnGrip;
@Grip.performed += instance.OnGrip;
@Grip.canceled += instance.OnGrip;
@GripPress.started += instance.OnGripPress;
@GripPress.performed += instance.OnGripPress;
@GripPress.canceled += instance.OnGripPress;
@GripForce.started += instance.OnGripForce;
@GripForce.performed += instance.OnGripForce;
@GripForce.canceled += instance.OnGripForce;
@SecondaryButton.started += instance.OnSecondaryButton;
@SecondaryButton.performed += instance.OnSecondaryButton;
@SecondaryButton.canceled += instance.OnSecondaryButton;
@SecondaryTouch.started += instance.OnSecondaryTouch;
@SecondaryTouch.performed += instance.OnSecondaryTouch;
@SecondaryTouch.canceled += instance.OnSecondaryTouch;
@TriggerTouch.started += instance.OnTriggerTouch;
@TriggerTouch.performed += instance.OnTriggerTouch;
@TriggerTouch.canceled += instance.OnTriggerTouch;
@ControllerPosition.started += instance.OnControllerPosition;
@ControllerPosition.performed += instance.OnControllerPosition;
@ControllerPosition.canceled += instance.OnControllerPosition;
@ControllerRotation.started += instance.OnControllerRotation;
@ControllerRotation.performed += instance.OnControllerRotation;
@ControllerRotation.canceled += instance.OnControllerRotation;
@Haptics.started += instance.OnHaptics;
@Haptics.performed += instance.OnHaptics;
@Haptics.canceled += instance.OnHaptics;
}
foreach (var item in m_Wrapper.m_RightHandActionsCallbackInterfaces)
UnregisterCallbacks(item);
m_Wrapper.m_RightHandActionsCallbackInterfaces.Clear();
AddCallbacks(instance);
}
}
public RightHandActions @RightHand => new RightHandActions(this);
// HMD
private readonly InputActionMap m_HMD;
private IHMDActions m_HMDActionsCallbackInterface;
private List<IHMDActions> m_HMDActionsCallbackInterfaces = new List<IHMDActions>();
private readonly InputAction m_HMD_hmdPosition;
private readonly InputAction m_HMD_hmdRotation;
public struct HMDActions
@@ -1564,34 +1625,47 @@ public partial class @HVRInputActions : IInputActionCollection2, IDisposable
public void Disable() { Get().Disable(); }
public bool enabled => Get().enabled;
public static implicit operator InputActionMap(HMDActions set) { return set.Get(); }
public void AddCallbacks(IHMDActions instance)
{
if (instance == null || m_Wrapper.m_HMDActionsCallbackInterfaces.Contains(instance)) return;
m_Wrapper.m_HMDActionsCallbackInterfaces.Add(instance);
@hmdPosition.started += instance.OnHmdPosition;
@hmdPosition.performed += instance.OnHmdPosition;
@hmdPosition.canceled += instance.OnHmdPosition;
@hmdRotation.started += instance.OnHmdRotation;
@hmdRotation.performed += instance.OnHmdRotation;
@hmdRotation.canceled += instance.OnHmdRotation;
}
private void UnregisterCallbacks(IHMDActions instance)
{
@hmdPosition.started -= instance.OnHmdPosition;
@hmdPosition.performed -= instance.OnHmdPosition;
@hmdPosition.canceled -= instance.OnHmdPosition;
@hmdRotation.started -= instance.OnHmdRotation;
@hmdRotation.performed -= instance.OnHmdRotation;
@hmdRotation.canceled -= instance.OnHmdRotation;
}
public void RemoveCallbacks(IHMDActions instance)
{
if (m_Wrapper.m_HMDActionsCallbackInterfaces.Remove(instance))
UnregisterCallbacks(instance);
}
public void SetCallbacks(IHMDActions instance)
{
if (m_Wrapper.m_HMDActionsCallbackInterface != null)
{
@hmdPosition.started -= m_Wrapper.m_HMDActionsCallbackInterface.OnHmdPosition;
@hmdPosition.performed -= m_Wrapper.m_HMDActionsCallbackInterface.OnHmdPosition;
@hmdPosition.canceled -= m_Wrapper.m_HMDActionsCallbackInterface.OnHmdPosition;
@hmdRotation.started -= m_Wrapper.m_HMDActionsCallbackInterface.OnHmdRotation;
@hmdRotation.performed -= m_Wrapper.m_HMDActionsCallbackInterface.OnHmdRotation;
@hmdRotation.canceled -= m_Wrapper.m_HMDActionsCallbackInterface.OnHmdRotation;
}
m_Wrapper.m_HMDActionsCallbackInterface = instance;
if (instance != null)
{
@hmdPosition.started += instance.OnHmdPosition;
@hmdPosition.performed += instance.OnHmdPosition;
@hmdPosition.canceled += instance.OnHmdPosition;
@hmdRotation.started += instance.OnHmdRotation;
@hmdRotation.performed += instance.OnHmdRotation;
@hmdRotation.canceled += instance.OnHmdRotation;
}
foreach (var item in m_Wrapper.m_HMDActionsCallbackInterfaces)
UnregisterCallbacks(item);
m_Wrapper.m_HMDActionsCallbackInterfaces.Clear();
AddCallbacks(instance);
}
}
public HMDActions @HMD => new HMDActions(this);
// UI
private readonly InputActionMap m_UI;
private IUIActions m_UIActionsCallbackInterface;
private List<IUIActions> m_UIActionsCallbackInterfaces = new List<IUIActions>();
private readonly InputAction m_UI_Click;
private readonly InputAction m_UI_pointerPosition;
private readonly InputAction m_UI_pointerRotation;
@@ -1607,33 +1681,46 @@ public partial class @HVRInputActions : IInputActionCollection2, IDisposable
public void Disable() { Get().Disable(); }
public bool enabled => Get().enabled;
public static implicit operator InputActionMap(UIActions set) { return set.Get(); }
public void AddCallbacks(IUIActions instance)
{
if (instance == null || m_Wrapper.m_UIActionsCallbackInterfaces.Contains(instance)) return;
m_Wrapper.m_UIActionsCallbackInterfaces.Add(instance);
@Click.started += instance.OnClick;
@Click.performed += instance.OnClick;
@Click.canceled += instance.OnClick;
@pointerPosition.started += instance.OnPointerPosition;
@pointerPosition.performed += instance.OnPointerPosition;
@pointerPosition.canceled += instance.OnPointerPosition;
@pointerRotation.started += instance.OnPointerRotation;
@pointerRotation.performed += instance.OnPointerRotation;
@pointerRotation.canceled += instance.OnPointerRotation;
}
private void UnregisterCallbacks(IUIActions instance)
{
@Click.started -= instance.OnClick;
@Click.performed -= instance.OnClick;
@Click.canceled -= instance.OnClick;
@pointerPosition.started -= instance.OnPointerPosition;
@pointerPosition.performed -= instance.OnPointerPosition;
@pointerPosition.canceled -= instance.OnPointerPosition;
@pointerRotation.started -= instance.OnPointerRotation;
@pointerRotation.performed -= instance.OnPointerRotation;
@pointerRotation.canceled -= instance.OnPointerRotation;
}
public void RemoveCallbacks(IUIActions instance)
{
if (m_Wrapper.m_UIActionsCallbackInterfaces.Remove(instance))
UnregisterCallbacks(instance);
}
public void SetCallbacks(IUIActions instance)
{
if (m_Wrapper.m_UIActionsCallbackInterface != null)
{
@Click.started -= m_Wrapper.m_UIActionsCallbackInterface.OnClick;
@Click.performed -= m_Wrapper.m_UIActionsCallbackInterface.OnClick;
@Click.canceled -= m_Wrapper.m_UIActionsCallbackInterface.OnClick;
@pointerPosition.started -= m_Wrapper.m_UIActionsCallbackInterface.OnPointerPosition;
@pointerPosition.performed -= m_Wrapper.m_UIActionsCallbackInterface.OnPointerPosition;
@pointerPosition.canceled -= m_Wrapper.m_UIActionsCallbackInterface.OnPointerPosition;
@pointerRotation.started -= m_Wrapper.m_UIActionsCallbackInterface.OnPointerRotation;
@pointerRotation.performed -= m_Wrapper.m_UIActionsCallbackInterface.OnPointerRotation;
@pointerRotation.canceled -= m_Wrapper.m_UIActionsCallbackInterface.OnPointerRotation;
}
m_Wrapper.m_UIActionsCallbackInterface = instance;
if (instance != null)
{
@Click.started += instance.OnClick;
@Click.performed += instance.OnClick;
@Click.canceled += instance.OnClick;
@pointerPosition.started += instance.OnPointerPosition;
@pointerPosition.performed += instance.OnPointerPosition;
@pointerPosition.canceled += instance.OnPointerPosition;
@pointerRotation.started += instance.OnPointerRotation;
@pointerRotation.performed += instance.OnPointerRotation;
@pointerRotation.canceled += instance.OnPointerRotation;
}
foreach (var item in m_Wrapper.m_UIActionsCallbackInterfaces)
UnregisterCallbacks(item);
m_Wrapper.m_UIActionsCallbackInterfaces.Clear();
AddCallbacks(instance);
}
}
public UIActions @UI => new UIActions(this);
@@ -233,6 +233,28 @@
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "692f48f9-3f21-406f-b2d5-5b5e0c4c2761",
"path": "<OculusTouchController>{LeftHand}/menu",
"interactions": "",
"processors": "",
"groups": "",
"action": "Menu",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "d55f9044-c561-4b40-957b-ad0bd93adc50",
"path": "<WMRSpatialController>{LeftHand}/menu",
"interactions": "",
"processors": "",
"groups": "",
"action": "Menu",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "54ac7ab0-8ca9-4cbc-a6d1-da5ee0b055cb",
@@ -676,6 +698,17 @@
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "0c608bc0-1dda-4d95-8e76-add87e298bcc",
"path": "<WMRSpatialController>{LeftHand}/menu",
"interactions": "",
"processors": "",
"groups": "",
"action": "Menu",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "488857b2-965c-486c-b24e-e21628ad2a07",
@@ -7,6 +7,9 @@ using UnityEngine;
namespace HurricaneVR.Framework.Core.Bags
{
/// <summary>
/// Used by the hand to detect sockets for removing objects from them
/// </summary>
public class HVRSocketBag : MonoBehaviour, IComparer<HVRSocket>
{
private readonly Dictionary<HVRSocket, HashSet<Collider>> _map = new Dictionary<HVRSocket, HashSet<Collider>>();
@@ -53,6 +56,9 @@ namespace HurricaneVR.Framework.Core.Bags
Calculate();
}
/// <summary>
/// Causes the bag to ignore the provided socket when it's trigger collider overlaps ours.
/// </summary>
public void IgnoreSocket(HVRSocket socket)
{
if (_ignoredSockets == null)
@@ -63,6 +69,14 @@ namespace HurricaneVR.Framework.Core.Bags
_ignoredSockets.Add(socket);
}
/// <summary>
/// Stops ignoring the provided socket
/// </summary>
public void UnIgnoreSocket(HVRSocket socket)
{
_ignoredSockets.Remove(socket);
}
protected void AddSocket(HVRSocket socket)
{
if (AllSockets.Contains(socket))
@@ -209,6 +209,9 @@ namespace HurricaneVR.Framework.Core.Grabbers
public override bool CanGrab(HVRGrabbable grabbable)
{
if (!grabbable.CanHandGrab(HandGrabber))
return false;
if (grabbable.IsSocketed)
return false;
@@ -267,6 +270,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
args.Grabbable.IsBeingForcedGrabbed = true;
IsForceGrabbing = true;
if (GrabStyle == HVRForceGrabMode.GravityGloves)
{
@@ -288,6 +292,13 @@ namespace HurricaneVR.Framework.Core.Grabbers
OnGrabbedHaptics();
}
protected override void OnReleased(HVRGrabbable grabbable)
{
base.OnReleased(grabbable);
grabbable.IsBeingForcedGrabbed = false;
}
protected override void OnHoverEnter(HVRGrabbable grabbable)
{
base.OnHoverEnter(grabbable);
@@ -366,7 +377,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
rb.angularDrag = 0f;
rb.drag = 0f;
grabbable.IsBeingForcedGrabbed = true;
IsHoldActive = true;
var grabPoint = grabbable.GetGrabPointTransform(HandGrabber, GrabpointFilter.ForceGrab);
@@ -434,7 +444,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
var delta = JointAnchorWorldPosition - grabbableAnchor;
distance = delta.magnitude;
if (isPhysicsGrab && distance < DynamicGrabThreshold && HandGrabber.TryAutoGrab(grabbable, posableGrabPoint))
if (isPhysicsGrab && distance < DynamicGrabThreshold && HandGrabber.TryTransferDistanceGrab(grabbable, posableGrabPoint))
{
rb.angularVelocity = Vector3.zero;
rb.velocity = Vector3.zero;
@@ -513,12 +523,13 @@ namespace HurricaneVR.Framework.Core.Grabbers
rb.velocity = Vector3.ClampMagnitude(rb.velocity, settings.MaxMissSpeed);
rb.angularVelocity = Vector3.ClampMagnitude(rb.angularVelocity, settings.MaxMissAngularSpeed);
rb.centerOfMass = com;
if (IsGrabbing)
{
if (distance < limit)
{
if (HandGrabber.TryAutoGrab(grabbable, posableGrabPoint))
if (HandGrabber.TryTransferDistanceGrab(grabbable, posableGrabPoint))
{
rb.angularVelocity = Vector3.zero;
rb.velocity = Vector3.zero;
@@ -529,9 +540,14 @@ namespace HurricaneVR.Framework.Core.Grabbers
ForceRelease();
}
}
grabbable.IsBeingForcedGrabbed = false;
else
{
HandGrabber.EnableHandCollision(grabbable);
ForceRelease();
}
}
}
}
@@ -558,7 +574,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
_grabbableCollided = false;
IsHoldActive = true;
grabbable.IsBeingForcedGrabbed = true;
grabbable.Rigidbody.useGravity = false;
grabbable.Rigidbody.drag = 0f;
grabbable.Rigidbody.angularDrag = 0f;
@@ -621,7 +637,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
if (AutoGrab && HandGrabber.IsValidGrabbable(GrabbedTarget) && HandGrabber.TryAutoGrab(GrabbedTarget, posableGrabPoint))
if (AutoGrab && HandGrabber.IsValidGrabbable(GrabbedTarget) && HandGrabber.TryTransferDistanceGrab(GrabbedTarget, posableGrabPoint))
{
grabbed = true;
IsForceGrabbing = false;
@@ -630,7 +646,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (AutoGrab && (JointAnchorWorldPosition - grabPoint.position).magnitude < AutoGrabDistance)
{
if (HandGrabber.TryAutoGrab(GrabbedTarget, posableGrabPoint))
if (HandGrabber.TryTransferDistanceGrab(GrabbedTarget, posableGrabPoint))
{
grabbed = true;
IsForceGrabbing = false;
@@ -697,7 +713,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
rb.useGravity = useGrav;
rb.drag = drag;
rb.angularDrag = angularDrag;
grabbable.IsBeingForcedGrabbed = false;
grabbable.Collided.RemoveListener(OnGrabbableCollided);
grabbable.Grabbed.RemoveListener(OnGrabbableGrabbed);
}
@@ -731,7 +746,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
if ((JointAnchorWorldPosition - t.position).magnitude < AutoGrabDistance)
{
if (HandGrabber.TryAutoGrab(grabbable, grabPoint))
if (HandGrabber.TryTransferDistanceGrab(grabbable, grabPoint))
{
grabbable.Rigidbody.angularVelocity = Vector3.zero;
grabbable.Rigidbody.velocity = Vector3.zero;
@@ -761,7 +776,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
private void UpdateGrabIndicator()
{
if (!IsHovering || !_grabIndicator)
if (!IsHovering || !_grabIndicator || !HoverTarget.ShowForceGrabIndicator)
return;
if (_grabIndicator.LookAtCamera && HVRManager.Instance.Camera)
@@ -40,6 +40,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
public HVRGrabbable HeldObject => GrabbedTarget;
public HVRGrabbable GrabbedTarget
{
@@ -453,7 +454,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
var closestValid = ClosestValidHover();
if (closestValid == null)
if (!closestValid )
return false;
HoverGrabbable(this, closestValid);
@@ -513,6 +514,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
public virtual bool CanGrab(HVRGrabbable grabbable)
{
if (grabbable.MasterGrabbable && grabbable.MasterGrabbable.IsSocketed)
return false;
return AllowGrabbing && !IsGrabbing;
}
@@ -553,15 +556,19 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
// ReSharper disable Unity.PerformanceAnalysis
protected virtual void OnHoverEnter(HVRGrabbable grabbable)
{
// Debug.Log($"OnHoverEnter {gameObject.name}");
if(HVRSettings.Instance.VerboseGrabbableEvents)
Debug.Log($"OnHoverEnter {gameObject.name} -> {grabbable.name}");
grabbable.Destroyed.AddListener(OnHoverGrabbableDestroyed);
}
// ReSharper disable Unity.PerformanceAnalysis
protected virtual void OnHoverExit(HVRGrabbable grabbable)
{
// Debug.Log($"OnHoverExit {gameObject.name}");
if(HVRSettings.Instance.VerboseGrabbableEvents)
Debug.Log($"OnHoverExit {gameObject.name}-> {grabbable.name}");
grabbable.Destroyed.RemoveListener(OnHoverGrabbableDestroyed);
}
@@ -577,6 +584,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
return false;
}
// ReSharper disable Unity.PerformanceAnalysis
private bool CheckLineOfSight(Vector3 rayOrigin, HVRGrabbable grabbable, LayerMask RaycastLayermask, float rayMaxDistance, List<Collider> colliders, QueryTriggerInteraction queryTrigger, bool useClosestPoint = true)
{
_lineOfSightRay.origin = rayOrigin;
@@ -588,7 +596,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (!grabbableCollider)
continue;
if (!useClosestPoint || grabbable.HasConcaveColliders && grabbableCollider is MeshCollider meshCollider && !meshCollider.convex)
if (!useClosestPoint || grabbable.HasConcaveColliders && grabbableCollider is MeshCollider meshCollider && !meshCollider.convex ||
grabbable.HasWheelCollider && grabbableCollider is WheelCollider)
{
_lineOfSightRay.direction = grabbableCollider.bounds.center - _lineOfSightRay.origin;
}
@@ -4,6 +4,9 @@ using UnityEngine;
namespace HurricaneVR.Framework.Core.Grabbers
{
/// <summary>
/// Example code to grab an object in code on start
/// </summary>
public class HVRHandGrabOnStart : MonoBehaviour
{
public HVRHandGrabber Grabber;
@@ -14,14 +17,13 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
if (Grabbable && Grabber)
{
if (Grabber.GrabTrigger == HVRGrabTrigger.Active ||
Grabbable.OverrideGrabTrigger && Grabbable.GrabTrigger == HVRGrabTrigger.Active)
Grabber.Grab(Grabbable, HVRGrabTrigger.Toggle);
if (!Grabber.GrabbedTarget)
{
Debug.LogWarning($"{Grabber.name} and {Grabbable.name} GrabTrigger is set to Active. The object will fall immediately if the user isn't holding the grab button.");
Grabbable.MainTransform.position = Grabber.transform.position;
Grabber.TryGrab(Grabbable, true);
Grabber.GrabToggleActive = true;
}
Grabbable.transform.position = Grabber.transform.position;
Grabber.TryGrab(Grabbable, true);
}
});
}
@@ -27,7 +27,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
public HVRSocketBag SocketBag;
[Header("HandSettings")]
[Tooltip("Set to true if the HandModel is an IK target")]
public bool InverseKinematics;
@@ -35,7 +34,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
public bool ApplyHandLayer = true;
[Header("Grab Settings")]
[Tooltip("If true the hand will move to the grabbable instead of pulling the grabbable to the hand")]
public bool HandGrabs;
@@ -60,7 +58,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
[Tooltip("If true the hand model will be cloned for collision use, and colliders removed off the original hand. This will prevent" +
"unwanted center of mass and inertia tensor recalculations on grabbable objects due to hand model parenting.")]
public bool CloneHandModel = true;
public bool CloneHandModel;
[Tooltip("Ignores hand model parenting distance check.")]
public bool IgnoreParentingDistance;
@@ -84,7 +82,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
public float PushoutTime = .1f;
[Header("Pull Settings")]
[Tooltip("Lerps between grabbable starting position and final hand posed position over this amount of time")]
public float PullLerpTime = .06f;
@@ -92,12 +89,12 @@ namespace HurricaneVR.Framework.Core.Grabbers
public float MoveThreshold = 10f;
[Header("Components")]
[Tooltip("The hand animator component, loads from children on startup if not supplied.")]
public HVRHandAnimator HandAnimator;
[Tooltip("Component that holds collider information about the hands. Auto populated from children if not set.")]
public HVRHandPhysics HandPhysics;
public HVRPlayerInputs Inputs;
public HVRPhysicsPoser PhysicsPoser;
public HVRForceGrabber ForceGrabber;
@@ -110,6 +107,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
[Header("Grab Indicators")]
public HVRGrabbableHoverBase GrabIndicator;
public HVRGrabbableHoverBase TriggerGrabIndicator;
public HVRGrabbableHoverBase DynamicPoseIndicator;
public DynamicPoseGrabIndicator DynamicPoseIndicatorMode = DynamicPoseGrabIndicator.Palm;
@@ -118,7 +116,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
public HVRHandPoser FallbackPoser;
[Header("Required Transforms")]
[Tooltip("Object holding the hand model.")]
public Transform HandModel;
@@ -134,8 +131,10 @@ namespace HurricaneVR.Framework.Core.Grabbers
[Tooltip("Sphere collider that checks when collisions should be re-enabled between a released grabbable and this hand.")]
public Transform OverlapSizer;
[Header("Throw Settings")]
[Tooltip("Player controller transform, used to find the correct relative velocity of the hands")]
public Transform PlayerController;
[Header("Throw Settings")]
[Tooltip("Factor to apply to the linear velocity of the throw.")]
public float ReleasedVelocityFactor;
@@ -154,6 +153,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
[Tooltip("If true throwing takes only the top peak velocities for throwing.")]
public bool TakePeakVelocities;
[DrawIf("TakePeakVelocities", true)]
public int CountPeakVelocities = 3;
@@ -164,13 +164,16 @@ namespace HurricaneVR.Framework.Core.Grabbers
public VRHandGrabberEvent BreakDistanceReached = new VRHandGrabberEvent();
[Header("Debugging")]
[Tooltip("If enabled displays vectors involved in throwing calculation.")]
public bool DrawCenterOfMass;
public bool GrabToggleActive;
[SerializeField]
private HVRGrabbable _triggerHoverTarget;
public HVRSocket HoveredSocket;
[SerializeField]
private HVRGrabbable _hoverTarget;
@@ -182,6 +185,9 @@ namespace HurricaneVR.Framework.Core.Grabbers
public override bool IsHandGrabber => true;
public bool IsLeftHand => HandSide == HVRHandSide.Left;
public bool IsRightHand => HandSide == HVRHandSide.Right;
public HVRHandStrengthHandler StrengthHandler { get; set; }
public Transform HandModelParent { get; private set; }
@@ -238,6 +244,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
public HVRPosableGrabPoint PosableGrabPoint { get; private set; }
private Transform _triggerGrabPoint;
public Transform TriggerGrabPoint
{
get => _triggerGrabPoint;
@@ -270,10 +277,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
/// </summary>
public Quaternion PoseWorldRotation
{
get
{
return GrabbedTarget.transform.rotation * PoseLocalRotation;
}
get { return GrabbedTarget.transform.rotation * PoseLocalRotation; }
}
public Vector3 PoseWorldPosition
@@ -344,6 +348,12 @@ namespace HurricaneVR.Framework.Core.Grabbers
public bool CanRelease { get; set; } = true;
/// <summary>
/// ignores the next overlap check and enabling of collision with the released grabbable. Useful if grabbing something
/// requires collision to remain disabled with the object that is next released.
/// </summary>
public bool IgnoreNextCollisionCheck { get; set; }
protected Vector3 LineGrabHandVector => transform.rotation * HandModelRotation * _lineGrabHandRelativeDirection;
protected Vector3 LineGrabVector => PosableGrabPoint.WorldLine.normalized * (_flippedLinePose ? -1f : 1f);
@@ -370,12 +380,13 @@ namespace HurricaneVR.Framework.Core.Grabbers
private bool _socketGrab;
private HVRPosableHand _posableHand;
private HVRPosableHand _collisionHand;
private bool _hasForceGrabber;
private HVRHandPoseData _physicsPose;
private HVRHandPoseData _savedPose;
private Vector3 _lineGrabHandRelativeDirection;
private WaitForFixedUpdate _wffu;
private bool _moveGrab;
private Vector3 _lastPlayerPos;
private Vector3 _playerVel;
protected bool IsGripGrabActivated;
protected bool IsTriggerGrabActivated;
protected bool IsGripGrabActive;
@@ -396,8 +407,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
#endregion
protected override void Awake()
{
base.Awake();
@@ -415,7 +424,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
protected override void Start()
{
base.Start();
@@ -433,15 +441,14 @@ namespace HurricaneVR.Framework.Core.Grabbers
//created in awake of the hand components if not exist, snapshot in start
StrengthHandler = GetComponent<HVRHandStrengthHandler>();
if (!Inputs)
if (!Inputs && transform.root)
{
Inputs = GetComponentInParent<HVRPlayerInputs>();
Inputs = transform.root.GetComponentInChildren<HVRPlayerInputs>();
}
if (!ForceGrabber)
{
ForceGrabber = GetComponentInChildren<HVRForceGrabber>();
_hasForceGrabber = ForceGrabber;
}
if (!HandAnimator)
@@ -515,7 +522,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
//removing colliders from the original hand model
foreach (var col in HandModel.GetComponentsInChildren<Collider>())
{
Destroy(col);
if (!col.isTrigger) Destroy(col);
}
_collisionTransform = handClone.transform;
@@ -605,7 +612,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
protected override void FixedUpdate()
{
if(PullingGrabbable) UpdatePullGrabbable();
if (PullingGrabbable) UpdatePullGrabbable();
UpdateLineGrab();
UpdatePostMoveGrab();
UpdatePushing();
@@ -814,7 +821,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
var closestValid = ClosestValidHover(false);
if (closestValid == null)
if (!closestValid)
return false;
HoverGrabbable(this, closestValid);
@@ -850,7 +857,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
var closestValid = ClosestValidHover(true);
if (closestValid == null)
if (!closestValid)
return false;
OnTriggerHoverEnter(this, closestValid);
@@ -858,7 +865,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
private void CheckUntoggleGrab()
{
if (GrabToggleActive && !_checkingSwap)
@@ -913,37 +919,37 @@ namespace HurricaneVR.Framework.Core.Grabbers
switch (grabTrigger)
{
case HVRGrabTrigger.Active:
{
if (GrabToggleActive)
{
if (GrabToggleActive)
{
return true;
}
if (IsLineGrab)
{
return IsGripGrabActive || IsTriggerGrabActive;
}
var grabActive = false;
switch (_currentGrabControl)
{
case HVRGrabControls.GripOrTrigger:
grabActive = IsGripGrabActive || (IsTriggerGrabActive && Inputs.CanTriggerGrab);
break;
case HVRGrabControls.GripOnly:
grabActive = IsGripGrabActive;
break;
case HVRGrabControls.TriggerOnly:
grabActive = IsTriggerGrabActive;
break;
}
return grabActive;
return true;
}
if (IsLineGrab)
{
return IsGripGrabActive || IsTriggerGrabActive;
}
var grabActive = false;
switch (_currentGrabControl)
{
case HVRGrabControls.GripOrTrigger:
grabActive = IsGripGrabActive || (IsTriggerGrabActive && Inputs.CanTriggerGrab);
break;
case HVRGrabControls.GripOnly:
grabActive = IsGripGrabActive;
break;
case HVRGrabControls.TriggerOnly:
grabActive = IsTriggerGrabActive;
break;
}
return grabActive;
}
case HVRGrabTrigger.Toggle:
{
return GrabToggleActive;
}
{
return GrabToggleActive;
}
case HVRGrabTrigger.ManualRelease:
return true;
}
@@ -953,7 +959,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
protected override void CheckGrab()
{
if (!AllowGrabbing || IsGrabbing || GrabbedTarget)
{
return;
@@ -999,7 +1004,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
GrabPoint = null;
var gp = HoveredSocket.GrabbedTarget.GetGrabPointTransform(this, GrabpointFilter.Socket);
if (!gp)//in case any socket grab point is invalid, deleted, inactive
if (!gp) //in case any socket grab point is invalid, deleted, inactive
gp = HoveredSocket.GrabbedTarget.GetGrabPointTransform(this, GrabpointFilter.Normal);
GrabPoint = gp;
@@ -1072,7 +1077,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
protected virtual void UpdateGrabIndicator()
{
if (!IsHovering || !_grabIndicator)
if (!IsHovering || !_grabIndicator || !HoverTarget.ShowGrabIndicator)
return;
if (_grabIndicator.LookAtCamera && HVRManager.Instance.Camera)
@@ -1146,7 +1151,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
protected virtual void UpdateTriggerGrabIndicator()
{
if (!IsTriggerHovering || !_triggerIndicator || IsGrabbing || TriggerHoverTarget == HoverTarget)
if (!IsTriggerHovering || !_triggerIndicator || IsGrabbing || TriggerHoverTarget == HoverTarget || !TriggerHoverTarget.ShowTriggerGrabIndicator)
return;
if (_triggerIndicator.LookAtCamera && HVRManager.Instance.Camera)
@@ -1185,7 +1190,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
if (grabPoint.IsLineGrab && !useGrabPoint && grabPoint.LineInitialCanReposition)
{
return grabbable.transform.TransformPoint(GetLocalLineGrabPoint(grabbable, transform.TransformPoint(GetLineGrabHandAnchor(PosableGrabPoint))));
return grabbable.transform.TransformPoint(GetLocalLineGrabPoint(grabbable, transform.TransformPoint(GetLineGrabHandAnchor(grabPoint)), grabPoint));
}
if (grabPoint.GrabIndicatorPosition)
@@ -1243,6 +1248,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
ResetAnimator();
}
}
private void EnableGrabIndicator()
{
if (_grabIndicatorEnabled) return;
@@ -1324,6 +1330,10 @@ namespace HurricaneVR.Framework.Core.Grabbers
private void TrackVelocities()
{
_playerVel = Vector3.zero;
if (PlayerController)
_playerVel = (PlayerController.position - _lastPlayerPos) / Time.deltaTime;
var deltaRotation = transform.rotation * Quaternion.Inverse(_previousRotation);
deltaRotation.ToAngleAxis(out var angle, out var axis);
angle *= Mathf.Deg2Rad;
@@ -1331,6 +1341,9 @@ namespace HurricaneVR.Framework.Core.Grabbers
RecentVelocities.Enqueue(Rigidbody.velocity);
RecentAngularVelocities.Enqueue(angularVelocity);
if (PlayerController)
_lastPlayerPos = PlayerController.position;
}
protected virtual void CheckSocketUnhover()
@@ -1352,7 +1365,12 @@ namespace HurricaneVR.Framework.Core.Grabbers
protected virtual bool CanGrabFromSocket(HVRSocket socket)
{
if (!socket)
if (!socket || !socket.GrabbedTarget)
{
return false;
}
if (!socket.GrabbedTarget.CanHandGrab(this))
{
return false;
}
@@ -1362,7 +1380,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
return false;
}
return socket.GrabDetectionType == HVRGrabDetection.Socket && socket.GrabbedTarget;
return socket.GrabDetectionType == HVRGrabDetection.Socket;
}
protected virtual void CheckSocketHover()
@@ -1493,7 +1511,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
var done = false;
try
{
@@ -1520,7 +1538,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
else if (_distanceComplete && !_posJoint)
{
_posJoint = grabbable.gameObject.AddComponent<ConfigurableJoint>();
_posJoint = grabbable.Rigidbody.gameObject.AddComponent<ConfigurableJoint>();
_posJoint.LockLinearMotion();
_posJoint.connectedBody = Rigidbody;
_posJoint.autoConfigureConnectedAnchor = false;
@@ -1529,13 +1547,14 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
_posJoint.anchor = BaseLineGrabAnchor + _lineOffset;
}
_posJoint.connectedAnchor = HandAnchorLocal;
PullJoint.SetLinearDrive(0f, 0f, 0f);
}
else if (angleComplete && !_rotJoint)
{
grabbable.transform.rotation = deltaRot * grabbable.transform.rotation;
_rotJoint = grabbable.gameObject.AddComponent<ConfigurableJoint>();
_rotJoint = grabbable.Rigidbody.gameObject.AddComponent<ConfigurableJoint>();
_rotJoint.LockAllAngularMotion();
_rotJoint.connectedBody = Rigidbody;
_rotJoint.autoConfigureConnectedAnchor = false;
@@ -1544,6 +1563,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
_posJoint.anchor = BaseLineGrabAnchor + _lineOffset;
}
_rotJoint.connectedAnchor = HandAnchorLocal;
PullJoint.SetSlerpDrive(0f, 0f, 0f);
}
@@ -1579,13 +1599,14 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
Debug.Log($"{name} break distance reached on {GrabbedTarget.name}.");
}
BreakDistanceReached.Invoke(this, GrabbedTarget);
ForceRelease();
}
protected virtual bool CheckBreakDistanceReached(HVRGrabbable grabbable)
{
if(grabbable.BreakDistanceSource == BreakDistanceSource.Hand)
if (grabbable.BreakDistanceSource == BreakDistanceSource.Hand)
return Vector3.Distance(GrabAnchorWorld, JointAnchorWorldPosition) > grabbable.BreakDistance;
if (grabbable.BreakDistanceSource == BreakDistanceSource.Controller)
return Vector3.Distance(GrabAnchorWorld, TrackedController.position) > grabbable.BreakDistance;
@@ -1651,7 +1672,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
ParentHandModel(GrabPoint);
}
SetAnimatorPose(poser, parent);
if (CloneHandModel && _collisionAnimator) _collisionAnimator.SetHeldPoser(poser);
if (HandAnimator) HandAnimator.SetHeldPoser(poser);
}
private void ParentHandModel(Transform parent)
@@ -1672,9 +1694,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
HandModel.parent = parent;
if (InverseKinematics && PosableGrabPoint)
if (PosableGrabPoint)
{
//posable hand not on the IK target, need to set pos / rot manually
var pose = PosableGrabPoint.HandPoser.PrimaryPose.Pose.GetPose(HandSide);
HandModel.localRotation = pose.Rotation;
HandModel.localPosition = pose.Position;
@@ -1682,14 +1703,20 @@ namespace HurricaneVR.Framework.Core.Grabbers
_hasPosed = true;
var listener = parent.gameObject.AddComponent<HVRDestroyListener>();
var listener = parent.gameObject.EnsureComponent<HVRDestroyListener>();
listener.Destroyed.AddListener(OnGrabPointDestroyed);
}
public void SetAnimatorPose(HVRHandPoser poser, bool poseHand = false, bool poseHandClone = false)
public void SetAnimatorPose(HVRHandPoser poser)
{
if (CloneHandModel && _collisionAnimator) _collisionAnimator.SetCurrentPoser(poser, poseHandClone);
if (HandAnimator) HandAnimator.SetCurrentPoser(poser, poseHand);
if (CloneHandModel && _collisionAnimator) _collisionAnimator.SetCurrentPoser(poser);
if (HandAnimator) HandAnimator.SetCurrentPoser(poser);
}
public void SetAnimatorOverridePose(HVRHandPoser poser)
{
if (CloneHandModel && _collisionAnimator) _collisionAnimator.SetOverridePoser(poser);
if (HandAnimator) HandAnimator.SetOverridePoser(poser);
}
public void ResetAnimator()
@@ -1718,11 +1745,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
public void OverrideHandSettings(HVRJointSettings settings)
{
StrengthHandler.OverrideHandSettings(settings);
}
public override bool CanHover(HVRGrabbable grabbable)
{
if (IsForceGrabbing || (IsGripGrabActive && (!HoverTarget || HoverTarget != grabbable)))
@@ -1731,13 +1753,16 @@ namespace HurricaneVR.Framework.Core.Grabbers
return CanGrab(grabbable);
}
private bool IsForceGrabbing => _hasForceGrabber && (ForceGrabber.IsForceGrabbing || ForceGrabber.IsAiming);
private bool IsForceGrabbing => ForceGrabber && (ForceGrabber.IsForceGrabbing || ForceGrabber.IsAiming);
public override bool CanGrab(HVRGrabbable grabbable)
{
if (!base.CanGrab(grabbable))
return false;
if (!grabbable.CanHandGrab(this))
return false;
if ((!AllowMultiplayerSwap && !grabbable.AllowMultiplayerSwap) && grabbable.HoldType != HVRHoldType.ManyHands && grabbable.AnyGrabberNotMine())
{
return false;
@@ -1752,7 +1777,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
return false;
}
if (GrabbedTarget != null && GrabbedTarget != grabbable)
if (GrabbedTarget && GrabbedTarget != grabbable)
return false;
if (grabbable.IsSocketed && grabbable.Socket.GrabDetectionType == HVRGrabDetection.Socket)
@@ -1808,9 +1833,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
if (_socketGrab)
{
}
else
{
@@ -1933,9 +1955,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
var isStatic = grabbable.Stationary ||
(grabbable.IsJointGrab && (!grabbable.Rigidbody || (grabbable.RemainsKinematic && grabbable.Rigidbody.isKinematic)));
var isStatic = grabbable.Stationary || (grabbable.IsJointGrab && (!grabbable.Rigidbody || grabbable.Rigidbody.isKinematic));
var linkedHeld = grabbable.MasterGrabbable && grabbable.MasterGrabbable.IsHandGrabbed || grabbable.AnyLinkedHandHeld();
@@ -1956,7 +1976,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
public static bool IsV1Closest(Vector3 v, Vector3 v1, Vector3 v2)
{
var vNorm = v.normalized;
@@ -1993,7 +2012,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
var mid = grabbable.transform.InverseTransformPoint(PosableGrabPoint.WorldLineMiddle);
var point = IsInitialLineGrab ? transform.TransformPoint(GetLineGrabHandAnchor(PosableGrabPoint)) : GrabPoint.position;
_lineOffset = GetLocalLineGrabPoint(grabbable, point) - mid;
_lineOffset = GetLocalLineGrabPoint(grabbable, point, PosableGrabPoint) - mid;
if (PosableGrabPoint.CanLineFlip)
{
@@ -2016,10 +2035,10 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
private Vector3 GetLocalLineGrabPoint(HVRGrabbable grabbable, Vector3 point)
private Vector3 GetLocalLineGrabPoint(HVRGrabbable grabbable, Vector3 point, HVRPosableGrabPoint grabPoint)
{
var start = grabbable.transform.InverseTransformPoint(PosableGrabPoint.LineStart.position);
var end = grabbable.transform.InverseTransformPoint(PosableGrabPoint.LineEnd.position);
var start = grabbable.transform.InverseTransformPoint(grabPoint.LineStart.position);
var end = grabbable.transform.InverseTransformPoint(grabPoint.LineEnd.position);
var testPoint = grabbable.transform.InverseTransformPoint(point);
return HVRUtilities.FindNearestPointOnLine(start, end, testPoint);
}
@@ -2038,12 +2057,13 @@ namespace HurricaneVR.Framework.Core.Grabbers
for (var i = 0; i < grabbable.Colliders.Count; i++)
{
var gc = grabbable.Colliders[i];
if (!gc.enabled || !gc.gameObject.activeInHierarchy || gc.isTrigger)
if (!gc || !gc.enabled || !gc.gameObject.activeInHierarchy || gc.isTrigger)
continue;
var anchor = Palm.transform.position;
Vector3 point;
if (grabbable.HasConcaveColliders && gc is MeshCollider meshCollider && !meshCollider.convex)
if (grabbable.HasConcaveColliders && gc is MeshCollider meshCollider && !meshCollider.convex ||
grabbable.HasWheelCollider && gc is WheelCollider wheelCollider)
{
if (!gc.Raycast(new Ray(anchor, Palm.transform.forward), out var hit, .3f))
{
@@ -2085,7 +2105,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
return false;
}
return GrabbedTarget.PoseType == PoseType.PhysicPoser || ((GrabPoint == null || GrabPoint == GrabbedTarget.transform) && GrabbedTarget.PhysicsPoserFallback);
return GrabbedTarget.PoseType == PoseType.PhysicPoser || ((!GrabPoint || GrabPoint == GrabbedTarget.transform) && GrabbedTarget.PhysicsPoserFallback);
}
private IEnumerator MoveGrab()
@@ -2177,7 +2197,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
SetupGrab(grabbable);
IsClimbing = grabbable.GetComponent<HVRClimbable>();
if (grabbable.HandGrabbedClip)
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(grabbable.HandGrabbedClip, transform.position);
if (SFXPlayer.Instance)
SFXPlayer.Instance.PlaySFX(grabbable.HandGrabbedClip, transform.position);
}
public void SetupGrab(HVRGrabbable grabbable)
@@ -2195,8 +2216,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
//determine if a pull to hand joint should be enabled, or should the final strong joint be enabled
final = grabbable.PoseType == PoseType.Offset || grabbable.Stationary ||
(grabbable.RemainsKinematic && grabbable.Rigidbody.isKinematic)
|| _moveGrab || _forceFullyGrabbed
grabbable.Rigidbody.isKinematic ||
_moveGrab || _forceFullyGrabbed
|| _socketGrab && HoveredSocket.InstantHandPose;
_moveGrab = false;
}
@@ -2209,12 +2230,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
StartPull();
}
if (grabbable.Rigidbody && (!grabbable.Rigidbody.isKinematic || !grabbable.RemainsKinematic))
{
grabbable.Rigidbody.isKinematic = false;
grabbable.Rigidbody.collisionDetectionMode = grabbable.CollisionDetection;
}
}
if (GrabPoint)
@@ -2335,18 +2350,12 @@ namespace HurricaneVR.Framework.Core.Grabbers
public Quaternion JointRotation
{
get
{
return Quaternion.Inverse(GrabbedTarget.transform.rotation) * CachedWorldRotation * Quaternion.Inverse(PoseLocalRotation);
}
get { return Quaternion.Inverse(GrabbedTarget.transform.rotation) * CachedWorldRotation * Quaternion.Inverse(PoseLocalRotation); }
}
private void SetupConfigurableJoint(HVRGrabbable grabbable)
{
var axis = Vector3.right;
var secondaryAxis = Vector3.up;
@@ -2453,7 +2462,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
UpdateGrabbableCOM(grabbable);
OnHandAttached();
BreakDistanceCooldown(2f);
_finalJointCreated = true;
@@ -2478,25 +2486,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
internal void UpdateGrabbableCOM(HVRGrabbable grabbable)
{
if (grabbable.Rigidbody && grabbable.PalmCenterOfMass)
{
//Debug.Log($"updating grabbable com { grabbable.HandGrabbers.Count}");
if (grabbable.HandGrabbers.Count == 1)
{
var p1 = grabbable.HandGrabbers[0].JointAnchorWorldPosition;
grabbable.Rigidbody.centerOfMass = grabbable.transform.InverseTransformPoint(p1);
}
else if (grabbable.HandGrabbers.Count == 2)
{
var p1 = grabbable.HandGrabbers[0].JointAnchorWorldPosition;
var p2 = grabbable.HandGrabbers[1].JointAnchorWorldPosition;
grabbable.Rigidbody.centerOfMass = grabbable.transform.InverseTransformPoint((p1 + p2) / 2);
}
}
}
private void UpdateLineGrab()
{
if (!IsLineGrab || PullingGrabbable || !_finalJointCreated || !Joint)
@@ -2516,7 +2505,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
(GrabTrigger == HVRGrabTrigger.Toggle || GrabToggleActive || !CanRelease) && !IsTriggerGrabActive;
loosen = GrabTrigger == HVRGrabTrigger.Active && !IsGripGrabActive && !GrabToggleActive && CanRelease ||
(GrabTrigger == HVRGrabTrigger.Toggle || GrabToggleActive || !CanRelease) && IsTriggerGrabActive;
(GrabTrigger == HVRGrabTrigger.Toggle || GrabToggleActive || !CanRelease) && IsTriggerGrabActive;
}
if (PosableGrabPoint.LineCanReposition || PosableGrabPoint.LineCanRotate)
@@ -2533,10 +2522,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
var mid = GrabbedTarget.transform.InverseTransformPoint(PosableGrabPoint.WorldLineMiddle);
_lineOffset = GetLocalLineGrabPoint(GrabbedTarget, transform.TransformPoint(HandAnchorLocal)) - mid;
_lineOffset = GetLocalLineGrabPoint(GrabbedTarget, transform.TransformPoint(HandAnchorLocal), PosableGrabPoint) - mid;
Joint.anchor = BaseLineGrabAnchor + _lineOffset;
UpdateGrabbableCOM(GrabbedTarget);
}
else if (_tightlyHeld && loosen)
{
@@ -2561,7 +2548,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
xDrive.positionDamper = PosableGrabPoint.LooseDamper;
xDrive.maximumForce = 100000f;
Joint.xDrive = xDrive;
}
if (PosableGrabPoint.LineCanRotate || PosableGrabPoint.LineFreeRotation)
@@ -2575,15 +2561,16 @@ namespace HurricaneVR.Framework.Core.Grabbers
xDrive.maximumForce = 100000f;
Joint.angularXDrive = xDrive;
}
}
// ReSharper disable Unity.PerformanceAnalysis
protected override void OnReleased(HVRGrabbable grabbable)
{
if (HVRSettings.Instance.VerboseHandGrabberEvents)
{
Debug.Log($"{name}:OnReleased");
}
base.OnReleased(grabbable);
if (ControllerOffset)
@@ -2597,6 +2584,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
StartPushing();
}
_checkingEnableCollision = false;
_primaryGrabPointGrab = false;
_socketGrab = false;
@@ -2606,7 +2594,17 @@ namespace HurricaneVR.Framework.Core.Grabbers
IsLineGrab = false;
TriggerGrabPoint = null;
ResetHandModel();
if (HandModel && HandModel.parent && HandModel.parent.TryGetComponent(out HVRDestroyListener listener))
{
listener.Destroyed.RemoveListener(OnGrabPointDestroyed);
}
_hasPosed = false;
ResetHandTransform(HandModel);
ResetHandTransform(_collisionTransform);
HandAnimator.OnHeldObjectReleased();
if (_collisionAnimator) _collisionAnimator.OnHeldObjectReleased();
IsPhysicsPose = false;
_physicsPose = null;
@@ -2623,26 +2621,33 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (grabbable.Rigidbody && !grabbable.Rigidbody.isKinematic)
{
var throwVelocity = ComputeThrowVelocity(grabbable, out var angularVelocity, true);
grabbable.Rigidbody.velocity = throwVelocity;
grabbable.Rigidbody.angularVelocity = angularVelocity;
var throwVelocity = ComputeThrowVelocity(grabbable, out var angularVelocity);
if(!throwVelocity.IsInvalid())
grabbable.Rigidbody.velocity = throwVelocity;
if(!throwVelocity.IsInvalid())
grabbable.Rigidbody.angularVelocity = angularVelocity;
//prevent clipping on throw
if (timeout < .2f && grabbable.Rigidbody.velocity.magnitude > 2f) timeout = .2f;
}
if (grabbable.Rigidbody && !grabbable.Rigidbody.isKinematic && (grabbable.RequireOverlapClearance || timeout > 0f))
if (!IgnoreNextCollisionCheck)
{
var routine = StartCoroutine(CheckReleasedOverlap(grabbable, timeout));
OverlappingGrabbables[grabbable] = routine;
}
else
{
EnableHandCollision(grabbable);
if (grabbable.Rigidbody && !grabbable.Rigidbody.isKinematic && (grabbable.RequireOverlapClearance || timeout > 0f))
{
var routine = StartCoroutine(CheckReleasedOverlap(grabbable, timeout));
OverlappingGrabbables[grabbable] = routine;
}
else
{
EnableHandCollision(grabbable);
}
}
grabbable.HeldGrabPoints.Remove(GrabPoint);
}
IgnoreNextCollisionCheck = false;
GrabToggleActive = false;
GrabPoint = null;
Released.Invoke(this, grabbable);
@@ -2678,14 +2683,15 @@ namespace HurricaneVR.Framework.Core.Grabbers
internal static Vector3 GetAverageVelocity(int frames, int start, CircularBuffer<Vector3> recentVelocities, bool takePeak = false, int nPeak = 3)
{
if (frames == 0)
return Vector3.zero;
var sum = Vector3.zero;
for (var i = start; i < start + frames; i++)
{
sum += recentVelocities[i];
}
if (Mathf.Approximately(frames, 0f))
return Vector3.zero;
var average = sum / frames;
@@ -2695,7 +2701,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
for (var i = start; i < start + frames; i++)
{
//removing any vectors not going in the direction of the average vector
var dot = Vector3.Dot(average.normalized, recentVelocities[i].normalized);
if (dot < .2)
@@ -2736,8 +2741,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
public Vector3 ComputeThrowVelocity(HVRGrabbable grabbable, out Vector3 angularVelocity, bool isThrowing = false)
public Vector3 ComputeThrowVelocity(HVRGrabbable grabbable, out Vector3 angularVelocity, bool playerRelative = false)
{
if (!grabbable.Rigidbody)
{
@@ -2749,8 +2753,16 @@ namespace HurricaneVR.Framework.Core.Grabbers
var grabbableAngular = grabbable.GetAverageAngularVelocity(ThrowLookback, ThrowLookbackStart);
var handVelocity = GetAverageVelocity(ThrowLookback, ThrowLookbackStart);
if (playerRelative)
{
handVelocity -= _playerVel;
grabbableVelocity -= _playerVel;
}
var handAngularVelocity = GetAverageAngularVelocity(ThrowLookback, ThrowLookbackStart);
//var throwVelocity = handVelocity * (ReleasedVelocityFactor * grabbable.ReleasedVelocityFactor);
var throwVelocity = ReleasedVelocityFactor * handVelocity + grabbableVelocity * grabbable.ReleasedVelocityFactor;
//Debug.Log($"{handAngularVelocity.magnitude}");
@@ -2758,7 +2770,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (handAngularVelocity.magnitude > ReleasedAngularThreshold)
{
//compute linear velocity from wrist rotation
var grabbableCom = GrabPoint != null ? GrabPoint.position : grabbable.Rigidbody.worldCenterOfMass;
var grabbableCom = GrabPoint ? GrabPoint.position : grabbable.Rigidbody.worldCenterOfMass;
Vector3 centerOfMass;
if (ThrowingCenterOfMass && ThrowingCenterOfMass.CenterOfMass)
@@ -2770,12 +2782,14 @@ namespace HurricaneVR.Framework.Core.Grabbers
centerOfMass = Rigidbody.worldCenterOfMass;
}
var cross = Vector3.Cross(handAngularVelocity, grabbableCom - centerOfMass) * grabbable.ReleasedAngularConversionFactor * ReleasedAngularConversionFactor;
var cross = Vector3.Cross(handAngularVelocity, grabbableCom - centerOfMass) * (grabbable.ReleasedAngularConversionFactor * ReleasedAngularConversionFactor);
throwVelocity += cross;
}
angularVelocity = grabbableAngular * grabbable.ReleasedAngularFactor;
return throwVelocity;
}
@@ -2934,9 +2948,9 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
public bool TryAutoGrab(HVRGrabbable grabbable, HVRPosableGrabPoint grabPoint)
public bool TryTransferDistanceGrab(HVRGrabbable grabbable, HVRPosableGrabPoint grabPoint)
{
if (GrabTrigger == HVRGrabTrigger.Active && !Inputs.GetHoldActive(HandSide))
if (GrabTrigger == HVRGrabTrigger.Active && !Inputs.GetForceGrabActive(HandSide))
{
return false;
}
@@ -2956,7 +2970,24 @@ namespace HurricaneVR.Framework.Core.Grabbers
//if (grabPoint) OrientGrabbable(grabbable, grabPoint, true, false);
if (TryGrab(grabbable))
{
_currentGrabControl = grabbable.GrabControl;
if (Inputs.ForceGrabActivation == HVRForceGrabActivation.Grip)
{
_currentGrabControl = HVRGrabControls.GripOnly;
}
else if (Inputs.ForceGrabActivation == HVRForceGrabActivation.Trigger)
{
_currentGrabControl = HVRGrabControls.TriggerOnly;
}
else
{
if (IsGripGrabActive)
_currentGrabControl = HVRGrabControls.GripOnly;
else
_currentGrabControl = HVRGrabControls.TriggerOnly;
}
CheckGrabControlSwap();
return true;
}
}
@@ -2964,6 +2995,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
_isForceAutoGrab = false;
}
return false;
}
@@ -2975,36 +3007,18 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (!HandModel)
return;
if (HandModel.parent)
{
var listener = HandModel.parent.GetComponent<HVRDestroyListener>();
if (listener)
{
listener.Destroyed.RemoveListener(OnGrabPointDestroyed);
Destroy(listener);
}
}
ResetHand(HandModel, HandAnimator);
ResetHandTransform(HandModel);
if (HandAnimator) HandAnimator.ResetToDefault();
if (_collisionTransform)
{
ResetHand(_collisionTransform, _collisionAnimator);
}
}
private void ResetHand(Transform hand, HVRHandAnimator animator)
{
ResetHandTransform(hand);
if (animator)
{
animator.ResetToDefault();
ResetHandTransform(_collisionTransform);
if (_collisionAnimator) _collisionAnimator.ResetToDefault();
}
}
private void ResetHandTransform(Transform hand)
{
if (!hand) return;
hand.parent = HandModelParent;
hand.localPosition = HandModelPosition;
hand.localRotation = HandModelRotation;
@@ -3036,6 +3050,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
_collisionHand.Pose(HVRHandPoseData.FromByteArray(data, HandSide), GrabbedTarget.ParentHandModel);
}
_posableHand.Pose(HVRHandPoseData.FromByteArray(data, HandSide), GrabbedTarget.ParentHandModel);
}
@@ -3048,7 +3063,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
protected virtual IEnumerator SwapGrabPoint(HVRPosableGrabPoint grabPoint, float time, HVRAxis axis)
{
var grabbable = GrabbedTarget;
@@ -3136,7 +3150,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
/// <summary>
/// Will grab the provided object using the provided grab point, if the grab point isn't provided then the first valid one on the object will be used.
/// If there are no grab points that are allowed to be grabbed by this hand you shouldn't use this method.
@@ -3186,8 +3199,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
public void OrientGrabbable(HVRGrabbable grabbable, HVRPosableGrabPoint grabPoint, bool position = true, bool rotation = true)
{
var deltaRot = CachedWorldRotation * Quaternion.Inverse(grabPoint.GetPoseWorldRotation(HandSide));
if (rotation) grabbable.transform.rotation = deltaRot * grabbable.transform.rotation;
if (position) grabbable.transform.position += (HandModel.position - grabPoint.GetPoseWorldPosition(HandSide));
if (rotation) grabbable.MainTransform.rotation = deltaRot * grabbable.MainTransform.rotation;
if (position) grabbable.MainTransform.position += (HandModel.position - grabPoint.GetPoseWorldPosition(HandSide));
}
public override void ForceRelease()
@@ -3197,7 +3210,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
@@ -3244,6 +3256,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
public enum DynamicPoseGrabIndicator
{
Transform, Palm, None
Transform,
Palm,
None
}
}
}
@@ -15,7 +15,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
{
public class HVRSocket : HVRGrabberBase
{
[Header("Grab Settings")]
public HVRGrabControls GrabControl = HVRGrabControls.GripOrTrigger;
@@ -77,6 +76,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
[Tooltip("Fallback grabbed sfx to play if the socketable doesn't have one.")]
public AudioClip AudioGrabbedFallback;
[Tooltip("Fallback released sfx to play if the socketable doesn't have one.")]
public AudioClip AudioReleasedFallback;
@@ -92,6 +92,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
[Tooltip("If supplied the hand will use this point when sorting distance to the closest socket instead of the socket position")]
public Transform DistanceSource;
[Tooltip("Used by the socketable to decide which saved pose to use.")]
public string PoseTag;
[Tooltip("If false, the socketed object colliders remain active, only works for static or kinematic rb sockets.")]
public bool DisableCollision = true;
@@ -105,16 +107,23 @@ namespace HurricaneVR.Framework.Core.Grabbers
protected Transform _previousParent;
protected Vector3 _previousScale;
protected Bounds _modelBounds;
protected bool _appQuitting;
protected HVRGrabbable _timeoutGrabbable;
protected float _mass;
private RigidbodyInterpolation _rbInterpolation;
private float _rbDrag;
private float _rbAngularDrag;
private float _rbMass;
private bool _rbGravity;
private bool _rbKinematic;
private float _socketMass;
protected bool _hadRigidBody;
protected bool _ignoreGrabSFX;
protected Coroutine _fixPositionRoutine;
public HVRGrabbable LinkedGrabbable { get; internal set; }
/// <summary>
/// If assigned only this grabbable can enter this socket.
/// </summary>
public HVRGrabbable LinkedGrabbable { get; set; }
public override bool IsGrabActivated => !IsGrabbing;
public override bool IsHoldActive => IsGrabbing;
@@ -125,6 +134,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
public override bool IsSocket => true;
public int? PoseHash { get; set; }
public bool CanAddGrabbable
{
get
@@ -151,6 +162,9 @@ namespace HurricaneVR.Framework.Core.Grabbers
Debug.LogWarning($"Sockets with a non kinematic rigidbody should not disable DisableCollision");
}
if (!string.IsNullOrWhiteSpace(PoseTag))
PoseHash = Animator.StringToHash(PoseTag);
//if (!Rigidbody && HoldType == SocketHoldType.RemoveRigidbody)
//{
// HoldType = SocketHoldType.Kinematic;
@@ -166,7 +180,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
SetupParentDisablesGrab();
SocketFilters = GetComponents<HVRSocketFilter>();
if (SocketFilters == null || SocketFilters.Length == 0)
SocketFilters = GetComponents<HVRSocketFilter>();
if (HoverActions == null || HoverActions.Length == 0)
HoverActions = GetComponents<HVRSocketHoverAction>();
@@ -201,7 +216,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
var cloneGrabbable = clone.GetComponent<HVRGrabbable>();
if (cloneGrabbable)
{
var t = TryGrab(cloneGrabbable, true, true);
TryGrab(cloneGrabbable, true, true);
SpawnedPrefab.Invoke(this, clone);
}
else
@@ -270,7 +285,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (GrabbableMustBeHeld && grabbable.GrabberCount != 1)
return false;
var handGrabber = grabbable.PrimaryGrabber as HVRHandGrabber;
if (handGrabber == null)
if (!handGrabber)
return false;
if (_timeoutGrabbable && _timeoutGrabbable == grabbable)
return false;
@@ -282,6 +297,7 @@ namespace HurricaneVR.Framework.Core.Grabbers
return false;
}
}
return base.CanHover(grabbable);
}
@@ -309,7 +325,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
grabbable.Released.AddListener(OnHoverGrabbableReleased);
base.OnHoverEnter(grabbable);
if (HoverActions != null)
{
@@ -359,7 +374,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (CanAddGrabbable && TryGrab(grabbable))
{
}
}
@@ -429,6 +443,11 @@ namespace HurricaneVR.Framework.Core.Grabbers
public virtual bool IsValid(HVRGrabbable grabbable)
{
if (LinkedGrabbable)
{
return LinkedGrabbable == grabbable;
}
if (grabbable.IsStabbing && !CanGrabStabbingGrabbable || grabbable.IsStabbed || !grabbable.Socketable)
return false;
@@ -476,30 +495,8 @@ namespace HurricaneVR.Framework.Core.Grabbers
_previousParent = grabbable.transform.parent;
_previousScale = grabbable.transform.localScale;
if (grabbable.Socketable && grabbable.Socketable.ScaleOverride)
{
var scaleBox = grabbable.Socketable.ScaleOverride;
var temp = scaleBox.enabled;
if (!scaleBox.enabled)
{
scaleBox.enabled = true;
}
_modelBounds = scaleBox.bounds;
if (!temp)
{
scaleBox.enabled = false;
}
}
else
{
_modelBounds = grabbable.ModelBounds;
}
grabbable.transform.parent = transform;
AttachGrabbable(grabbable);
OnGrabbableParented(grabbable);
HandleRigidBodyGrab(grabbable);
PlaySocketedSFX(grabbable.Socketable);
@@ -510,44 +507,51 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
}
protected virtual Vector3 GetPositionOffset(HVRGrabbable grabbable)
protected virtual void AttachGrabbable(HVRGrabbable grabbable)
{
if (!grabbable || !grabbable.Socketable || !grabbable.Socketable.SocketOrientation)
return Vector3.zero;
return grabbable.Socketable.SocketOrientation.localPosition;
grabbable.transform.parent = transform;
}
protected virtual Quaternion GetRotationOffset(HVRGrabbable grabbable)
{
if (!grabbable || !grabbable.Socketable || !grabbable.Socketable.SocketOrientation)
return Quaternion.identity;
return grabbable.Socketable.SocketOrientation.localRotation;
}
protected virtual Vector3 GetTargetPosition(HVRGrabbable grabbable)
{
var offSet = -GetPositionOffset(grabbable);
var delta = Quaternion.Inverse(GetRotationOffset(grabbable));
offSet = delta * offSet;
offSet.x *= grabbable.transform.localScale.x;
offSet.y *= grabbable.transform.localScale.y;
offSet.z *= grabbable.transform.localScale.z;
return offSet;
}
protected virtual Quaternion GetTargetRotation(HVRGrabbable grabbable)
/// <summary>
/// Returns the socketed local position
/// </summary>
public virtual Vector3 GetTargetPosition(HVRGrabbable grabbable)
{
var socketable = grabbable.Socketable;
if (!grabbable || !socketable)
return Vector3.zero;
if (socketable.SocketOrientation)
{
var rotationOffset = GetRotationOffset(grabbable);
return Quaternion.Inverse(rotationOffset);
var offSet = -socketable.SocketOrientation.localPosition;
var delta = Quaternion.Inverse(socketable.SocketOrientation.localRotation);
offSet = delta * offSet;
offSet.x *= grabbable.transform.localScale.x;
offSet.y *= grabbable.transform.localScale.y;
offSet.z *= grabbable.transform.localScale.z;
return offSet;
}
return Quaternion.identity;
return socketable.GetPositionOffset(this);
}
/// <summary>
/// Returns the socketed local rotation;
/// </summary>
public virtual Quaternion GetTargetRotation(HVRGrabbable grabbable)
{
var socketable = grabbable.Socketable;
if (!socketable)
return Quaternion.identity;
if (socketable.SocketOrientation)
{
return Quaternion.Inverse(socketable.SocketOrientation.localRotation);
}
return socketable.GetRotationOffset(this);
}
protected virtual void OnGrabbableParented(HVRGrabbable grabbable)
@@ -572,55 +576,71 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (!grabbable.Rigidbody)
return;
_rbKinematic = grabbable.Rigidbody.isKinematic;
_rbInterpolation = grabbable.Rigidbody.interpolation;
switch (HoldType)
{
case SocketHoldType.Kinematic:
{
grabbable.Rigidbody.useGravity = false;
grabbable.Rigidbody.velocity = Vector3.zero;
grabbable.Rigidbody.angularVelocity = Vector3.zero;
grabbable.Rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
grabbable.Rigidbody.isKinematic = true;
grabbable.Rigidbody.interpolation = RigidbodyInterpolation.None;
if (DisableCollision) grabbable.SetAllToTrigger();
}
{
grabbable.Rigidbody.velocity = Vector3.zero;
grabbable.Rigidbody.angularVelocity = Vector3.zero;
grabbable.Rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
grabbable.Rigidbody.isKinematic = true;
grabbable.Rigidbody.interpolation = RigidbodyInterpolation.None;
if (DisableCollision) grabbable.SetAllToTrigger();
}
break;
case SocketHoldType.RemoveRigidbody:
{
_hadRigidBody = true;
_rbMass = grabbable.Rigidbody.mass;
_rbGravity = grabbable.Rigidbody.useGravity;
_rbDrag = grabbable.Rigidbody.drag;
_rbAngularDrag = grabbable.Rigidbody.angularDrag;
if (Rigidbody)
{
_hadRigidBody = true;
if (Rigidbody)
{
_mass = Rigidbody.mass;
Rigidbody.mass += grabbable.Rigidbody.mass;
}
Destroy(grabbable.Rigidbody);
if (_fixPositionRoutine != null)
{
StopCoroutine(_fixPositionRoutine);
}
_fixPositionRoutine = StartCoroutine(SetPositionNextFrame(grabbable));
_socketMass = Rigidbody.mass;
Rigidbody.mass += _rbMass;
}
Destroy(grabbable.Rigidbody);
if (_fixPositionRoutine != null)
{
StopCoroutine(_fixPositionRoutine);
}
_fixPositionRoutine = StartCoroutine(SetPositionNextFrame(grabbable));
}
break;
}
}
protected virtual void CleanupRigidBody(HVRGrabbable grabbable)
{
var rb = grabbable.Rigidbody;
if (HoldType == SocketHoldType.RemoveRigidbody && _hadRigidBody)
{
grabbable.Rigidbody = grabbable.gameObject.AddComponent<Rigidbody>();
rb = grabbable.Rigidbody = grabbable.gameObject.AddComponent<Rigidbody>();
if (Rigidbody)
{
Rigidbody.mass = _mass;
Rigidbody.mass = _socketMass;
}
rb.useGravity = _rbGravity;
rb.mass = _rbMass;
rb.drag = _rbDrag;
rb.angularDrag = _rbAngularDrag;
}
grabbable.ResetRigidBody();
if (rb)
{
rb.collisionDetectionMode = grabbable.OriginalCollisionMode;
rb.isKinematic = _rbKinematic;
rb.interpolation = _rbInterpolation;
}
}
private IEnumerator SetPositionNextFrame(HVRGrabbable grabbable)
@@ -677,21 +697,27 @@ namespace HurricaneVR.Framework.Core.Grabbers
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(clip, transform.position);
}
protected virtual float GetSocketableScaleSize(HVRSocketable socketable)
{
return socketable.GetSocketScaleSize(this);
}
protected virtual void UpdateScale(HVRGrabbable grabbable)
{
if (!grabbable || !ScaleGrabbable)
return;
var extents = _modelBounds.extents;
var axis = extents.x;
if (extents.y > axis) axis = extents.y;
if (extents.z > axis) axis = extents.z;
axis *= 2;
var finalScale = ComputeScale(grabbable.Socketable);
grabbable.transform.localScale = finalScale;
}
public virtual Vector3 ComputeScale(HVRSocketable socketable)
{
var axis = GetSocketableScaleSize(socketable);
var ratio = Size / axis;
ratio *= grabbable.Socketable.SocketScale;
var counterScale = grabbable.Socketable.CounterScale;
grabbable.transform.localScale = new Vector3(ratio * counterScale.x, ratio * counterScale.y, ratio * counterScale.z);
ratio *= socketable.SocketScale;
var counterScale = socketable.CounterScale;
return new Vector3(ratio * counterScale.x, ratio * counterScale.y, ratio * counterScale.z);
}
protected override void OnReleased(HVRGrabbable grabbable)
@@ -744,8 +770,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
}
protected virtual IEnumerator GrabTimeoutRoutine(HVRGrabbable grabbable)
{
_timeoutGrabbable = grabbable;
@@ -790,7 +814,6 @@ namespace HurricaneVR.Framework.Core.Grabbers
[Serializable]
public class SocketSpawnEvent : UnityEvent<HVRSocket, GameObject>
{
}
public enum SocketCondition
@@ -6,6 +6,10 @@ using UnityEngine;
namespace HurricaneVR.Framework.Core.Grabbers
{
/// <summary>
/// Grabber that uses a HVRSocketContainer as a target of the grab. Main uses are over the shoulder or chest collection type inventories
/// </summary>
public class HVRSocketContainerGrabber : HVRGrabberBase
{
public HVRSocketContainer SocketContainer;
@@ -0,0 +1,31 @@
using System;
using HurricaneVR.Framework.Core.Grabbers;
/// <summary>
/// Filters the incoming grabbing hand by left or right hand only
/// </summary>
public class HVRGrabHandFilter : HVRHandGrabFilter
{
public HandOptions AllowedHands;
public override bool CanBeGrabbed(HVRHandGrabber hand)
{
if (AllowedHands == HandOptions.Both)
return true;
if (AllowedHands == HandOptions.Left && hand.IsLeftHand)
return true;
if (AllowedHands == HandOptions.Right && hand.IsRightHand)
return true;
return false;
}
//[Flags]
public enum HandOptions
{
Left = 0, Right = 1, Both = 2
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9cf9028b057d4b7db0423f5d0a26074b
timeCreated: 1674090737
@@ -17,8 +17,6 @@ using UnityEngine.Serialization;
namespace HurricaneVR.Framework.Core
{
public class HVRGrabbable : MonoBehaviour
{
#region Fields
@@ -26,32 +24,36 @@ namespace HurricaneVR.Framework.Core
internal const int TrackedVelocityCount = 10;
[Header("Grab Settings")]
[Tooltip("Define grab behaviour, HandGrabber Default, Pull object to hand, Hand goes to the object.")]
public GrabBehaviour GrabBehaviour = GrabBehaviour.Default;
[FormerlySerializedAs("GrabType")]
[FormerlySerializedAs("GrabType")]
public PoseType PoseType;
[Tooltip("Whether or not the grab uses physics joints with the hand")]
public HVRGrabTracking TrackingType;
[Tooltip("One Hand, Swap hand Allowed, or two hand hold allowed")]
public HVRHoldType HoldType = HVRHoldType.Swap;
[Tooltip("Control whether grip, trigger, or grip and trigger can grab this")]
public HVRGrabControls GrabControl = HVRGrabControls.GripOrTrigger;
[Tooltip("By default input to continue holding will use whatever the Hand Grabber is set to, enable this to allow overriding that behaviour.")]
public bool OverrideGrabTrigger;
[DrawIf("OverrideGrabTrigger", true)]
[Tooltip("Decide if the grip must be released to drop, toggled off to drop, or manually released in code to drop.")]
public HVRGrabTrigger GrabTrigger = HVRGrabTrigger.Active;
[Tooltip("Does this grabbable require line of sight to the hand grabber to be grabbed?")]
public bool RequireLineOfSight = true;
[FormerlySerializedAs("ParentHandModelImmediately")]
[Tooltip("Should the hand model pose immediately to this upon grabbing.")]
[Tooltip("Should the hand model pose immediately to this upon grabbing. Useful for non physics based grabbing.")]
public bool PoseImmediately;
[Tooltip("Should the hand model parent to the grabbable once close enough? Required for posing.")]
[Tooltip("Should the hand model parent to the grabbable once close enough?")]
public bool ParentHandModel;
[Tooltip("Released if the grabbable exceeds this distance from the grabber.")]
@@ -60,9 +62,6 @@ namespace HurricaneVR.Framework.Core
[Tooltip("The grabbed object will compare it's distance to this when checking BreakDistance release.")]
public BreakDistanceSource BreakDistanceSource = BreakDistanceSource.NoDistanceCheck;
[Tooltip("If true the object remains kinematic")]
public bool RemainsKinematic = true;
[Tooltip("If true the object is static or attached to something else and shouldn't be pulled and rotated to the hand")]
public bool Stationary;
@@ -78,6 +77,7 @@ namespace HurricaneVR.Framework.Core
[Header("Grab Indicators")]
public HVRGrabbableHoverBase GrabIndicator;
public HVRGrabbableHoverBase ForceGrabIndicator;
public bool ShowGrabIndicator = true;
public bool ShowTriggerGrabIndicator = true;
@@ -94,47 +94,30 @@ namespace HurricaneVR.Framework.Core
#region Joint
[Header("Configurable Joint Override")]
[Tooltip("If set it will override the default joint settings.")]
public HVRJointSettings JointOverride;
[Header("Hand Joint Overrides")]
[Header("Physics")]
[Embedded]
[Tooltip("Overrides the hand strength when one hand is holding this.")]
public PDStrength OneHandStrength;
[Tooltip("Applies the joint settings to the hand joint with one hand hold.")]
public HVRJointSettings OneHandJointSettings;
[Tooltip("Applies the joint settings to the hand joint with two hand hold.")]
public HVRJointSettings TwoHandJointSettings;
[Embedded]
[Tooltip("Overrides the hand strength when two hands are holding this.")]
public PDStrength TwoHandStrength;
[Tooltip("Uses this to pull the object to the hand, overrides default settings")]
public HVRJointSettings PullingSettingsOverride;
[Header("Physics")]
[Tooltip("If true the hand palm will become the center of mass on grab, midpoint for 2 handed grabs")]
public bool PalmCenterOfMass;
#endregion
[Header("SFX")]
[Header("Misc")]
[Tooltip("SFX played when grabbed by a hand.")]
public AudioClip HandGrabbedClip;
[Header("Sockets")]
[Tooltip("Socket that this grabbable will start in.")]
public HVRSocket StartingSocket;
[Tooltip("If true this grabbable will be auto grabbed by the StartingSocket whenever it's dropped.")]
public bool LinkStartingSocket;
[Tooltip("If provided only these grab points will be considered when an object is removed from a socket, otherwise the closest grab point will be used.")]
public HVRPosableGrabPoint[] SocketGrabPoints;
[Header("Misc")]
[Tooltip("RB for hand jointing, majority of grabbables should be on the rigidbody, only assign this for compound objects with secondary grabbables")]
public Rigidbody Rigidbody;
@@ -193,11 +176,22 @@ namespace HurricaneVR.Framework.Core
[DrawIf("OverrideMaxDistanceBehaviour", true)]
public MaxDistanceBehaviour MaxDistanceBehaviour;
[Header("Deprecated")]
[Tooltip("Applies the joint settings to the hand joint with one hand hold.")]
public HVRJointSettings OneHandJointSettings;
[Tooltip("Applies the joint settings to the hand joint with two hand hold.")]
public HVRJointSettings TwoHandJointSettings;
[Tooltip("Socket that this grabbable will start in.")]
public HVRSocket StartingSocket;
[Tooltip("If true this grabbable will be auto grabbed by the StartingSocket whenever it's dropped.")]
public bool LinkStartingSocket;
[Header("Debug")]
public bool ShowBoundingBox;
public bool DrawCenterOfMass;
public List<Transform> GrabPoints = new List<Transform>();
@@ -223,7 +217,6 @@ namespace HurricaneVR.Framework.Core
public VRSocketEvent Socketed = new VRSocketEvent();
public VRSocketEvent UnSocketed = new VRSocketEvent();
#endregion
#region Properties
@@ -254,20 +247,19 @@ namespace HurricaneVR.Framework.Core
/// </summary>
public List<Collider> Triggers { get; private set; } = new List<Collider>();
/// <summary>
/// Saved on awake and used by framework to reset after the object is released as the rb has CCD enabled after it's
/// released to help with collisions.
/// </summary>
public CollisionDetectionMode OriginalCollisionMode { get; set; }
public bool WasGravity { get; set; }
public bool WasKinematic { get; set; }
public List<HVRPosableGrabPoint> GrabPointsMeta = new List<HVRPosableGrabPoint>();
public HVRGrabberBase PrimaryGrabber { get; private set; }
public HVRSocket SocketHoverer { get; internal set; }
public HVRSocketable Socketable { get; private set; }
public HVRSocketable Socketable { get; set; }
/// <summary>
/// The socket this grabbable will return to when it's released.
@@ -284,11 +276,33 @@ namespace HurricaneVR.Framework.Core
public bool IsHandGrabbed => HandGrabbers.Count > 0;
/// <summary>
/// Transform of the Rigidbody if attached. If MasterGrabbable is assigned, the transform of it's rigidbody.
/// Otherwise the transform of the grabbable or MasterGrabbable.
/// </summary>
public Transform MainTransform
{
get
{
if (MasterGrabbable)
{
if (MasterGrabbable.Rigidbody)
return MasterGrabbable.Rigidbody.transform;
return MasterGrabbable.transform;
}
if (Rigidbody)
return Rigidbody.transform;
return transform;
}
}
public bool IsJointGrab => TrackingType == HVRGrabTracking.ConfigurableJoint || TrackingType == HVRGrabTracking.FixedJoint;
public bool HasConcaveColliders { get; private set; }
public bool HasWheelCollider { get; set; }
/// <summary>
/// If true will force use the two hand settings regardless of the number of hand grabbers holding
/// </summary>
@@ -328,6 +342,8 @@ namespace HurricaneVR.Framework.Core
public bool BeingDestroyed { get; set; }
public bool CollidedThisFrame { get; private set; }
#endregion
#region Private
@@ -341,12 +357,10 @@ namespace HurricaneVR.Framework.Core
private bool _forceTwoHandSettings;
private Vector3 _centerOfMass;
private RigidbodyInterpolation _rbInterpolation;
private float _mass;
private bool _waitingForColDetectionReset;
private Coroutine _resetCollisionDetectionRoutine;
private readonly HashSet<Collider> _ignoredColliders = new HashSet<Collider>();
private readonly List<HVRHandGrabFilter> _filters = new List<HVRHandGrabFilter>();
#endregion
@@ -354,7 +368,13 @@ namespace HurricaneVR.Framework.Core
protected virtual void Awake()
{
if (!Rigidbody) TryGetComponent(out Rigidbody);
if (!Rigidbody)
TryGetComponent(out Rigidbody);
if (Rigidbody)
{
OriginalCollisionMode = Rigidbody.collisionDetectionMode;
}
SetupColliders();
@@ -362,17 +382,9 @@ namespace HurricaneVR.Framework.Core
PopulateGrabPoints();
LoadGrabPoints();
LoadFilters();
Socketable = GetComponent<HVRSocketable>();
if (Socketable && !Socketable.SocketOrientation)
{
var orientation = new GameObject("SocketOrientation");
orientation.transform.SetParent(this.transform);
orientation.transform.localPosition = Vector3.zero;
orientation.transform.localRotation = Quaternion.identity;
orientation.transform.localScale = Vector3.zero;
Socketable.SocketOrientation = orientation.transform;
}
ResetTrackedVelocities();
@@ -389,7 +401,7 @@ namespace HurricaneVR.Framework.Core
//if (Stationary) Debug.LogWarning($"stationary {name}");
if (IsJointGrab && (!Rigidbody || RemainsKinematic && Rigidbody.isKinematic))
if (IsJointGrab && (!Rigidbody || Rigidbody.isKinematic))
{
Stationary = true;
}
@@ -400,13 +412,7 @@ namespace HurricaneVR.Framework.Core
MaxDistanceBehaviour = MaxDistanceBehaviour.GrabbableDrops;
}
if (GrabColliders != null)
{
GrabCollidersSet = new HashSet<Collider>(GrabColliders);
FilterGrabColliders = GrabColliders.Length > 0;
}
SetupGrabColliders();
}
@@ -421,6 +427,7 @@ namespace HurricaneVR.Framework.Core
LinkedSocket = StartingSocket;
LinkedSocket.LinkedGrabbable = this;
}
//let all Starts() go off first
StartCoroutine(AttachToStartingSocket());
}
@@ -437,6 +444,7 @@ namespace HurricaneVR.Framework.Core
{
DrawBoundingBox();
}
if (!IsBeingHeld)
ElapsedSinceReleased += Time.deltaTime;
@@ -445,7 +453,7 @@ namespace HurricaneVR.Framework.Core
ProcessUpdate();
}
private void CheckIfStabbing()
public void CheckIfStabbing()
{
IsStabbing = false;
@@ -465,10 +473,10 @@ namespace HurricaneVR.Framework.Core
if (HandGrabbers.Count > 0)
{
TrackVelocities();
}
ProcessFixedUpdate();
CollidedThisFrame = false;
}
private void OnDestroy()
@@ -486,6 +494,9 @@ namespace HurricaneVR.Framework.Core
protected virtual void OnCollisionEnter(Collision other)
{
if (CollidedThisFrame)
return;
CollidedThisFrame = true;
Collided.Invoke(this);
}
@@ -515,7 +526,6 @@ namespace HurricaneVR.Framework.Core
}
#endif
#endregion
@@ -553,8 +563,6 @@ namespace HurricaneVR.Framework.Core
if (grabPoint.PoserIndex != hand.PoserIndex)
return false;
if(!grabPoint) return false;
if (!grabPoint.gameObject.activeInHierarchy || !grabPoint.enabled)
{
return false;
@@ -612,7 +620,7 @@ namespace HurricaneVR.Framework.Core
}
}
if (closest == null)
if (!closest)
return null;
var currentAngle = Quaternion.Angle(hand.HandWorldRotation, closest.GetPoseWorldRotation(hand.HandSide));
@@ -641,7 +649,7 @@ namespace HurricaneVR.Framework.Core
internal Transform GetGrabPointTransform(HVRHandGrabber hand, GrabpointFilter forceGrab)
{
var gp = GetGrabPoint(hand, forceGrab);
return gp == null ? null : gp.transform;
return !gp ? null : gp.transform;
}
/// <summary>
@@ -890,11 +898,21 @@ namespace HurricaneVR.Framework.Core
if (LinkedGrabbables == null) return false;
for (int i = 0; i < LinkedGrabbables.Count; i++)
if (LinkedGrabbables[i].IsHandGrabbed) return true;
if (LinkedGrabbables[i].IsHandGrabbed)
return true;
return false;
}
public virtual bool CanHandGrab(HVRHandGrabber hand)
{
foreach(var filter in _filters)
if (!filter.CanBeGrabbed(hand))
return false;
return true;
}
#endregion
#region Protected Methods
@@ -904,7 +922,6 @@ namespace HurricaneVR.Framework.Core
/// </summary>
protected virtual void ProcessUpdate()
{
}
/// <summary>
@@ -912,7 +929,6 @@ namespace HurricaneVR.Framework.Core
/// </summary>
protected virtual void ProcessFixedUpdate()
{
}
/// <summary>
@@ -926,6 +942,8 @@ namespace HurricaneVR.Framework.Core
foreach (var c in parent.GetComponents<Collider>())
{
if (!c) continue;
if (c.isTrigger)
{
triggers.Add(c);
@@ -968,10 +986,6 @@ namespace HurricaneVR.Framework.Core
Debug.Log($"{name}:OnBeforeGrabbed");
}
if (GrabberCount == 0)
{
SaveRigidBodyState();
}
AddGrabber(grabber);
}
@@ -984,6 +998,7 @@ namespace HurricaneVR.Framework.Core
{
Debug.Log($"{name}:OnGrabCanceled");
}
//ResetRigidBody();
RemoveGrabber(grabber);
}
@@ -1008,6 +1023,10 @@ namespace HurricaneVR.Framework.Core
if (grabber.IsHandGrabber)
{
HandGrabbed.Invoke(grabber as HVRHandGrabber, this);
if (Rigidbody && !Rigidbody.isKinematic)
{
Rigidbody.collisionDetectionMode = CollisionDetection;
}
}
if (grabber.IsSocket)
@@ -1021,6 +1040,7 @@ namespace HurricaneVR.Framework.Core
}
}
// ReSharper disable Unity.PerformanceAnalysis
/// <summary>
/// Fired after the grabber released this
/// </summary>
@@ -1038,8 +1058,9 @@ namespace HurricaneVR.Framework.Core
RemoveGrabber(grabber);
Socket = null;
IsBeingForcedGrabbed = false;
IsSocketed = false;
RemoveJoint(grabber);
@@ -1048,10 +1069,7 @@ namespace HurricaneVR.Framework.Core
ElapsedSinceReleased = 0f;
if (Rigidbody)
{
if (PalmCenterOfMass) Rigidbody.centerOfMass = _centerOfMass;
Rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete; //preventing warnings
Rigidbody.isKinematic = WasKinematic;
if (!Rigidbody.isKinematic)
{
@@ -1060,6 +1078,7 @@ namespace HurricaneVR.Framework.Core
{
StopCoroutine(_resetCollisionDetectionRoutine);
}
_resetCollisionDetectionRoutine = StartCoroutine(ResetCollisionMode());
}
else
@@ -1069,13 +1088,8 @@ namespace HurricaneVR.Framework.Core
}
}
IsSocketed = _distinctGrabbers.Any(e => e.IsSocket); //really should only be one if socketed...
if (!IsSocketed)
{
Socket = null;
}
if (!PrimaryGrabber && LinkedSocket)
if (!PrimaryGrabber && LinkedSocket && gameObject.activeInHierarchy)
{
StartCoroutine(CheckLinkedSocket());
}
@@ -1100,7 +1114,6 @@ namespace HurricaneVR.Framework.Core
/// </summary>
protected virtual void OnBeforeHandGrabberRemoved(HVRHandGrabber handGrabber)
{
}
protected virtual void OnAfterHandGrabberRemoved(HVRHandGrabber handGrabber)
@@ -1115,8 +1128,9 @@ namespace HurricaneVR.Framework.Core
IsRightHandGrabbed = false;
RightHandGrabber = null;
}
handGrabber.OverrideHandSettings(null);
handGrabber.UpdateGrabbableCOM(this);
if(handGrabber.StrengthHandler)
handGrabber.StrengthHandler.ResetHandOverride();
UpdateHandSettings();
}
@@ -1135,30 +1149,53 @@ namespace HurricaneVR.Framework.Core
IsRightHandGrabbed = true;
RightHandGrabber = handGrabber;
}
UpdateHandSettings();
}
/// <summary>
/// If provided, will update the hand joint settings depending on one or two handed grabs
/// </summary>
protected virtual void UpdateHandSettings()
public virtual void UpdateHandSettings()
{
if ((HandGrabbers.Count >= 2 || ForceTwoHandSettings) && TwoHandJointSettings)
if (HandGrabbers.Count >= 2 || ForceTwoHandSettings)
{
//Debug.Log($"{name} Update two hand : {TwoHandJointSettings?.name} [{ForceTwoHandSettings}]");
for (int i = 0; i < HandGrabbers.Count; i++)
{
HandGrabbers[i].OverrideHandSettings(TwoHandJointSettings);
if (!HandGrabbers[i].StrengthHandler)
continue;
if (TwoHandStrength)
{
HandGrabbers[i].StrengthHandler.OverrideHandSettings(TwoHandStrength);
}
else if (TwoHandJointSettings)
{
HandGrabbers[i].StrengthHandler.OverrideHandSettings(TwoHandJointSettings);
}
else
{
HandGrabbers[i].StrengthHandler.ResetHandOverride();
}
}
}
else if (HandGrabbers.Count > 0)
else if (HandGrabbers.Count == 1 && HandGrabbers[0].StrengthHandler)
{
//Debug.Log($"{name} Update one hand : {OneHandJointSettings?.name}");
HandGrabbers[0].OverrideHandSettings(OneHandJointSettings);
if (OneHandStrength)
{
HandGrabbers[0].StrengthHandler.OverrideHandSettings(OneHandStrength);
}
else if (OneHandJointSettings)
{
HandGrabbers[0].StrengthHandler.OverrideHandSettings(OneHandJointSettings);
}
else
{
HandGrabbers[0].StrengthHandler.ResetHandOverride();
}
}
}
#endregion
#region Private Methods
@@ -1173,7 +1210,12 @@ namespace HurricaneVR.Framework.Core
}
public void LoadFilters()
{
_filters.Clear();
_filters.AddRange(GetComponents<HVRHandGrabFilter>());
}
/// <summary>
/// Locates colliders that are used for line of sight checking and for collision disabling with the grabbing hand when held.
/// </summary>
@@ -1189,8 +1231,8 @@ namespace HurricaneVR.Framework.Core
{
if (collisionParent)
{
Colliders.AddRange(collisionParent.gameObject.GetComponentsInChildren<Collider>().Where(c => !c.isTrigger));
Triggers.AddRange(collisionParent.gameObject.GetComponentsInChildren<Collider>().Where(c => c.isTrigger));
Colliders.AddRange(collisionParent.gameObject.GetComponentsInChildren<Collider>().Where(c => c && !c.isTrigger));
Triggers.AddRange(collisionParent.gameObject.GetComponentsInChildren<Collider>().Where(c => c && c.isTrigger));
}
}
}
@@ -1205,14 +1247,35 @@ namespace HurricaneVR.Framework.Core
{
if (collisionParent)
{
AdditionalIgnoreColliders.AddRange(collisionParent.gameObject.GetComponentsInChildren<Collider>().Where(c => !c.isTrigger));
AdditionalIgnoreColliders.AddRange(collisionParent.gameObject.GetComponentsInChildren<Collider>().Where(c => c && !c.isTrigger));
}
}
}
UpdateIgnoreColliders();
HasConcaveColliders = Triggers.Any(e => { var mesh = e as MeshCollider; return mesh != null && !mesh.convex; });
HasConcaveColliders = HasConcaveColliders || Colliders.Any(e => { var mesh = e as MeshCollider; return mesh && !mesh.convex; });
HasConcaveColliders = Triggers.Any(e =>
{
var mesh = e as MeshCollider;
return mesh != null && !mesh.convex;
});
HasConcaveColliders = HasConcaveColliders || Colliders.Any(e =>
{
var mesh = e as MeshCollider;
return mesh && !mesh.convex;
});
HasWheelCollider = Colliders.Any(e => e is WheelCollider);
}
/// <summary>
/// Caches GrabColliders array into a hashset for lookup for grab detection
/// </summary>
public void SetupGrabColliders()
{
if (GrabColliders != null)
{
GrabCollidersSet = new HashSet<Collider>(GrabColliders);
FilterGrabColliders = GrabColliders.Length > 0;
}
}
public void UpdateIgnoreColliders()
@@ -1254,6 +1317,7 @@ namespace HurricaneVR.Framework.Core
{
_recentVelocities.Enqueue(Rigidbody.velocity);
}
_recentAngularVelocities.Enqueue(angularVelocity);
_previousRotation = transform.rotation;
@@ -1287,31 +1351,6 @@ namespace HurricaneVR.Framework.Core
}
}
private void SaveRigidBodyState()
{
if (!Rigidbody)
return;
WasGravity = Rigidbody.useGravity;
WasKinematic = Rigidbody.isKinematic;
if (!_waitingForColDetectionReset)
{
OriginalCollisionMode = Rigidbody.collisionDetectionMode;
}
_centerOfMass = Rigidbody.centerOfMass;
_mass = Rigidbody.mass;
_rbInterpolation = Rigidbody.interpolation;
}
public virtual void ResetRigidBody()
{
Rigidbody.useGravity = WasGravity;
Rigidbody.mass = _mass;
Rigidbody.collisionDetectionMode = OriginalCollisionMode;
Rigidbody.interpolation = _rbInterpolation;
}
/// <summary>
/// Destroys and cleanups reference to the configurable joint attached to this grabber
/// </summary>
@@ -1331,11 +1370,10 @@ namespace HurricaneVR.Framework.Core
{
if (!Rigidbody)
yield break;
_waitingForColDetectionReset = true;
yield return new WaitForSeconds(10f);
_waitingForColDetectionReset = false;
if (!IsBeingHeld)
if (!IsBeingHeld && Rigidbody)
{
Rigidbody.collisionDetectionMode = OriginalCollisionMode;
}
@@ -1358,8 +1396,6 @@ namespace HurricaneVR.Framework.Core
}
}
#endregion
#region Internal Methods
@@ -1486,7 +1522,6 @@ namespace HurricaneVR.Framework.Core
private Vector3 v3BackBottomRight;
void DrawBoundingBox()
{
Bounds bounds = transform.GetRendererBounds(gameObject);
@@ -1494,14 +1529,14 @@ namespace HurricaneVR.Framework.Core
Vector3 v3Center = bounds.center;
Vector3 v3Extents = bounds.extents;
v3FrontTopLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y + v3Extents.y, v3Center.z - v3Extents.z); // Front top left corner
v3FrontTopRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y + v3Extents.y, v3Center.z - v3Extents.z); // Front top right corner
v3FrontBottomLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y - v3Extents.y, v3Center.z - v3Extents.z); // Front bottom left corner
v3FrontBottomRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y - v3Extents.y, v3Center.z - v3Extents.z); // Front bottom right corner
v3BackTopLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y + v3Extents.y, v3Center.z + v3Extents.z); // Back top left corner
v3BackTopRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y + v3Extents.y, v3Center.z + v3Extents.z); // Back top right corner
v3BackBottomLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y - v3Extents.y, v3Center.z + v3Extents.z); // Back bottom left corner
v3BackBottomRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y - v3Extents.y, v3Center.z + v3Extents.z); // Back bottom right corner
v3FrontTopLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y + v3Extents.y, v3Center.z - v3Extents.z); // Front top left corner
v3FrontTopRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y + v3Extents.y, v3Center.z - v3Extents.z); // Front top right corner
v3FrontBottomLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y - v3Extents.y, v3Center.z - v3Extents.z); // Front bottom left corner
v3FrontBottomRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y - v3Extents.y, v3Center.z - v3Extents.z); // Front bottom right corner
v3BackTopLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y + v3Extents.y, v3Center.z + v3Extents.z); // Back top left corner
v3BackTopRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y + v3Extents.y, v3Center.z + v3Extents.z); // Back top right corner
v3BackBottomLeft = new Vector3(v3Center.x - v3Extents.x, v3Center.y - v3Extents.y, v3Center.z + v3Extents.z); // Back bottom left corner
v3BackBottomRight = new Vector3(v3Center.x + v3Extents.x, v3Center.y - v3Extents.y, v3Center.z + v3Extents.z); // Back bottom right corner
var color = Color.magenta;
@@ -1526,12 +1561,16 @@ namespace HurricaneVR.Framework.Core
public enum GrabpointFilter
{
Normal, ForceGrab, Socket
Normal,
ForceGrab,
Socket
}
public enum GrabBehaviour
{
Default, PullToHand, HandRetrieves
Default,
PullToHand,
HandRetrieves
}
@@ -0,0 +1,20 @@
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Grabbers;
using UnityEngine;
/// <summary>
/// Optional filter applied to HVRGrabbable object to decide if the potential hand can grab this object
/// </summary>
[RequireComponent(typeof(HVRGrabbable))]
public abstract class HVRHandGrabFilter : MonoBehaviour
{
public HVRGrabbable Grabbable { get; set; }
protected virtual void Awake()
{
if (TryGetComponent(out HVRGrabbable g))
Grabbable = g;
}
public abstract bool CanBeGrabbed(HVRHandGrabber hand);
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8bef30b910ae46c4acd561544cc1e389
timeCreated: 1674090329
@@ -18,7 +18,7 @@ namespace HurricaneVR.Framework.Core
public void SetupColliders()
{
HandColliders = GetComponentsInChildren<Collider>().Where(e => !e.isTrigger).ToArray();
HandColliders = GetComponentsInChildren<Collider>().Where(e => !e.isTrigger && e.enabled).ToArray();
}
public void DisableCollision()
@@ -0,0 +1,12 @@
using HurricaneVR.Framework.Core.Sockets;
namespace HurricaneVR.Framework.Core
{
/// <summary>
/// Dummy socketable added while linking in case one isn't provided so the socket code will not break.
/// </summary>
public class HVRLinkedSocketable : HVRSocketable
{
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e342e34c74884f399b6b418e8b6b9273
timeCreated: 1666497596
@@ -10,7 +10,7 @@ namespace HurricaneVR.Framework.Core
[Tooltip("If the required grabbable is dropped, should we release?")]
public bool DropIfReleased;
[Tooltip("If the required grabbable is dropped, let's try and grab it.")]
[Tooltip("If the required grabbable is dropped, let's try and grab it.")]
public bool GrabRequiredIfReleased;
}
}
@@ -55,7 +55,6 @@ namespace HurricaneVR.Framework.Core
public string LocalEditorRootDirectory;
public string LocalRootDirectory;
public string LocalResourcesDirectory;
public string LocalReferencePoseDirectory;
public string LocalRuntimePosesDirectory;
public string LocalPosesDirectory;
@@ -69,7 +68,6 @@ namespace HurricaneVR.Framework.Core
public const string DefaultLeftHand = "HVR_left_hand";
public const string DefaultRightHand = "HVR_right_hand";
public const string ReferencePoses = "ReferencePoses";
public const string RuntimePoses = "RuntimePoses";
[Header("Misc Settings")]
@@ -151,7 +149,6 @@ namespace HurricaneVR.Framework.Core
Debug.LogException(e);
}
//TryCreateReferencePoseFolder();
TryCreateRuntimePoseFolder();
SetupDefaultHands(settings);
@@ -216,10 +213,6 @@ namespace HurricaneVR.Framework.Core
return path;
}
private string GetDefaultReferencePoseDirectory()
{
return Path.Combine(GetResourcesDirectory(), ReferencePoses);
}
private string GetDefaultRuntimePosesDirectory()
{
@@ -281,26 +274,7 @@ namespace HurricaneVR.Framework.Core
Debug.LogException(e);
}
}
private void TryCreateReferencePoseFolder()
{
try
{
if (string.IsNullOrEmpty(LocalResourcesDirectory)) return;
if (string.IsNullOrEmpty(LocalReferencePoseDirectory))
{
LocalReferencePoseDirectory = LocalResourcesDirectory + "ReferencePoses" + Path.DirectorySeparatorChar;
}
Directory.CreateDirectory(GetDefaultReferencePoseDirectory());
}
catch (Exception e)
{
Debug.LogException(e);
}
}
private void TryCreateRuntimePoseFolder()
{
@@ -324,9 +298,6 @@ namespace HurricaneVR.Framework.Core
[InspectorButton("ShowPosesFolderChooser")]
public string ChosePosesDirectory = "Choose Pose Directory";
//[InspectorButton("ShowReferencePosesFolderChooser", 300)]
//public string ChoseReferencePosesDirectory = "Choose Reference Poses Directory";
[InspectorButton("ShowRuntimePosesFolderChooser", 300)]
public string ChoseRunTimePosesDirectory = "Choose RunTime Poses Directory";
@@ -347,15 +318,7 @@ namespace HurricaneVR.Framework.Core
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
public void ShowReferencePosesFolderChooser()
{
var ReferencePoseDirectory = EditorUtility.OpenFolderPanel("Choose Pose Directory", null, null);
LocalReferencePoseDirectory = ReferencePoseDirectory.Substring(Application.dataPath.IndexOf("Assets"));
EditorUtility.SetDirty(this);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
[InspectorButton("ReloadGlobalsMethod")]
public string ReloadGlobals = "Reload Globals";
@@ -458,25 +421,6 @@ namespace HurricaneVR.Framework.Core
return null;
}
public void SaveReferencePose(HVRHandPose pose, string name)
{
try
{
if (!name.EndsWith(".asset"))
{
name += ".asset";
}
var path = Path.Combine(LocalReferencePoseDirectory, name);
AssetUtils.CreateOrReplaceAsset(pose, path);
Debug.Log($"Saved {name} to {LocalReferencePoseDirectory}");
}
catch (Exception e)
{
Debug.LogException(e);
}
}
public void AddAssetToResource<T>(T asset, string name) where T : Object
{
try
@@ -0,0 +1,87 @@
using System;
using Assets.HurricaneVR.Framework.Shared.Utilities;
using HurricaneVR.Framework.Core.Grabbers;
using UnityEngine;
namespace HurricaneVR.Framework.Core
{
[RequireComponent(typeof(HVRGrabbable))]
public class HVRSocketLink : MonoBehaviour
{
public HVRSocket Socket;
public float ReturnTime = 0f;
public bool PlaySocketedSFX = true;
public HVRGrabbable Grabbable { get; private set; }
private bool _returning;
private float _time;
private float _elapsed;
private Vector3 _startPos;
private Quaternion _startRot;
protected virtual void Awake()
{
Setup();
}
public void Setup()
{
Grabbable = GetComponent<HVRGrabbable>();
Grabbable.HandFullReleased.AddListener(OnGrabbableReleased);
if (!Grabbable.Socketable)
{
//Socket code expects this, add dummy if not found.
Grabbable.Socketable = Grabbable.gameObject.AddComponent<HVRLinkedSocketable>();
}
if (Socket)
{
Socket.LinkedGrabbable = Grabbable;
this.ExecuteNextUpdate(() => Socket.TryGrab(Grabbable, true, true));
}
}
protected virtual void Update()
{
if (_returning)
{
var pos = Socket.transform.TransformPoint(Socket.GetTargetPosition(Grabbable));
var rot = Socket.transform.rotation * Socket.GetTargetRotation(Grabbable);
var lerp = _elapsed / _time;
_elapsed += Time.deltaTime;
Grabbable.transform.position = Vector3.Lerp(_startPos, pos, lerp);
Grabbable.transform.rotation = Quaternion.Lerp(_startRot, rot, lerp);
if (lerp >= 1f)
{
Grabbable.CanBeGrabbed = true;
_returning = false;
Grabbable.ResetToNonTrigger();
Socket.TryGrab(Grabbable, true, PlaySocketedSFX);
}
}
}
private void OnGrabbableReleased(HVRGrabberBase arg0, HVRGrabbable arg1)
{
if (!Socket)
return;
if (ReturnTime > 0f)
{
_returning = true;
var pos = Socket.transform.TransformPoint(Socket.GetTargetPosition(Grabbable));
_time = ReturnTime;
_elapsed = 0f;
Grabbable.SetAllToTrigger();
_startPos = Grabbable.transform.position;
_startRot = Grabbable.transform.rotation;
Grabbable.CanBeGrabbed = false;
}
else
{
Socket.TryGrab(Grabbable, true, PlaySocketedSFX);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 96785e435f4a7a04d84021e497eeb783
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -11,11 +11,8 @@ namespace HurricaneVR.Framework.Core.HandPoser
{
[FormerlySerializedAs("PosePosAndRot")]
[Header("Settings")]
[Tooltip("True for floaty hands, false for FinalIK hands")]
public bool PoseHand = true;
[Tooltip("If true the default poser will pause the hand")]
public bool DefaultPoseHand = true;
[Tooltip("If true the default poser will pose the hand's local position and rotation")]
public bool DefaultPoseHand = true; //fyi - false is best, only left true for older users and their projects
[Tooltip("Finger bend speed when dynamic pose is active")]
public float DynamicPoseSpeed = 16f;
@@ -24,11 +21,16 @@ namespace HurricaneVR.Framework.Core.HandPoser
public HVRPhysicsPoser PhysicsPoser;
public HVRPosableHand Hand;
public HVRHandPoser DefaultPoser;
[Tooltip("Used if the HVRPosableHand component is not on the transform that needs to be posed. IKTarget for VRIK is one example.")]
public Transform HandOverride;
[Header("Debug View")]
public HVRHandPoser CurrentPoser;
public HVRHandPoser OverridePoser;
/// <summary>
/// Current hand pose, moves towards BlendedPose based on the speed defined on the Primary Pose
/// </summary>
@@ -74,7 +76,13 @@ namespace HurricaneVR.Framework.Core.HandPoser
public bool DynamicPose { get; set; }
/// <summary>
/// Returns true if the CurrentPoser is a pose from a held object
/// </summary>
public bool HandHeldPose { get; internal set; }
private bool _poseHand = true;
private bool _poseHandOverride;
private float[] _fingerCurls;
protected virtual void Start()
@@ -170,31 +178,53 @@ namespace HurricaneVR.Framework.Core.HandPoser
return;
}
if (CurrentPoser == null)
var poseHand = _poseHand;
var poser = CurrentPoser;
if (OverridePoser && !HandHeldPose)
{
return;
poser = OverridePoser;
poseHand = _poseHandOverride;
}
UpdateBlends();
ApplyBlending();
Hand.Pose(CurrentPose, _poseHand);
if (!poser)
return;
UpdateBlends(poser);
ApplyBlending(poser);
if (poseHand)
{
if (HandOverride)
{
HandOverride.localPosition = CurrentPose.Position;
HandOverride.localRotation = CurrentPose.Rotation;
}
else
{
Hand.Pose(CurrentPose, true);
}
}
else
{
Hand.Pose(CurrentPose, false);
}
}
private void UpdateBlends()
private void UpdateBlends(HVRHandPoser poser)
{
if (!IsMine)
return;
UpdateBlendValue(CurrentPoser.PrimaryPose);
UpdateBlendValue(poser.PrimaryPose);
if (CurrentPoser.Blends == null)
if (poser.Blends == null)
{
return;
}
for (int i = 0; i < CurrentPoser.Blends.Count; i++)
for (int i = 0; i < poser.Blends.Count; i++)
{
UpdateBlendValue(CurrentPoser.Blends[i]);
UpdateBlendValue(poser.Blends[i]);
}
}
@@ -242,16 +272,16 @@ namespace HurricaneVR.Framework.Core.HandPoser
}
private void ApplyBlending()
private void ApplyBlending(HVRHandPoser poser)
{
PrimaryPose.CopyTo(BlendedPose);
ApplyFingerCurls(DefaultPose, PrimaryPose, BlendedPose, CurrentPoser.PrimaryPose);
ApplyFingerCurls(DefaultPose, PrimaryPose, BlendedPose, poser.PrimaryPose);
if (CurrentPoser.Blends != null)
if (poser.Blends != null)
{
for (int i = 0; i < CurrentPoser.Blends.Count; i++)
for (int i = 0; i < poser.Blends.Count; i++)
{
var blend = CurrentPoser.Blends[i];
var blend = poser.Blends[i];
if (blend.Disabled || !blend.Pose)
{
@@ -275,7 +305,7 @@ namespace HurricaneVR.Framework.Core.HandPoser
}
}
ApplyBlend(CurrentPose, BlendedPose, CurrentPoser.PrimaryPose, CurrentPoser.PrimaryPose.Speed);
ApplyBlend(CurrentPose, BlendedPose, poser.PrimaryPose, poser.PrimaryPose.Speed);
}
/// <summary>
@@ -432,24 +462,18 @@ namespace HurricaneVR.Framework.Core.HandPoser
}
}
public void ResetIfNotDefault()
{
if (CurrentPoser != DefaultPoser)
ResetToDefault();
}
public void ResetToDefault()
{
DynamicPose = false;
if (DefaultPoser != null)
_poseHand = DefaultPoseHand;
CurrentPoser = DefaultPoser;
if (HandHeldPose || !OverridePoser)
{
SetCurrentPoser(DefaultPoser, DefaultPoseHand);
SetupPoser(CurrentPoser);
}
else
else if (OverridePoser)
{
Debug.Log("Default poser not set.");
SetupPoser(OverridePoser);
}
}
@@ -460,17 +484,61 @@ namespace HurricaneVR.Framework.Core.HandPoser
PrimaryPose = pose;
_poseHand = false;
}
public void SetCurrentPoser(HVRHandPoser poser, bool poseHand = true)
/// <summary>
/// Sets or reset (pass null) a poser that will take precedence over framework hover posers, but won't take precedence over held object poses.
/// </summary>
public virtual void SetOverridePoser(HVRHandPoser poser, bool poseHand = false)
{
_poseHandOverride = poseHand;
OverridePoser = poser;
if (!poser)
{
SetupPoser(CurrentPoser);
}
else if (!HandHeldPose)
{
SetupPoser(poser);
}
}
public void SetHeldPoser(HVRHandPoser poser, bool poseHand = false)
{
HandHeldPose = true;
_poseHand = poseHand;
CurrentPoser = poser;
SetupPoser(poser);
}
public void OnHeldObjectReleased()
{
HandHeldPose = false;
DynamicPose = false;
CurrentPoser = DefaultPoser;
_poseHand = DefaultPoseHand;
if (OverridePoser)
{
SetupPoser(OverridePoser);
}
else
{
SetupPoser(CurrentPoser);
}
}
public virtual void SetCurrentPoser(HVRHandPoser poser, bool poseHand = false)
{
_poseHand = poseHand;
if (!PoseHand)
{
//hand grabber handles posing the IKTarget since the posable hand component is placed on the avatar itself
_poseHand = false;
}
CurrentPoser = poser;
if (poser == null || poser.PrimaryPose == null) return;
if (!OverridePoser || HandHeldPose)
SetupPoser(poser);
}
protected virtual void SetupPoser(HVRHandPoser poser)
{
if (!poser || poser.PrimaryPose == null) return;
PrimaryPose = poser.PrimaryPose.Pose.GetPose(Hand.IsLeft);
@@ -487,12 +555,12 @@ namespace HurricaneVR.Framework.Core.HandPoser
}
}
for (var i = 0; i < poser.Blends.Count; i++)
{
poser.Blends[i].Value = 0f; //reset blend weight
poser.Blends[i].Value = 0f; //reset blend weight
PrimaryPose.CopyTo(Blends[i]); //copy primary pose to the blend pose as a base
}
}
}
}
}
@@ -10,6 +10,7 @@ namespace HurricaneVR.Framework.Core.HandPoser
None = 0, Hand = 1, Thumb = 2, Index = 4, Middle = 8, Ring = 16, Pinky = 32
}
[HelpURL("https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/hand_posing.html")]
public class HVRHandPoser : MonoBehaviour
{
#region EditorState
@@ -47,7 +48,6 @@ namespace HurricaneVR.Framework.Core.HandPoser
public HVRHandPoseBlend PrimaryPose;
public List<HVRHandPoseBlend> Blends = new List<HVRHandPoseBlend>();
public HVRHandPose ReferencePose;
public MirrorAxis MirrorAxis = MirrorAxis.X;
private void Awake()
@@ -0,0 +1,9 @@
using UnityEngine;
namespace HurricaneVR.Framework.Core.HandPoser
{
public class HVRHandTrigger : MonoBehaviour
{
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 364f55a0f60644beb4e906f6db185d28
timeCreated: 1661135657
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using HurricaneVR.Framework.Core.Grabbers;
using HurricaneVR.Framework.Core.Utils;
using UnityEngine;
namespace HurricaneVR.Framework.Core.HandPoser
{
public class HVRPoseZone : MonoBehaviour
{
[Tooltip("Decide to ignore non trigger colliders or not on the hand for stable detection of non moving colliders.")]
public bool UseHandTriggersOnly = true;
[Tooltip("Uses box overlap or sphere overlap")]
public bool UseBox = true;
public Vector3 OverlapBox = new Vector3(.15f, .15f, .15f);
public float OverlapRadius = .15f;
[Tooltip("Layer mask of the hand collider for performant detection")]
public LayerMask HandMask;
[Tooltip("Poser that defines the pose to animate to, captured on awake from same object if not supplied.")]
public HVRHandPoser Poser;
private readonly List<HVRHandGrabber> overlappedHands = new List<HVRHandGrabber>(2);
private readonly List<HVRHandGrabber> hands = new List<HVRHandGrabber>(2);
private readonly Collider[] _colliders = new Collider[100];
private void Awake()
{
if (!Poser)
{
TryGetComponent(out Poser);
}
}
private void FixedUpdate()
{
hands.Clear();
int count;
if (UseBox)
{
count = Physics.OverlapBoxNonAlloc(transform.position, OverlapBox * .5f, _colliders, transform.rotation, HandMask, QueryTriggerInteraction.Collide);
}
else
{
count = Physics.OverlapSphereNonAlloc(transform.position, OverlapRadius, _colliders, HandMask, QueryTriggerInteraction.Collide);
}
for (int i = 0; i < count; i++)
{
var c = _colliders[i];
var hand = c.FindComponent<HVRHandGrabber>();
if (!hand) continue;
if (c.isTrigger)
{
if (!c.TryGetComponent(out HVRHandTrigger _))
{
//ignore triggers that aren't marked with HVRHandTrigger or a child of the hand model so that other triggers on the hand rigidbody
//that are used for other purposes like the distance grabber are aren't considered
if (hand.HandAnimator && (!c.transform.IsChildOf(hand.HandAnimator.Hand.transform)) && c.transform != hand.HandAnimator.Hand.transform)
{
continue;
}
}
}
else if (UseHandTriggersOnly)
{
continue;
}
hands.Add(hand);
}
foreach (var hand in hands)
{
if (!overlappedHands.Contains(hand))
{
hand.SetAnimatorOverridePose(Poser);
overlappedHands.Add(hand);
}
}
for (var i = overlappedHands.Count - 1; i >= 0; i--)
{
var hand = overlappedHands[i];
if (!hand || !hands.Contains(hand))
{
hand.SetAnimatorOverridePose(null);
overlappedHands.RemoveAt(i);
}
}
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.green;
if (UseBox)
{
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireCube(Vector3.zero, OverlapBox);
}
else
{
Gizmos.DrawWireSphere(transform.position, OverlapRadius);
}
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 81ed24babdf5471dbf0b20a8d9f02ba1
timeCreated: 1661109513
@@ -16,8 +16,7 @@ namespace HurricaneVR.Framework.Core.Player
/// <summary>
/// HMD transform used to detect HMD movement at start
/// </summary>
[Header("Required Transforms")]
public Transform Camera;
[Header("Required Transforms")] public Transform Camera;
/// <summary>
/// Camera rig child used to offset the Y height of the HMD.
@@ -32,15 +31,13 @@ namespace HurricaneVR.Framework.Core.Player
/// <summary>
/// Manually setting this will raise / lower the HMD
/// </summary>
[Header("Manual Camera Offsetting")]
[Tooltip("Manually modify the camera height if needed")]
[Header("Manual Camera Offsetting")] [Tooltip("Manually modify the camera height if needed")]
public float CameraYOffset;
/// <summary>
/// Used with height calibration to define the virtual player's HMD sight line.
/// </summary>
[FormerlySerializedAs("PlayerHeight")]
[Tooltip("Height of the virtual player")]
[FormerlySerializedAs("PlayerHeight")] [Tooltip("Height of the virtual player")]
public float EyeHeight = 1.66f;
/// <summary>
@@ -48,19 +45,14 @@ namespace HurricaneVR.Framework.Core.Player
/// Standing - CameraScale is scaled based on the ratio of EyeHeight / HMD height.
/// PlayerHeight - No offsetting or scaling performed.
/// </summary>
[Tooltip("Sitting or standing mode")]
public HVRSitStand SitStanding = HVRSitStand.PlayerHeight;
[Tooltip("Sitting or standing mode")] public HVRSitStand SitStanding = HVRSitStand.PlayerHeight;
[Header("Debug Height Offsets")]
[Tooltip("If true, use up and down arrow to change YOffset to help with testing.")]
[Header("Debug Height Offsets")] [Tooltip("If true, use up and down arrow to change YOffset to help with testing.")]
public bool DebugKeyboardOffset;
public float DebugKeyboardIncrement = .25f;
[Header("Debug Height Calibration")]
/// <summary>
/// Calibration height is saved to player prefs when height is calibrated.
/// </summary>
@@ -90,7 +82,6 @@ namespace HurricaneVR.Framework.Core.Player
public KeyCode RecalibrateKey = KeyCode.R;
#elif ENABLE_INPUT_SYSTEM
public Key HeightCalibrateKey = Key.R;
#endif
@@ -98,8 +89,7 @@ namespace HurricaneVR.Framework.Core.Player
/// <summary>
/// Set by the player controller to raise / lower the camera rig when performing a input driven crouch.
/// </summary>
[Header("For Debugging Display only")]
public float PlayerControllerYOffset = 0f;
[Header("For Debugging Display only")] public float PlayerControllerYOffset = 0f;
/// <summary>
/// Floor offset height adjusted by the Standing camera scale (if any).
@@ -202,16 +192,18 @@ namespace HurricaneVR.Framework.Core.Player
{
if (IsMine)
{
if (DebugKeyboardOffset)
{
#if ENABLE_LEGACY_INPUT_MANAGER
if (DebugKeyboardOffset && UnityEngine.Input.GetKeyDown(KeyCode.DownArrow))
{
CameraYOffset += -DebugKeyboardIncrement;
}
else if (DebugKeyboardOffset && UnityEngine.Input.GetKeyDown(KeyCode.UpArrow))
{
CameraYOffset += DebugKeyboardIncrement;
}
if (UnityEngine.Input.GetKeyDown(KeyCode.DownArrow))
{
CameraYOffset += -DebugKeyboardIncrement;
}
else if (UnityEngine.Input.GetKeyDown(KeyCode.UpArrow))
{
CameraYOffset += DebugKeyboardIncrement;
}
#elif ENABLE_INPUT_SYSTEM
if (Keyboard.current[Key.UpArrow].wasPressedThisFrame)
{
@@ -222,6 +214,7 @@ namespace HurricaneVR.Framework.Core.Player
CameraYOffset += -DebugKeyboardIncrement;
}
#endif
}
if (DebugKeyboardRecalibrate)
{
@@ -314,6 +307,8 @@ namespace HurricaneVR.Framework.Core.Player
public enum HVRDebugCalibrate
{
None, HMDMoved, Immediately
None,
HMDMoved,
Immediately
}
}
@@ -1,4 +1,6 @@
using HurricaneVR.Framework.Core.ScriptableObjects;
using System;
using HurricaneVR.Framework.Core.ScriptableObjects;
using HurricaneVR.Framework.Core.Utils;
using UnityEngine;
namespace HurricaneVR.Framework.Core.Player
@@ -6,11 +8,18 @@ namespace HurricaneVR.Framework.Core.Player
public class HVRHandStrengthHandler : MonoBehaviour
{
[Header("Debug")]
public HVRJointSettings CurrentSettings;
public bool LogStrengthChanges;
[Tooltip("If true will update the joint every update - useful for tweaking HVRJointSettings in play mode.")]
public bool AlwaysUpdateJoint;
[Tooltip("Active strength profile")]
public PDStrength CurrentStrength;
[Tooltip("Deprecated active strength profile")]
public HVRJointSettings CurrentSettings;
[Tooltip("Enable to print to console when the strength profile changes")]
public bool LogStrengthChanges;
public HVRJointSettings JointSettings { get; private set; }
@@ -18,6 +27,12 @@ namespace HurricaneVR.Framework.Core.Player
public HVRJointSettings HandGrabberOverride { get; private set; }
public PDStrength DefaultStrength { get; private set; }
public PDStrength StrengthOverride { get; private set; }
public PDStrength HandGrabOverride { get; private set; }
public ConfigurableJoint Joint { get; set; }
public bool Stopped { get; private set; }
@@ -42,6 +57,12 @@ namespace HurricaneVR.Framework.Core.Player
JointSettings = defaultSettings;
UpdateJoint();
}
public void Initialize(PDStrength defaultSettings)
{
DefaultStrength = defaultSettings;
UpdateJoint();
}
protected virtual void FixedUpdate()
{
@@ -51,12 +72,20 @@ namespace HurricaneVR.Framework.Core.Player
}
}
protected virtual void UpdateJoint()
public virtual void UpdateJoint()
{
if (Stopped)
return;
if (HandGrabberOverride)
if (StrengthOverride)
{
UpdateStrength(StrengthOverride);
}
else if (HandGrabOverride)
{
UpdateStrength(HandGrabOverride);
}
else if (HandGrabberOverride)
{
UpdateStrength(HandGrabberOverride);
}
@@ -68,8 +97,30 @@ namespace HurricaneVR.Framework.Core.Player
{
UpdateStrength(JointSettings);
}
else if (DefaultStrength)
{
UpdateStrength(DefaultStrength);
}
}
// ReSharper disable Unity.PerformanceAnalysis
protected virtual void UpdateStrength(PDStrength settings)
{
if (!settings) return;
CurrentStrength = settings;
if(settings.Mode != JointApply.Rotation)
Joint.SetLinearDrive(settings.Spring, settings.Damper, settings.MaxForce);
if(settings.Mode != JointApply.Position)
Joint.SetSlerpDrive(settings.TorqueSpring, settings.TorqueDamper, settings.MaxTorque);
if (LogStrengthChanges)
{
Debug.Log($"{settings.name} applied.");
}
}
// ReSharper disable Unity.PerformanceAnalysis
protected virtual void UpdateStrength(HVRJointSettings settings)
{
if (settings)
@@ -90,7 +141,7 @@ namespace HurricaneVR.Framework.Core.Player
UpdateJoint();
}
public virtual void OverrideHandSettings(HVRJointSettings settings)
internal virtual void OverrideHandSettings(HVRJointSettings settings)
{
HandGrabberOverride = settings;
UpdateJoint();
@@ -99,6 +150,32 @@ namespace HurricaneVR.Framework.Core.Player
public virtual void StopOverride()
{
JointOverride = null;
StrengthOverride = null;
UpdateJoint();
}
public virtual void ResetHandOverride()
{
var needsReset = HandGrabberOverride || HandGrabOverride;
HandGrabberOverride = null;
HandGrabOverride = null;
if(needsReset)
UpdateJoint();
}
/// <summary>
/// Override the strength profile. Takes precedence over grabbable strength overrides.
/// Call StopOverride to revert to default strength.
/// </summary>
public virtual void OverrideSettings(PDStrength settings)
{
StrengthOverride = settings;
UpdateJoint();
}
public virtual void OverrideHandSettings(PDStrength settings)
{
HandGrabOverride = settings;
UpdateJoint();
}
@@ -113,5 +190,18 @@ namespace HurricaneVR.Framework.Core.Player
Stopped = false;
UpdateJoint();
}
}
[Serializable]
public class HandStrength
{
public bool UseOneHandStrength;
public bool UseTwoHandStrength;
public PDStrength OneHandStrength;
public PDStrength TwoHandStrength;
}
}
@@ -17,14 +17,20 @@ namespace HurricaneVR.Framework.Core.Player
/// Default hand strength settings.
/// </summary>
[Header("Settings")]
[Tooltip("Default hand strength settings.")]
public HVRJointSettings JointSettings;
[Embedded]
[Tooltip("Default hand strength settings.")]
public PDStrength Strength;
[Tooltip("Physx constraint iterations")]
public int SolverIterations = 10;
[Tooltip("Physx constraint iterations")]
public int SolverVelocityIterations = 10;
/// <summary>
/// The speed at which the hand returns to the controller when the MaxDistanceBehaviour is not set to HandSweep
@@ -66,6 +72,10 @@ namespace HurricaneVR.Framework.Core.Player
[Tooltip("Target transform for position and rotation tracking")]
public Transform Target;
[Header("Deprecated")]
[Tooltip("Default hand strength settings.")]
public HVRJointSettings JointSettings;
/// <summary>
/// Kinematic rigidbody that will hold the joint for stability.
/// </summary>
@@ -103,10 +113,9 @@ namespace HurricaneVR.Framework.Core.Player
public HVRHandGrabber Grabber { get; private set; }
private Vector3 _previousControllerPosition;
public Vector3 PreviousControllerPosition { get; set; }
private Quaternion _previousRotation;
private float _timer = 0f;
private bool _hasTeleporter;
private float _teleportTimer = 0f;
protected virtual void Awake()
{
@@ -126,10 +135,15 @@ namespace HurricaneVR.Framework.Core.Player
Teleporter = transform.root.GetComponentInChildren<HVRTeleporter>();
}
_hasTeleporter = Teleporter;
if (Teleporter)
{
Teleporter.PositionUpdate.AddListener(OnPlayerTeleported);
Teleporter.BeforeDashTeleport.AddListener(OnBeforeDashTeleport);
Teleporter.AfterDashTeleport.AddListener(OnAfterDashTeleport);
}
if (!JointSettings)
Debug.LogError("JointSettings field is empty, must be populated with HVRJointSettings scriptable object.");
if (!Strength)
Debug.LogError("Strength field is empty, must be populated with PDStrength scriptable object.");
if (!StrengthHandler)
{
@@ -143,12 +157,23 @@ namespace HurricaneVR.Framework.Core.Player
ReturnSpeed = 5f;
StrengthHandler.Joint = Joint;
StrengthHandler.Initialize(JointSettings);
if(JointSettings) StrengthHandler.Initialize(JointSettings);
else StrengthHandler.Initialize(Strength);
}
private void OnAfterDashTeleport(Vector3 arg0)
{
Enable();
}
private void OnBeforeDashTeleport(Vector3 arg0)
{
Disable();
}
protected virtual void Start()
{
_previousControllerPosition = Target.position;
PreviousControllerPosition = Target.position;
_previousRotation = Target.rotation;
//fixing the issue where the hand goes to world 0,0,0 at start
StartCoroutine(StopHandsRoutine());
@@ -224,17 +249,16 @@ namespace HurricaneVR.Framework.Core.Player
}
public virtual void OnPlayerTeleported(Vector3 position)
{
_teleportTimer = Time.time;
SaveTargetState(); //updating state after teleport
}
protected virtual void UpdateDistanceCheck()
{
if (_hasTeleporter)
{
if (Teleporter.TeleportState == TeleportState.None) _timer += Time.deltaTime;
else _timer = 0f;
if (_timer < .5f)
return;
}
if (Time.time - _teleportTimer < .5f)
return;
if (!IsReturningToController)
{
@@ -298,22 +322,26 @@ namespace HurricaneVR.Framework.Core.Player
RigidBody.detectCollisions = false;
}
public virtual void UpdateTargetVelocity()
{
var worldVelocity = (Target.position - _previousControllerPosition) / Time.fixedDeltaTime;
_previousControllerPosition = Target.position;
Joint.targetVelocity = ParentRigidBody.transform.InverseTransformDirection(worldVelocity);
var angularVelocity = Target.rotation.AngularVelocity(_previousRotation);
Joint.targetAngularVelocity = Quaternion.Inverse(ParentRigidBody.transform.rotation) * angularVelocity;
if (Joint.rotationDriveMode == RotationDriveMode.XYAndZ)
if (!(Vector3.SqrMagnitude(Target.position - PreviousControllerPosition) > 1f))
{
Joint.targetAngularVelocity *= -1;
var worldVelocity = (Target.position - PreviousControllerPosition) / Time.fixedDeltaTime;
Joint.targetVelocity = ParentRigidBody.transform.InverseTransformDirection(worldVelocity);
}
var angularVelocity = Target.rotation.AngularVelocity(_previousRotation);
Joint.targetAngularVelocity = Quaternion.Inverse(ParentRigidBody.transform.rotation) * angularVelocity;
SaveTargetState();
}
/// <summary>
/// Saves the controller position and rotation, call this if you manually move the player outside of the framework teleporter code.
/// </summary>
public void SaveTargetState()
{
PreviousControllerPosition = Target.position;
_previousRotation = Target.rotation;
}
@@ -333,4 +361,4 @@ namespace HurricaneVR.Framework.Core.Player
GrabbableDrops,
HandSweep
}
}
}
@@ -17,6 +17,7 @@ namespace HurricaneVR.Framework.Core.Player
{
[Header("Settings")]
public bool CanJump = false;
public bool CanSteerWhileJumping = true;
public bool CanSprint = true;
public bool CanCrouch = true;
@@ -29,27 +30,36 @@ namespace HurricaneVR.Framework.Core.Player
public LayerMask GroundedLayerMask;
public float GroundedDistance = .02f;
[Tooltip("Grounded sphere case radius factor multiplied by the capsules radius for ground checking.")]
public float GroundedRadiusFactor = .5f;
[Tooltip("Minimum Player Capsule Height.")]
public float MinHeight = .3f;
[Header("Locomotion")]
public bool InstantAcceleration = true;
[Tooltip("Walking speed in m/s.")]
public float Acceleration = 15;
public float Deacceleration = 15f;
public float MoveSpeed = 1.5f;
public float SprintAcceleration = 20f;
[Tooltip("Sprinting speed in m/s.")]
public float RunSpeed = 3.5f;
public float Gravity = 9.81f;
public float MaxFallSpeed = 2f;
public float JumpVelocity = 5f;
[Tooltip("Double click timeout for sprinting.")]
public float DoubleClickThreshold = .25f;
[Header("Turning")]
public RotationType RotationType;
public float SmoothTurnSpeed = 90f;
public float SmoothTurnThreshold = .1f;
public float SnapAmount = 45f;
@@ -61,18 +71,18 @@ namespace HurricaneVR.Framework.Core.Player
public bool RotateWhileTeleportAiming;
[Header("Crouching")]
[Tooltip("Player height must be above this to toggle crouch.")]
public float CrouchMinHeight = 1.2f;
[Tooltip("Player height after toggling a crouch via controller.")]
public float CrouchHeight = 0.7f;
[Tooltip("Speed at which toggle crouch moves the player up and down.")]
public float CrouchSpeed = 1.5f;
[Header("Transforms")]
public Transform Camera;
public Transform NeckPivot;
public Transform Root;
public Transform FloorOffset;
@@ -81,6 +91,7 @@ namespace HurricaneVR.Framework.Core.Player
[Header("Components")]
public HVRCameraRig CameraRig;
public HVRHandGrabber LeftHand;
public HVRHandGrabber RightHand;
public HVRJointHand LeftJointHand;
@@ -89,23 +100,26 @@ namespace HurricaneVR.Framework.Core.Player
[Header("Head Collision")]
public HVRHeadCollision HeadCollision;
public float HeadCollisionFadeSpeed = 1f;
[Tooltip("If true, when your head collides it returns your head to the body's position")]
public bool HeadCollisionPushesBack = true;
[Tooltip("If true, limits the head distance from the body by MaxLean amount.")]
public bool LimitHeadDistance = true;
[Tooltip("If LimitHeadDistance is true, the max distance your head can be from your body.")]
public float MaxLean = .5f;
[Tooltip("Screen fades when leaning to far into something.")]
public bool FadeFromLean = true;
[Header("Debugging")]
public bool MouseTurning;
public float MouseSensitivityX = 1f;
public float MouseSensitivityX = 1f;
public Rigidbody RigidBody { get; private set; }
@@ -114,10 +128,7 @@ namespace HurricaneVR.Framework.Core.Player
public virtual float CameraHeight
{
get
{
return CameraRig.AdjustedCameraHeight;
}
get { return CameraRig.AdjustedCameraHeight; }
}
public bool IsCrouching => CameraHeight < CrouchMinHeight;
@@ -126,7 +137,9 @@ namespace HurricaneVR.Framework.Core.Player
public bool Sprinting { get; set; }
public bool IsGrounded;// { get; set; }
public bool IsGrounded; // { get; set; }
public Vector3 GroundNormal { get; set; }
public bool MovementEnabled { get; set; } = true;
public bool RotationEnabled { get; set; } = true;
@@ -135,8 +148,8 @@ namespace HurricaneVR.Framework.Core.Player
public HVRPlayerInputs Inputs { get; private set; }
public Vector3 PreviousPosition { get; protected set; }
public Vector3 PreviousPosition { get; set; }
private Vector3 _previousLeftControllerPosition;
private Vector3 _previousRightControllerPosition;
@@ -158,8 +171,10 @@ namespace HurricaneVR.Framework.Core.Player
private Vector3 _previousVelocity;
private float yVelocity;
private Vector3 xzVelocity;
private Quaternion _preTeleportRotation;
[SerializeField] private float _actualVelocity;
[SerializeField]
private float _actualVelocity;
protected virtual void Awake()
{
@@ -169,6 +184,8 @@ namespace HurricaneVR.Framework.Core.Player
if (Teleporter)
{
_hasTeleporter = true;
Teleporter.BeforeTeleport.AddListener(OnBeforeTeleport);
Teleporter.PositionUpdate.AddListener(OnTeleported);
}
if (NeckPivot)
@@ -188,6 +205,21 @@ namespace HurricaneVR.Framework.Core.Player
ScreenFader = finder.gameObject.GetComponent<HVRScreenFade>();
}
}
PreviousPosition = transform.position;
}
private void OnTeleported(Vector3 arg0)
{
//prevent teleporting from impulsing the hand calcs in AdjustHandAcceleration
PreviousPosition = transform.position;
var rot = transform.rotation * Quaternion.Inverse(_preTeleportRotation);
_previousVelocity = rot * _previousVelocity;
}
private void OnBeforeTeleport(Vector3 arg0)
{
_preTeleportRotation = transform.rotation;
}
@@ -240,6 +272,10 @@ namespace HurricaneVR.Framework.Core.Player
protected virtual void Update()
{
// if (Input.GetKeyDown(KeyCode.Q))
// {
// Teleporter.Teleport(transform.position, Quaternion.AngleAxis(90f, Vector3.up) * transform.forward);
// }
CheckCameraCorrection();
CheckSprinting();
UpdateHeight();
@@ -262,7 +298,8 @@ namespace HurricaneVR.Framework.Core.Player
if (CharacterController.enabled)
{
HandleMovement();
HandleMovement();
if (CanRotate())
{
@@ -274,7 +311,6 @@ namespace HurricaneVR.Framework.Core.Player
CheckGrounded();
_actualVelocity = ((transform.position - PreviousPosition) / Time.deltaTime).magnitude;
_previousLeftControllerPosition = LeftControllerTransform.position;
@@ -307,18 +343,22 @@ namespace HurricaneVR.Framework.Core.Player
delta.y = 0f;
CameraRig.transform.position -= delta;
_waitingForCameraMovement = false;
PreviousPosition = transform.position;
}
protected virtual void CheckGrounded()
{
var origin = CharacterController.center - Vector3.up * (.5f * CharacterController.height - CharacterController.radius);
var radius = CharacterController.radius * GroundedRadiusFactor;
var origin = CharacterController.center - Vector3.up * (.5f * CharacterController.height - radius);
IsGrounded = Physics.SphereCast(
transform.TransformPoint(origin) + Vector3.up * CharacterController.contactOffset,
CharacterController.radius,
transform.TransformPoint(origin) + Vector3.up * CharacterController.contactOffset,
radius,
Vector3.down,
out var hit,
GroundedDistance + CharacterController.contactOffset,
GroundedLayerMask, QueryTriggerInteraction.Ignore);
GroundNormal = hit.normal;
}
protected virtual void CheckLean()
@@ -330,7 +370,7 @@ namespace HurricaneVR.Framework.Core.Player
delta.y = 0;
if (delta.sqrMagnitude < .01f || delta.magnitude < MaxLean) return;
if (FadeFromLean)
{
StartCoroutine(CorrectCamera());
@@ -358,6 +398,7 @@ namespace HurricaneVR.Framework.Core.Player
delta.y = 0f;
if (delta.magnitude > 0.0f && CharacterController.enabled)
{
delta = Vector3.ProjectOnPlane(delta, GroundNormal);
CharacterController.Move(delta);
}
@@ -438,6 +479,7 @@ namespace HurricaneVR.Framework.Core.Player
{
HandleHMDMovement();
}
HandleHorizontalMovement();
HandleVerticalMovement();
AdjustHandAcceleration();
@@ -494,7 +536,7 @@ namespace HurricaneVR.Framework.Core.Player
yVelocity = Mathf.Clamp(yVelocity, -MaxFallSpeed, yVelocity);
}
velocity.y = yVelocity;
velocity.y += yVelocity;
CharacterController.Move(velocity * Time.deltaTime);
}
@@ -519,6 +561,11 @@ namespace HurricaneVR.Framework.Core.Player
if (IsGrounded || CanSteerWhileJumping)
{
if (IsGrounded)
{
direction = Vector3.ProjectOnPlane(direction, GroundNormal);
}
if (InstantAcceleration)
{
xzVelocity = speed * direction;
@@ -549,22 +596,35 @@ namespace HurricaneVR.Framework.Core.Player
}
}
/// <summary>
/// Accounts for the instantaneous acceleration of the player, without this the hands would lag behind
/// </summary>
protected virtual void AdjustHandAcceleration()
{
var v = (transform.position - PreviousPosition) / Time.deltaTime;
var acceler = (v - _previousVelocity) / Time.deltaTime;
_previousVelocity = v;
LeftJointHand.RigidBody.AddForce(acceler * LeftJointHand.RigidBody.mass, ForceMode.Force);
RightJointHand.RigidBody.AddForce(acceler * RightJointHand.RigidBody.mass, ForceMode.Force);
var leftRB = LeftHand.GrabbedTarget?.Rigidbody;
var rightRb = RightHand.GrabbedTarget?.Rigidbody;
Rigidbody leftRB = null;
Rigidbody rightRb = null;
if (LeftHand.GrabbedTarget && LeftHand.GrabbedTarget.Rigidbody)
{
leftRB = LeftHand.GrabbedTarget.Rigidbody;
}
if (RightHand.GrabbedTarget && RightHand.GrabbedTarget.Rigidbody)
{
rightRb = RightHand.GrabbedTarget.Rigidbody;
}
if (leftRB && rightRb && leftRB == rightRb)
{
LeftJointHand.RigidBody.AddForce(acceler * .5f * leftRB.mass, ForceMode.Force);
RightJointHand.RigidBody.AddForce(acceler * .5f * rightRb.mass, ForceMode.Force);
LeftJointHand.RigidBody.AddForce(acceler * (.5f * leftRB.mass), ForceMode.Force);
RightJointHand.RigidBody.AddForce(acceler * (.5f * rightRb.mass), ForceMode.Force);
}
else
{
@@ -642,7 +702,6 @@ namespace HurricaneVR.Framework.Core.Player
}
else
{
if (Sprinting && Inputs.IsSprintingActivated)
Sprinting = false;
else if (!Sprinting && Inputs.IsSprintingActivated)
@@ -687,7 +746,6 @@ namespace HurricaneVR.Framework.Core.Player
_cameraBelowCrouchHeight = true;
}
}
}
protected virtual void Crouch()
@@ -761,23 +819,23 @@ namespace HurricaneVR.Framework.Core.Player
/// </summary>
public void RemoveMultiplayerComponents()
{
foreach (var t in new[]{
typeof(HVRCamera),
typeof(Camera),
typeof(AudioListener),
//typeof(TrackedPoseDriver),
typeof(HVRScreenFade),
typeof(HVRHeadCollision),
typeof(HVRThrowingCenterOfMass),
typeof(HVRControllerOffset), typeof(HVRJointHand)
})
foreach (var t in new[]
{
typeof(HVRCamera),
typeof(Camera),
typeof(AudioListener),
//typeof(TrackedPoseDriver),
typeof(HVRScreenFade),
typeof(HVRHeadCollision),
typeof(HVRThrowingCenterOfMass),
typeof(HVRControllerOffset), typeof(HVRJointHand)
})
{
foreach (var component in GetComponentsInChildren(t))
{
Destroy(component);
}
}
}
public void SetTurnType(RotationType rotationType)
@@ -800,7 +858,8 @@ namespace HurricaneVR.Framework.Core.Player
var f = Camera.forward;
f.y = 0f;
forward.y = 0f;
transform.rotation = Quaternion.FromToRotation(f, forward) * transform.rotation;
var rotation = Quaternion.AngleAxis(Vector3.SignedAngle(f, forward, Vector3.up), Vector3.up);
transform.rotation = rotation * transform.rotation;
}
}
@@ -816,7 +875,4 @@ namespace HurricaneVR.Framework.Core.Player
Smooth,
Snap
}
}
@@ -208,19 +208,14 @@ namespace HurricaneVR.Framework.Core.Player
if (LeftJointHand)
{
LeftJointHand.Disable();
LeftJointHand.RigidBody.detectCollisions = false;
}
if (RightJointHand)
{
RightJointHand.Disable();
RightJointHand.RigidBody.detectCollisions = false;
}
LeftHand.Rigidbody.velocity = Vector3.zero;
RightHand.Rigidbody.velocity = Vector3.zero;
_previousPosition = position;
}
@@ -257,9 +252,6 @@ namespace HurricaneVR.Framework.Core.Player
RightJointHand.RigidBody.position = RightJointHand.RigidBody.position;
}
//SweepHand(LeftHand, leftGrabbable);
//SweepHand(RightHand, rightGrabbable);
_previousPosition = position;
}
@@ -323,9 +315,29 @@ namespace HurricaneVR.Framework.Core.Player
}
Physics.SyncTransforms();
StartCoroutine(AfterFixedUpdate());
var direction = (_teleportStart - _teleportEnd).normalized;
direction.y = 0f;
var offset = Vector3.zero;
if (leftGrabbable) offset = leftGrabbable.transform.InverseTransformPoint(RightHand.transform.position);
PostTeleportSweep(LeftHand, leftGrabbable, direction);
if (leftGrabbable && leftGrabbable == rightGrabbable)
{
RightHand.transform.position = leftGrabbable.transform.TransformPoint(offset);
RightHand.Rigidbody.position = RightHand.transform.position;
}
else
{
PostTeleportSweep(RightHand, rightGrabbable, direction);
}
leftGrabbable = null;
rightGrabbable = null;
}
@@ -346,8 +358,7 @@ namespace HurricaneVR.Framework.Core.Player
SweepHand(hand, hand.GrabbedTarget, target);
}
#endregion
#endregion
#region Protected
@@ -382,7 +393,7 @@ namespace HurricaneVR.Framework.Core.Player
hand.Rigidbody.position = origin.position;
var bounds = hand.Rigidbody.GetColliderBounds();
var bounds = hand.HandPhysics.HandColliders.GetColliderBounds();
var maxSide = Mathf.Max(bounds.size.x, bounds.size.y, bounds.size.z);
var start = bounds.center;
var length = Vector3.Distance(target, start);
@@ -437,7 +448,7 @@ namespace HurricaneVR.Framework.Core.Player
hand.transform.position = hand.Rigidbody.position = target;
}
bounds = hand.Rigidbody.GetColliderBounds();
bounds = hand.HandPhysics.HandColliders.GetColliderBounds();
if (VerboseDebug) DrawSweepLines(hand, start, direction, length);
if (VerboseDebug) CastEnd(hand, bounds, start, direction, length);
@@ -448,7 +459,6 @@ namespace HurricaneVR.Framework.Core.Player
//backout after forward sweep
var offset = Vector3.zero;
for (var d = 0f; d < backoutDistance; d += .05f)
@@ -467,71 +477,6 @@ namespace HurricaneVR.Framework.Core.Player
hand.transform.position = hand.Rigidbody.position;
}
protected virtual IEnumerator AfterFixedUpdate()
{
yield return new WaitForFixedUpdate();
var lgPos = Vector3.zero;
var rgPos = Vector3.zero;
var lgRot = Quaternion.identity;
var rgRot = Quaternion.identity;
if (leftGrabbable) LeftJointHand.transform.GetRelativeValues(leftGrabbable.transform, out lgPos, out lgRot);
if (rightGrabbable) RightJointHand.transform.GetRelativeValues(rightGrabbable.transform, out rgPos, out rgRot);
LeftJointHand.RigidBody.position = LeftJointHand.Target.position;
RightJointHand.RigidBody.position = RightJointHand.Target.position;
if (leftGrabbable)
{
leftGrabbable.transform.SetPositionAndRotation(
LeftJointHand.transform.TransformPoint(lgPos),
LeftJointHand.transform.rotation * lgRot);
if (leftGrabbable.Rigidbody) leftGrabbable.Rigidbody.velocity = Vector3.zero;
}
if (rightGrabbable)
{
rightGrabbable.transform.SetPositionAndRotation(
RightJointHand.transform.TransformPoint(rgPos),
RightJointHand.transform.rotation * rgRot);
if (rightGrabbable.Rigidbody) rightGrabbable.Rigidbody.velocity = Vector3.zero;
}
Physics.SyncTransforms();
LeftHand.Rigidbody.velocity = Vector3.zero;
RightHand.Rigidbody.velocity = Vector3.zero;
LeftJointHand.Enable();
RightJointHand.Enable();
var direction = (_teleportStart - _teleportEnd).normalized;
direction.y = 0f;
var pos = LeftHand.transform.position;
var offset = Vector3.zero;
if (leftGrabbable) offset = leftGrabbable.transform.InverseTransformPoint(RightHand.transform.position);
PostTeleportSweep(LeftHand, leftGrabbable, direction);
if (leftGrabbable && leftGrabbable == rightGrabbable)
{
RightHand.transform.position = leftGrabbable.transform.TransformPoint(offset);
RightHand.Rigidbody.position = RightHand.transform.position;
}
else
{
PostTeleportSweep(RightHand, rightGrabbable, direction);
}
leftGrabbable = null;
rightGrabbable = null;
}
/// <summary>
/// Handles sweeping the hand and grabbable after a teleport sequence.
/// </summary>
@@ -574,7 +519,7 @@ namespace HurricaneVR.Framework.Core.Player
return other && other.GrabbedTarget && other.GrabbedTarget.HasCollider(c);
}
#endregion
#endregion
#region Private
@@ -676,7 +621,7 @@ namespace HurricaneVR.Framework.Core.Player
private void Backout(HVRHandGrabber hand, HVRGrabbable g, Vector3 direction, HVRTeleportOptions options)
{
var bounds = hand.Rigidbody.GetColliderBounds();
var bounds = hand.HandPhysics.HandColliders.GetColliderBounds();
if (options && options.CustomBoundingBox)
{
@@ -709,7 +654,7 @@ namespace HurricaneVR.Framework.Core.Player
if (VerboseDebug)
{
bounds = hand.Rigidbody.GetColliderBounds();
bounds = hand.HandPhysics.HandColliders.GetColliderBounds();
if (options && options.CustomBoundingBox)
{
@@ -757,7 +702,7 @@ namespace HurricaneVR.Framework.Core.Player
}
#endregion
#region Debugging
@@ -792,7 +737,6 @@ namespace HurricaneVR.Framework.Core.Player
[Serializable]
public class GrabbableStuck : UnityEvent<HVRGrabbable>
{
}
public class GrabbableCollisionTracker
@@ -816,4 +760,4 @@ namespace HurricaneVR.Framework.Core.Player
StartTime = Time.time;
}
}
}
}
@@ -13,6 +13,7 @@ namespace HurricaneVR.Framework.Core.Player
{
[Header("Transforms / Components")]
public Transform Camera;
public Transform TeleportLineSourceLeft;
public Transform TeleportLineSourceRight;
public HVRHandGrabber LeftHand;
@@ -20,7 +21,6 @@ namespace HurricaneVR.Framework.Core.Player
public HVRPlayerController Player;
[Header("Teleport Disable Checks")]
[Tooltip("Should player rotation disable teleport aiming?")]
public bool PlayerRotateCheck = true;
@@ -36,6 +36,7 @@ namespace HurricaneVR.Framework.Core.Player
[Header("Visuals")]
public Color ValidColor = new Color(2, 212, 186);
public Color InvalidColor = new Color(221, 37, 37);
public LineRenderer LineRenderer;
public LineRenderer DownRenderer;
@@ -64,16 +65,17 @@ namespace HurricaneVR.Framework.Core.Player
[Header("Ballistic Settings")]
public float Speed = 7.5f;
public float TimeStep = .01f;
[Header("Bezier Settings")]
public float BezierAngleOffset = .3f;
public AnimationCurve BezierAngleOffsetCurve;
public float TeleportDistance = 5f;
[Header("Downward Ray cast")]
[Tooltip("Max length of the downwards ray cast")]
public float DownRayLength = 5f;
@@ -83,10 +85,10 @@ namespace HurricaneVR.Framework.Core.Player
[Header("Dash Teleport")]
public bool Dash;
public float DashSpeed = 15f;
[Header("Origin Line Of Sight")]
[Tooltip("If true line of sight from the camera to the origin of the teleport line is required")]
public bool RequireOriginLineOfSight;
@@ -95,8 +97,6 @@ namespace HurricaneVR.Framework.Core.Player
[Header("Destination Line Of Sight")]
[Tooltip("If true line of sight from the camera to the teleport destination is required")]
public bool RequireDestinationLineOfSight;
@@ -110,7 +110,6 @@ namespace HurricaneVR.Framework.Core.Player
[Header("Destination Validation")]
[Tooltip("If true the fall distance from the bottom of the capsule cannot exceed MaxDropDistance")]
public bool CheckDropDistance;
@@ -135,15 +134,16 @@ namespace HurricaneVR.Framework.Core.Player
public CapsuleCollider Capsule;
public TeleportPositionUpdate BeforeDashTeleport = new TeleportPositionUpdate();
public TeleportPositionUpdate AfterDashTeleport = new TeleportPositionUpdate();
public TeleportPositionUpdate BeforeTeleport = new TeleportPositionUpdate();
public UnityEvent AfterTeleport = new UnityEvent();
public TeleportPositionUpdate PositionUpdate = new TeleportPositionUpdate();
[Header("Debugging")]
public Vector3 DownHitNormal;
public float SurfaceAngle;
public bool IsDropDistanceValid;
public bool IsSurfaceAngleValid;
@@ -214,7 +214,7 @@ namespace HurricaneVR.Framework.Core.Player
/// </summary>
public int LastIndex { get; protected set; }
public Transform TeleportLineSource => TeleportHand == HVRHandSide.Left ? TeleportLineSourceLeft : TeleportLineSourceRight;
public virtual Transform TeleportLineSource => TeleportHand == HVRHandSide.Left ? TeleportLineSourceLeft : TeleportLineSourceRight;
/// <summary>
/// Did the forward raycast find a valid teleportable location
@@ -253,6 +253,7 @@ namespace HurricaneVR.Framework.Core.Player
protected float _timeSinceLastRotation;
protected Quaternion _previousPlayerRotation;
private Vector3 _leftVel, _rightVel, _leftHeldVel, _rightHeldVel;
protected virtual void Awake()
@@ -305,8 +306,6 @@ namespace HurricaneVR.Framework.Core.Player
}
public virtual void Enable()
{
CanTeleport = true;
@@ -334,6 +333,7 @@ namespace HurricaneVR.Framework.Core.Player
{
IsTeleportValid = false;
}
SurfaceAngle = Vector3.Angle(Vector3.up, SurfaceNormal);
CheckValidTeleportChanged(IsTeleportPreviouslyValid);
HandleValidStatus(IsTeleportValid);
@@ -391,14 +391,7 @@ namespace HurricaneVR.Framework.Core.Player
else if (TeleportState == TeleportState.Teleporting)
{
UpdateTeleport();
}
else if (TeleportState == TeleportState.AwaitingNextFrame)
{
OnAfterTeleport();
if (Dash)
{
OnAfterDashTeleport();
}
}
}
@@ -409,7 +402,7 @@ namespace HurricaneVR.Framework.Core.Player
return;
}
if (IsTeleportActivated())
if (!IsAiming && IsTeleportActivated())
{
OnTeleportActivated();
}
@@ -450,7 +443,7 @@ namespace HurricaneVR.Framework.Core.Player
HitPosition = forwardHit.point - direction.normalized * CollisionBuffer;
HitCollider = forwardHit.collider;
destination = forwardHit.point;// + VerticalBuffer;
destination = forwardHit.point; // + VerticalBuffer;
if (CheckValidDestination(HitCollider.gameObject, destination, forwardHit.normal))
{
@@ -476,7 +469,7 @@ namespace HurricaneVR.Framework.Core.Player
LastDownwardPoint = downwardHit.point;
DownHitNormal = downwardHit.normal;
destination = downwardHit.point;// + VerticalBuffer;
destination = downwardHit.point; // + VerticalBuffer;
if (!CheckValidDestination(downwardHit.collider.gameObject, destination, downwardHit.normal))
{
@@ -530,7 +523,6 @@ namespace HurricaneVR.Framework.Core.Player
protected virtual void HandleValidStatus(bool valid)
{
}
protected virtual void OnTeleportActivated()
@@ -797,7 +789,7 @@ namespace HurricaneVR.Framework.Core.Player
length = hit.distance;
}
var point = ray.GetPoint(length);// - CollisionBuffer);
var point = ray.GetPoint(length); // - CollisionBuffer);
return point;
}
@@ -811,6 +803,7 @@ namespace HurricaneVR.Framework.Core.Player
angle = MaxAngle;
return Vector3.RotateTowards(Vector3.down, Forward, Mathf.Deg2Rad * MaxAngle, 0f);
}
return Forward;
}
@@ -995,10 +988,42 @@ namespace HurricaneVR.Framework.Core.Player
protected virtual void OnBeforeDashTeleport()
{
var leftGrabbable = LeftHand.GrabbedTarget;
var rightGrabbable = RightHand.GrabbedTarget;
_leftVel = LeftHand.Rigidbody.velocity;
_rightVel = RightHand.Rigidbody.velocity;
_leftHeldVel = Vector3.zero;
_rightHeldVel = Vector3.zero;
var lrb = leftGrabbable ? leftGrabbable.Rigidbody : null;
var rrb = rightGrabbable ? rightGrabbable.Rigidbody : null;
if (lrb) _leftHeldVel = lrb.velocity;
if (rrb) _rightHeldVel = rrb.velocity;
//execute last, hand will disable itself in it's event handler
BeforeDashTeleport.Invoke(FeetPosition);
}
protected virtual void OnAfterDashTeleport()
{
//execute first, hand will enable itself in it's event handler
AfterDashTeleport.Invoke(FeetPosition);
//restore velocity from before dash
var leftGrabbable = LeftHand.GrabbedTarget;
var rightGrabbable = RightHand.GrabbedTarget;
var lrb = leftGrabbable ? leftGrabbable.Rigidbody : null;
var rrb = rightGrabbable ? rightGrabbable.Rigidbody : null;
LeftHand.Rigidbody.velocity = _leftVel;
RightHand.Rigidbody.velocity = _rightVel;
if (lrb) lrb.velocity = _leftHeldVel;
if (rrb && rrb != lrb) rrb.velocity = _rightHeldVel;
}
protected virtual void OnBeforeTeleport()
@@ -1021,20 +1046,24 @@ namespace HurricaneVR.Framework.Core.Player
if (RightHand) RightHand.BreakDistanceCooldown();
}
/// <summary>
/// Instantly teleports the player to the desired position
/// </summary>
public virtual bool Teleport(Vector3 position)
{
if (IsTeleporting)
return false;
OnBeforeTeleport();
TeleportState = TeleportState.Teleporting;
TeleportDestination = position;
Teleport(position, Vector3.zero, false);
return true;
}
public virtual void Teleport(Vector3 position, Vector3 direction)
/// <summary>
/// Optionally rotate the player to the desired direction, and then instantly teleports the player to the desired position
/// </summary>
public virtual void Teleport(Vector3 position, Vector3 direction, bool faceDirection = true)
{
if (!Teleport(position))
if (IsTeleporting)
return;
if (!Player) return;
@@ -1050,40 +1079,80 @@ namespace HurricaneVR.Framework.Core.Player
//snapshot relative values and then reapply after rotating the player
var leftGrabbable = LeftHand.GrabbedTarget;
var rightGrabbable = RightHand.GrabbedTarget;
if (LeftHand)
{
Player.GetRelativeValues(LeftHand, out leftPos, out leftRot);
if (LeftHand.GrabbedTarget)
LeftHand.GetRelativesTo(Player, out leftPos, out leftRot);
if (leftGrabbable)
{
LeftHand.GetRelativeValues(LeftHand.GrabbedTarget, out leftGrabPos, out leftGrabRot);
leftGrabbable.MainTransform.GetRelativesTo(LeftHand, out leftGrabPos, out leftGrabRot);
}
}
if (RightHand)
{
Player.GetRelativeValues(RightHand, out rightPos, out rightRot);
if (RightHand.GrabbedTarget) RightHand.GetRelativeValues(RightHand.GrabbedTarget, out rightGrabPos, out rightGrabRot);
RightHand.GetRelativesTo(Player, out rightPos, out rightRot);
if (rightGrabbable)
{
rightGrabbable.MainTransform.GetRelativesTo(RightHand, out rightGrabPos, out rightGrabRot);
}
}
Player.FaceDirection(direction);
var lv = LeftHand.Rigidbody.velocity;
var rv = RightHand.Rigidbody.velocity;
var leftObjV = Vector3.zero;
var rightObjV = Vector3.zero;
var lrb = leftGrabbable ? leftGrabbable.Rigidbody : null;
var rrb = rightGrabbable ? rightGrabbable.Rigidbody : null;
if (lrb) leftObjV = lrb.velocity;
if (rrb) rightObjV = rrb.velocity;
BeforeTeleport.Invoke(FeetPosition);
var before = Player.transform.rotation;
if (faceDirection)
Player.FaceDirection(direction);
var rot = Player.transform.rotation * Quaternion.Inverse(before);
lv = rot * lv;
rv = rot * rv;
leftObjV = rot * leftObjV;
rightObjV = rot * rightObjV;
if (LeftHand)
{
LeftHand.transform.SetPositionAndRotation(Player.transform.TransformPoint(leftPos), Player.transform.rotation * leftRot);
if (LeftHand.GrabbedTarget)
if (leftGrabbable)
{
LeftHand.GrabbedTarget.transform.SetPositionAndRotation(LeftHand.transform.TransformPoint(leftGrabPos), LeftHand.transform.rotation * leftGrabRot);
leftGrabbable.MainTransform.SetPositionAndRotation(LeftHand.transform.TransformPoint(leftGrabPos), LeftHand.transform.rotation * leftGrabRot);
}
}
if (RightHand)
{
RightHand.transform.SetPositionAndRotation(Player.transform.TransformPoint(rightPos), Player.transform.rotation * rightRot);
if (RightHand.GrabbedTarget)
if (rightGrabbable)
{
RightHand.GrabbedTarget.transform.SetPositionAndRotation(RightHand.transform.TransformPoint(rightGrabPos), RightHand.transform.rotation * rightGrabRot);
rightGrabbable.MainTransform.SetPositionAndRotation(RightHand.transform.TransformPoint(rightGrabPos), RightHand.transform.rotation * rightGrabRot);
}
}
UpdatePlayerPosition(position);
PositionUpdate.Invoke(FeetPosition);
AfterTeleport.Invoke();
LeftHand.Rigidbody.velocity = lv;
RightHand.Rigidbody.velocity = rv;
if (lrb) lrb.velocity = leftObjV;
if (rrb && rrb != lrb) rrb.velocity = rightObjV;
}
protected virtual Vector3 FeetPosition => CharacterController.transform.position;
@@ -1099,7 +1168,8 @@ namespace HurricaneVR.Framework.Core.Player
{
UpdatePlayerPosition(TeleportDestination);
PositionUpdate.Invoke(FeetPosition);
TeleportState = TeleportState.AwaitingNextFrame;
OnAfterTeleport();
OnAfterDashTeleport();
}
}
@@ -1107,7 +1177,6 @@ namespace HurricaneVR.Framework.Core.Player
{
UpdatePlayerPosition(TeleportDestination);
PositionUpdate.Invoke(FeetPosition);
TeleportState = TeleportState.AwaitingNextFrame;
}
protected virtual void RightHandReleased(HVRGrabberBase arg0, HVRGrabbable grabbable)
@@ -1145,20 +1214,19 @@ namespace HurricaneVR.Framework.Core.Player
public enum HVRTeleportCurve
{
Ballistic, Bezier
Ballistic,
Bezier
}
public enum TeleportState
{
None,
Teleporting,
Dashing,
AwaitingNextFrame
Dashing
}
[Serializable]
public class TeleportPositionUpdate : UnityEvent<Vector3>
{
}
}
}
@@ -100,9 +100,9 @@ namespace HurricaneVR.Framework.Core.ScriptableObjects
{
mass = joint.connectedBody.mass;
}
else
else if(joint.gameObject.TryGetComponent(out Rigidbody rb))
{
mass = joint.gameObject.GetComponent<Rigidbody>().mass;
mass = rb.mass;
}
}
@@ -0,0 +1,22 @@
using System;
using UnityEngine;
using UnityEngine.Serialization;
namespace HurricaneVR.Framework.Core.ScriptableObjects
{
[CreateAssetMenu(menuName = "HurricaneVR/Hand Strength", fileName = "HandStrength")]
public class PDStrength : ScriptableObject
{
public JointApply Mode = JointApply.PositionAndRotation;
//[Header("Force")]
public float Spring = 3000f;
public float Damper = 300f;
public float MaxForce = 300f;
//[Header("Torque")]
public float TorqueSpring = 500f;
public float TorqueDamper = 50f;
public float MaxTorque = 75f;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 595f9e32dd154ba28dcd9b9fb86e85eb
timeCreated: 1666138458
@@ -5,6 +5,9 @@ using UnityEngine;
namespace HurricaneVR.Framework.Core.Sockets
{
/// <summary>
/// Groups sockets together for inventory like querying
/// </summary>
public class HVRSocketContainer : MonoBehaviour
{
[Tooltip("Adds all sockets found on or below this object.")]
@@ -19,11 +22,9 @@ namespace HurricaneVR.Framework.Core.Sockets
Sockets = GetComponentsInChildren<HVRSocket>().ToList();
}
void Update()
{
}
/// <summary>
/// Returns true if any socket in the container is not currently holding an object
/// </summary>
public virtual bool HasAvailableSocket()
{
for (var i = 0; i < Sockets.Count; i++)
@@ -35,11 +36,22 @@ namespace HurricaneVR.Framework.Core.Sockets
return false;
}
/// <summary>
/// Returns true if any socket in the container is free and is able to socket this grabbable based on the socket filter applied
/// </summary>
/// <param name="grabbable"></param>
/// <returns></returns>
public virtual bool HasAvailableSocket(HVRGrabbable grabbable)
{
return TryFindAvailableSocket(grabbable, out var socket);
}
/// <summary>
/// Returns true if any socket in the container is free and able to socket the provided grabbable based on the filter applied.
/// </summary>
/// <param name="grabbable">Grabbable to check the filter for</param>
/// <param name="socket">Resulting free socket, null if none found</param>
/// <returns></returns>
public virtual bool TryFindAvailableSocket(HVRGrabbable grabbable, out HVRSocket socket)
{
socket = Sockets.FirstOrDefault(e => !e.IsGrabbing && e.IsValid(grabbable));
@@ -48,6 +60,11 @@ namespace HurricaneVR.Framework.Core.Sockets
return true;
}
/// <summary>
/// Sockets the grabbable to the first found free socket if any are available, returns true if it succeeded
/// </summary>
/// <param name="grabbable"></param>
/// <returns></returns>
public virtual bool TryAddGrabbable(HVRGrabbable grabbable)
{
if (TryFindAvailableSocket(grabbable, out var socket))
@@ -11,5 +11,10 @@ namespace HurricaneVR.Framework.Core.Sockets
/// Return true if the HVRSocketable is allowed in the socket this filter is attached to.
/// </summary>
public abstract bool IsValid(HVRSocketable socketable);
protected virtual void Awake()
{
}
}
}
@@ -1,25 +1,46 @@
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using HurricaneVR.Framework.Core.Grabbers;
using HurricaneVR.Framework.Shared;
using UnityEngine;
namespace HurricaneVR.Framework.Core.Sockets
{
[RequireComponent(typeof(HVRGrabbable))]
public class HVRSocketable : MonoBehaviour
{
public HVRGrabbable Grabbable { get; private set; }
public Transform SocketOrientation;
public float SocketScale = 1f;
[Tooltip("Stores relative position and rotation information for any socket type.")]
public List<SocketPose> Poses = new List<SocketPose>();
[Tooltip("If your grabbable model is not at 1,1,1 scale. ")]
public Vector3 CounterScale = Vector3.one;
[Header("Scaling")] [Tooltip("If true the the renderer bounds at the time of socketing will be used to scale the object in a socket that has scaling enabled.")]
public bool UseRendererBounds = true;
[Tooltip("If greater than 0 and UseRendererBounds is disabled, the size used when computing socket scale when socketing into a socket with scale enabled.")]
public float ScaleSize = 0f;
[Tooltip("Socket scale factor applied after socketing.")]
public float SocketScale = 1f;
[Tooltip("Override renderer bounds when socket is scaling")]
public BoxCollider ScaleOverride;
public AudioClip SocketedClip;
[Header("SFX")] public AudioClip SocketedClip;
public AudioClip UnsocketedClip;
[Tooltip("If populated this object cannot be socketed if any of these objects are held.")]
public HVRGrabbable[] LinkedGrabbables;
[Header("Deprecated")]
public Transform SocketOrientation;
public bool AnyLinkedGrabbablesHeld
{
get
@@ -40,9 +61,115 @@ namespace HurricaneVR.Framework.Core.Sockets
}
}
private void Start()
private Dictionary<int, SocketPose> _poseCache = new Dictionary<int, SocketPose>();
protected virtual void Awake()
{
Grabbable = GetComponent<HVRGrabbable>();
InitializePoses();
}
public void InitializePoses()
{
foreach (var pose in Poses)
{
pose.Init();
}
_poseCache = Poses.Where(e => !string.IsNullOrWhiteSpace(e.SocketTag))
.GroupBy(e=>e.Hash)
.ToDictionary(e => e.Key, e => e.First());
}
public virtual float GetSocketScaleSize(HVRSocket socket)
{
Vector3 size;
if (ScaleOverride)
{
size = ScaleOverride.size;
}
else
{
if (!UseRendererBounds && ScaleSize > 0f)
{
return ScaleSize;
}
//making sure the AABB is aligned the same every time before pulling the renderer bounds
var rot = transform.rotation;
transform.rotation = Quaternion.identity;
#if UNITY_EDITOR
if (!Grabbable)
{
Grabbable = GetComponent<HVRGrabbable>();
}
#endif
size = Grabbable.ModelBounds.size;
transform.rotation = rot;
}
var axis = size.x;
if (size.y > axis) axis = size.y;
if (size.z > axis) axis = size.z;
return axis;
}
public virtual Vector3 GetPositionOffset(HVRSocket socket)
{
if (socket.PoseHash.HasValue && _poseCache.TryGetValue(socket.PoseHash.Value, out var pose))
{
return pose.Position;
}
return Vector3.zero;
}
public virtual Quaternion GetRotationOffset(HVRSocket socket)
{
if (socket.PoseHash.HasValue && _poseCache.TryGetValue(socket.PoseHash.Value, out var pose))
{
return pose.Rotation;
}
return Quaternion.identity;
}
}
[Serializable]
public class SocketPose
{
public string SocketTag;
public Vector3 Position;
public Vector3 EulerAngles;
private Quaternion? _rotation;
public Quaternion Rotation
{
get
{
if (!_rotation.HasValue)
_rotation = Quaternion.Euler(EulerAngles);
return _rotation.Value;
}
}
public int Hash { get; private set; }
public void Init()
{
if (SocketTag != null)
Hash = Animator.StringToHash(SocketTag);
}
}
}
@@ -10,6 +10,27 @@ namespace HurricaneVR.Framework.Core.Sockets
{
[SerializeField] private string[] _socketables = new string[32];
[Tooltip("Needed to identify this tag file when using addressables. Will populate with the SO name if not provided.")]
public string Identifier;
public int Hash { get; set; }
protected virtual void Awake()
{
if (string.IsNullOrWhiteSpace(Identifier))
{
Identifier = name;
}
Hash = Animator.StringToHash(Identifier);
}
public virtual bool MatchesTags(HVRSocketableTags other)
{
return other.Hash == Hash;
}
public string this[int index]
{
get { return _socketables[index]; }
@@ -1,17 +1,37 @@
namespace HurricaneVR.Framework.Core.Sockets
using UnityEngine;
namespace HurricaneVR.Framework.Core.Sockets
{
public class HVRStringSocketFilter : HVRSocketFilter
{
[Tooltip("Lower cased and trimmed prior to hashing.")]
public string SocketType;
public int? Hash { get; private set; }
protected override void Awake()
{
base.Awake();
ResetHash();
}
public void ResetHash()
{
if (!string.IsNullOrWhiteSpace(SocketType))
{
SocketType = SocketType.Trim();
Hash = Animator.StringToHash(SocketType.ToLowerInvariant());
}
}
public override bool IsValid(HVRSocketable socketable)
{
if (string.IsNullOrWhiteSpace(SocketType)) return false;
if (!socketable) return false;
var stringFilter = socketable as HVRStringSocketable;
if (stringFilter == null) return false;
if (string.IsNullOrWhiteSpace(stringFilter.SocketType)) return false;
return SocketType.ToLowerInvariant().Equals(stringFilter.SocketType.ToLowerInvariant());
if (!Hash.HasValue || !socketable)
return false;
var stringSocketable = socketable as HVRStringSocketable;
if (!stringSocketable || !stringSocketable.Hash.HasValue)
return false;
return Hash.Value == stringSocketable.Hash.Value;
}
}
}
@@ -1,7 +1,27 @@
namespace HurricaneVR.Framework.Core.Sockets
using UnityEngine;
namespace HurricaneVR.Framework.Core.Sockets
{
public class HVRStringSocketable : HVRSocketable
{
[Tooltip("Lower cased and trimmed prior to hashing.")]
public string SocketType;
public int? Hash { get; private set; }
protected override void Awake()
{
base.Awake();
ResetHash();
}
public void ResetHash()
{
if (!string.IsNullOrWhiteSpace(SocketType))
{
SocketType = SocketType.Trim();
Hash = Animator.StringToHash(SocketType.ToLowerInvariant());
}
}
}
}
@@ -7,10 +7,10 @@ namespace HurricaneVR.Framework.Core.Sockets
{
public HVRSocketableTag Tags;
[Tooltip("If true, the socketable is valid as long as a there is a single match, otherwise all selected tags must be assigned on the socketable.")]
public bool Any = true;
public void Reset()
{
if (Tags == null)
@@ -31,12 +31,12 @@ namespace HurricaneVR.Framework.Core.Sockets
{
var tagSocketable = socketable as HVRTagSocketable;
if (tagSocketable == null || tagSocketable.Tags == null)
if (!tagSocketable || tagSocketable.Tags == null)
return false;
var socketableTags = tagSocketable.Tags;
if (socketableTags.Tags != Tags.Tags)
if (!socketableTags.Tags.MatchesTags(Tags.Tags))
return false;
var anyHit = false;
@@ -1,9 +1,11 @@
using HurricaneVR.Framework.Shared;
using UnityEngine;
namespace HurricaneVR.Framework.Core.Sockets
{
public class HVRTagSocketable : HVRSocketable
{
[Header("Socketable Tags")]
public HVRSocketableTag Tags;
@@ -18,9 +20,8 @@ namespace HurricaneVR.Framework.Core.Sockets
UnityEditor.EditorUtility.SetDirty(this);
#endif
Tags.Tags = HVRSettings.Instance.DefaultSocketableTags;
}
Tags.Tags = HVRSettings.Instance.DefaultSocketableTags;
}
}
}
@@ -15,45 +15,28 @@ namespace HurricaneVR.Framework.Core.UI
public Camera Camera { get; private set; }
public LineRenderer Pointer { get; private set; }
public float offsetPointerHit;
public GameObject PointerHit;
public PointerEventData PointerEventData { get; internal set; }
public HVRController Controller => HVRInputManager.Instance.GetController(HandSide);
public GameObject CurrentUIElement;// { get; internal set; }
private void Start()
protected virtual void Start()
{
Camera = GetComponent<Camera>();
Pointer = GetComponent<LineRenderer>();
}
private void Update()
protected virtual void Update()
{
Pointer.enabled = CurrentUIElement;
if (Pointer.enabled)
{
Pointer.SetPosition(0, transform.position);
Pointer.SetPosition(1, PointerEventData.pointerCurrentRaycast.worldPosition);
if(PointerHit)
{
var forward = PointerEventData.pointerCurrentRaycast.worldNormal;
forward *= offsetPointerHit;
PointerHit.transform.position = PointerEventData.pointerCurrentRaycast.worldPosition + forward;
PointerHit.transform.rotation = PointerEventData.pointerCurrentRaycast.gameObject.transform.rotation;
Debug.DrawRay(PointerHit.transform.position, PointerEventData.pointerCurrentRaycast.worldNormal, Color.red);
Debug.DrawRay(PointerHit.transform.position, CurrentUIElement.transform.forward, Color.yellow);
}
}
if(PointerHit)
{
PointerHit.SetActive(Pointer.enabled);
}
}
internal void Process()
public virtual void Process()
{
PointerEventData.Reset();
PointerEventData.position = new Vector2(Camera.pixelWidth / 2, Camera.pixelHeight / 2);
@@ -40,11 +40,6 @@ namespace HurricaneVR.Framework.Core.Utils
}
}
void Update()
{
}
private void OnCollisionEnter(Collision other)
{
//Debug.Log($"Impulse: {other.impulse}. Velocity: {other.relativeVelocity}");
@@ -0,0 +1,10 @@
using System;
using UnityEngine;
namespace HurricaneVR.Framework.Core.Utils
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EmbeddedAttribute : PropertyAttribute
{
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 39fe36781abf42198e0f3c98afb72795
timeCreated: 1666155343
@@ -84,6 +84,19 @@ namespace HurricaneVR.Framework.Core.Utils
yield return new WaitForSeconds(timeout);
transform.SetLayerRecursive(layer);
}
/// <summary>
/// Locates a component by checking the collider first, then the collider's rigidbody, then finally uses GetComponentInParent.
/// </summary>
public static T FindComponent<T>(this Collider collider, bool tryParent = true) where T : Component
{
if (collider.TryGetComponent(out T c) || collider.attachedRigidbody && collider.attachedRigidbody.TryGetComponent(out c))
{
return c;
}
return tryParent ? collider.GetComponentInParent<T>() : default(T);
}
}
}
@@ -48,6 +48,24 @@ namespace HurricaneVR.Framework.Core.Utils
joint.highAngularXLimit = ll;
}
public static void SetAngularYLimit(this ConfigurableJoint joint, float limit, float bounciness = 0f, float contactDistance = 0f)
{
joint.angularYLimit = new SoftJointLimit() { bounciness = bounciness, contactDistance = contactDistance, limit = limit };
}
public static void SetAngularZLimit(this ConfigurableJoint joint, float limit, float bounciness = 0f, float contactDistance = 0f)
{
joint.angularZLimit = new SoftJointLimit() { bounciness = bounciness, contactDistance = contactDistance, limit = limit };
}
public static void SetAngularLimits(this ConfigurableJoint joint, float xLow, float xHigh, float y, float z)
{
joint.SetAngularXLowLimit(xLow);
joint.SetAngularXHighLimit(xHigh);
joint.SetAngularYLimit(y);
joint.SetAngularZLimit(z);
}
public static void LimitXMotion(this ConfigurableJoint joint)
{
joint.xMotion = ConfigurableJointMotion.Limited;
@@ -63,6 +81,18 @@ namespace HurricaneVR.Framework.Core.Utils
joint.zMotion = ConfigurableJointMotion.Limited;
}
public static void FreeLinearMotion(this ConfigurableJoint joint)
{
joint.xMotion = joint.yMotion = joint.zMotion = ConfigurableJointMotion.Free;
}
public static void LimitLinearMotion(this ConfigurableJoint joint)
{
joint.LimitXMotion();
joint.LimitYMotion();
joint.LimitZMotion();
}
public static void LockLinearMotion(this ConfigurableJoint joint)
{
joint.LockXMotion();
@@ -70,6 +100,13 @@ namespace HurricaneVR.Framework.Core.Utils
joint.LockZMotion();
}
public static void LimitAngularMotion(this ConfigurableJoint joint)
{
joint.LimitAngularXMotion();
joint.LimitAngularYMotion();
joint.LimitAngularZMotion();
}
public static void LimitAngularXMotion(this ConfigurableJoint joint)
{
joint.angularXMotion = ConfigurableJointMotion.Limited;
@@ -3,23 +3,33 @@ using UnityEngine;
namespace HurricaneVR.Framework.Core.Utils
{
/// <summary>
/// Specialized shoulder inventory collector that will check the hand's velocity to prevent grabbing when we feel like the player is throwing something
/// </summary>
public class HVRShoulderGrabber : HVRSocketContainerGrabber
{
public float VelocityCutoff = 2f;
public override bool CanHover(HVRGrabbable grabbable)
{
if (!base.CanHover(grabbable))
return false;
var handGrabber = grabbable.PrimaryGrabber as HVRHandGrabber;
if (handGrabber == null)
if (!handGrabber)
return false;
//if a forward throw is happening don't grab it
var velocity = handGrabber.ComputeThrowVelocity(grabbable, out var dummy);
var velocity = handGrabber.ComputeThrowVelocity(grabbable, out var dummy, true);
velocity.y = transform.position.y;
if (Vector3.Dot(velocity.normalized, transform.forward) > 0f)
var dot = Vector3.Dot(transform.forward, velocity);
if (dot > VelocityCutoff)
{
return false;
}
return true;
}
}
@@ -5,20 +5,25 @@ namespace HurricaneVR.Framework.Core.Utils
{
public class HVRShoulderSocket : HVRSocket
{
public float VelocityCutoff = 2f;
public override bool CanHover(HVRGrabbable grabbable)
{
if (!base.CanHover(grabbable))
return false;
var handGrabber = grabbable.PrimaryGrabber as HVRHandGrabber;
if (handGrabber == null)
if (!handGrabber)
return false;
//if a forward throw is happening don't grab it
var velocity = handGrabber.ComputeThrowVelocity(grabbable, out var dummy);
var velocity = handGrabber.ComputeThrowVelocity(grabbable, out var dummy, true);
velocity.y = transform.position.y;
if (Vector3.Dot(velocity.normalized, transform.forward) > 0f)
var dot = Vector3.Dot(transform.forward, velocity);
if (dot > VelocityCutoff)
{
return false;
}
return true;
}
@@ -228,14 +228,17 @@ namespace HurricaneVR.Framework.Core.Utils
var elapsed = 0f;
while (elapsed < TimeToSlow)
{
elapsed += Time.unscaledDeltaTime;
Time.timeScale = Mathf.Lerp(1f, scale, elapsed / TimeToSlow);
Time.fixedDeltaTime = 1f / RefreshRate * Time.timeScale;
if (SmoothFixedTimeStep)
ResetBuffer();
yield return null;
elapsed += Time.unscaledDeltaTime;
}
Time.timeScale = scale;
Time.fixedDeltaTime = 1f / RefreshRate * Time.timeScale;
_slowRoutine = null;
}
@@ -245,14 +248,16 @@ namespace HurricaneVR.Framework.Core.Utils
var start = Time.timeScale;
while (elapsed < TimeToSlow)
{
elapsed += Time.unscaledDeltaTime;
Time.timeScale = Mathf.Lerp(start, 1f, elapsed / TimeToResume);
Time.fixedDeltaTime = 1f / RefreshRate * Time.timeScale;
if (SmoothFixedTimeStep)
ResetBuffer();
yield return null;
elapsed += Time.unscaledDeltaTime;
}
Time.timeScale = 1f;
Time.fixedDeltaTime = 1f / RefreshRate;
_resetRoutine = null;
}
}
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using HurricaneVR.Framework.Shared;
using UnityEngine;
using Random = UnityEngine.Random;
namespace HurricaneVR.Framework.Core.Utils
{
@@ -142,11 +144,16 @@ namespace HurricaneVR.Framework.Core.Utils
public static Bounds GetColliderBounds(this Collider[] colliders)
{
var bounds = new Bounds();
var first = true;
for (var i = 0; i < colliders.Length; i++)
{
var collider = colliders[i];
if (i == 0)
if (!collider.enabled) continue;
if (first)
{
first = false;
bounds = collider.bounds;
}
else
@@ -256,11 +263,12 @@ namespace HurricaneVR.Framework.Core.Utils
public static T EnsureComponent<T>(this GameObject obj) where T : UnityEngine.Component
{
var temp = obj.GetComponent<T>();
if (temp)
return temp;
if (!obj.TryGetComponent(out T component))
{
component = obj.AddComponent<T>();
}
return obj.AddComponent<T>();
return component;
}
public static T EnsureComponent<T>(this Transform t) where T : UnityEngine.Component
@@ -338,7 +346,7 @@ namespace HurricaneVR.Framework.Core.Utils
/// <summary>
/// return the position and rotation of target relative to relativeTo
/// </summary>
public static void GetRelativeValues(this Transform relativeTo, Transform target, out Vector3 pos, out Quaternion rot)
public static void GetRelativesTo(this Transform target, Transform relativeTo, out Vector3 pos, out Quaternion rot)
{
pos = relativeTo.InverseTransformPoint(target.position);
rot = Quaternion.Inverse(relativeTo.rotation) * target.rotation;
@@ -347,20 +355,20 @@ namespace HurricaneVR.Framework.Core.Utils
/// <summary>
/// return the position and rotation of target relative to relativeTo
/// </summary>
public static void GetRelativeValues(this Component relativeTo, Transform target, out Vector3 pos, out Quaternion rot)
public static void GetRelativesTo(this Component target, Transform relativeTo, out Vector3 pos, out Quaternion rot)
{
pos = Vector3.zero;
rot = Quaternion.identity;
if (!relativeTo || !target) return;
pos = relativeTo.transform.InverseTransformPoint(target.position);
pos = relativeTo.transform.InverseTransformPoint(target.transform.position);
rot = Quaternion.Inverse(relativeTo.transform.rotation) * target.transform.rotation;
}
/// <summary>
/// return the position and rotation of target relative to relativeTo
/// </summary>
public static void GetRelativeValues(this Component relativeTo, Component target, out Vector3 pos, out Quaternion rot)
public static void GetRelativesTo(this Component target, Component relativeTo, out Vector3 pos, out Quaternion rot)
{
pos = Vector3.zero;
rot = Quaternion.identity;
@@ -398,5 +406,12 @@ namespace HurricaneVR.Framework.Core.Utils
{
return float.IsNaN(v.x) || float.IsNaN(v.y) || float.IsNaN(v.z) || float.IsInfinity(v.x) || float.IsInfinity(v.y) || float.IsInfinity(v.z);
}
public static List<string> SplitClean(this string s, char separator)
{
return s.Split(new[] {separator}, StringSplitOptions.RemoveEmptyEntries).Select(e => e.Trim()).Where(e => !e.IsNullOrWhiteSpace()).ToList();
}
public static bool IsNullOrWhiteSpace(this string s) => string.IsNullOrWhiteSpace(s);
}
}
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using FMODUnity;
using UnityEngine;
using Random = UnityEngine.Random;
@@ -15,7 +14,21 @@ namespace HurricaneVR.Framework.Core.Utils
static SFXPlayer s_Instance;
public static SFXPlayer Instance => s_Instance;
static int id;
public AudioSource SFXReferenceSource;
public int SFXSourceCount;
[Tooltip("Changes object name to the clip. This will create garbage.")]
public bool SetClipName;
Dictionary<Guid, PlayEvent> m_PlayEvents = new Dictionary<Guid, PlayEvent>();
List<int> m_PlayingSources = new List<int>();
AudioSource[] m_SFXSourcePool;
int m_UsedSource = 0;
private List<Guid> IDToRemove = new List<Guid>();
void Awake()
{
if (s_Instance != null)
@@ -25,26 +38,103 @@ namespace HurricaneVR.Framework.Core.Utils
}
s_Instance = this;
m_SFXSourcePool = new AudioSource[SFXSourceCount];
for (int i = 0; i < SFXSourceCount; ++i)
{
m_SFXSourcePool[i] = Instantiate(SFXReferenceSource, transform);
m_SFXSourcePool[i].gameObject.SetActive(false);
}
}
void Update()
{
foreach (var playEvent in m_PlayEvents)
{
playEvent.Value.Time -= Time.deltaTime;
if (playEvent.Value.Time <= 0.0f)
IDToRemove.Add(playEvent.Key);
}
foreach (var id in IDToRemove)
{
m_PlayEvents.Remove(id);
}
for (int i = 0; i < m_PlayingSources.Count; ++i)
{
int id = m_PlayingSources[i];
if (!m_SFXSourcePool[id].isPlaying)
{
m_SFXSourcePool[id].gameObject.SetActive(false);
m_PlayingSources.RemoveAt(i);
i--;
}
}
IDToRemove.Clear();
}
public AudioSource GetNewSource()
{
return Instantiate(SFXReferenceSource);
}
public void PlaySFXRandomPitch(AudioClip clip, Vector3 position, float min, float max)
{
PlaySFX(clip, position, Random.Range(min, max), 1f);
}
public void PlaySFXCooldown(AudioClip clip, Vector3 position, Guid sourceId, float pitch = 1f, float volume = 1f, float cooldownTime = 0.5f)
{
if (clip == null)
return;
//can't play this sound again as the previous one with the same source was too early
if (m_PlayEvents.ContainsKey(sourceId))
return;
PlaySFX(clip, position, pitch, volume);
m_PlayEvents.Add(sourceId, new PlayEvent() { Time = cooldownTime });
}
public void PlaySFX(AudioClip clip, Vector3 position)
{
PlaySFX(clip, position, 1f, 1f);
}
public void PlaySFX(AudioClip clip, Vector3 position, float pitch, float volume)
{
if (clip == null)
return;
}
var audioSource = m_SFXSourcePool[m_UsedSource];
public void PlaySFX(EventReference refClip, Vector3 position)
{
RuntimeManager.PlayOneShot(refClip.Guid, position);
if (!audioSource)
return;
m_PlayingSources.Add(m_UsedSource);
m_UsedSource = m_UsedSource + 1;
if (m_UsedSource >= m_SFXSourcePool.Length) m_UsedSource = 0;
if (SetClipName && Application.isEditor)
{
audioSource.name = clip.name;
}
audioSource.gameObject.SetActive(true);
audioSource.transform.position = position;
audioSource.clip = clip;
audioSource.volume = volume;
audioSource.pitch = pitch;
audioSource.Play();
}
}
}
}
@@ -1,6 +1,5 @@
{
"name": "HurricaneVR.Framework",
"rootNamespace": "Zero",
"references": [
"Hurricane.Shared",
"UnityEngine.SpatialTracking",
@@ -10,8 +9,7 @@
"Unity.XR.OpenVR",
"Unity.XR.OpenXR",
"Oculus.VR",
"SteamVR_Actions",
"FMODUnity"
"SteamVR_Actions"
],
"includePlatforms": [],
"excludePlatforms": [],
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using HurricaneVR.Framework.ControllerInput;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Shared.Utilities;
using UnityEngine;
@@ -199,7 +200,8 @@ namespace HurricaneVR.Framework.Shared
SecondaryTouchButtonState.Active,
TrackPadTouchState.Active,
JoystickTouchState.Active,
Knuckles);
Knuckles,
HVRInputManager.Instance.IsOpenXR);
}
}
@@ -497,6 +499,7 @@ namespace HurricaneVR.Framework.Shared
Vive,
Knuckles,
Cosmos,
ReverbG2
ReverbG2,
Pico
}
}
@@ -1,4 +1,5 @@
using System;
using HurricaneVR.Framework.ControllerInput;
using UnityEngine;
namespace HurricaneVR.Framework.Shared
@@ -59,7 +60,7 @@ namespace HurricaneVR.Framework.Shared
public float PinkyTotal => JoystickTouchWeight.Pinky + TrackpadTouchWeight.Pinky + PrimaryTouchWeight.Pinky + SecondaryTouchWeight.Pinky +
TriggerTouchWeight.Pinky + GripWeight.Pinky + TriggerWeight.Pinky;
public void Evaluate(float[] curls, float grip, float trigger, bool triggerTouch, bool primaryTouch, bool secondaryTouch, bool trackpadTouch, bool joystickTouch, bool knuckles)
public void Evaluate(float[] curls, float grip, float trigger, bool triggerTouch, bool primaryTouch, bool secondaryTouch, bool trackpadTouch, bool joystickTouch, bool knuckles, bool isOpenXR)
{
var joystick = joystickTouch ? 1f : 0f;
var trackPad = trackpadTouch ? 1f : 0f;
@@ -83,7 +84,8 @@ namespace HurricaneVR.Framework.Shared
GripWeight.Index * grip +
TriggerWeight.Index * trigger;
if (!knuckles || KnucklesOverrideGripFingers)
//until openxr has index finger curls supplied (if ever..)
if (!knuckles || (KnucklesOverrideGripFingers || isOpenXR))
{
curls[2] = JoystickTouchWeight.Middle * joystick +
TrackpadTouchWeight.Middle * trackPad +
@@ -22,13 +22,14 @@ namespace HurricaneVR.Framework.Weapons.Bow
}
}
private void OnStringGrabbed(HVRHandGrabber arg0, HVRGrabbable arg1)
private void OnStringGrabbed(HVRHandGrabber hand, HVRGrabbable arg1)
{
if (!bow.ArrowNocked && ArrowPrefab)
{
var go = Instantiate(ArrowPrefab);
var arrow = go.GetComponent<HVRArrow>();
bow.NockArrow(arrow);
hand.DisableHandCollision(arrow.Grabbable);
}
}
}
@@ -15,11 +15,13 @@ namespace HurricaneVR.Framework.Weapons.Bow
{
[Header("Bow String")]
public HVRGrabbable NockGrabbable;
public float StringLimit = .5f;
public float StringDropLimit = .6f;
[Header("Settings")]
public HVRBowLimitStyle StringLimitStyle = HVRBowLimitStyle.Limit;
public float ShootThreshold = .2f;
public float Speed = 50f;
public AnimationCurve SpeedCurve;
@@ -27,7 +29,6 @@ namespace HurricaneVR.Framework.Weapons.Bow
[Header("Transforms")]
[Tooltip("Arrow Rest When the bow is held with the left hand.")]
public Transform LeftRest;
@@ -39,6 +40,7 @@ namespace HurricaneVR.Framework.Weapons.Bow
[Header("Haptics")]
public bool StringHaptics = true;
public bool BowHandHaptics = true;
[Tooltip("Number of haptic ticks by percent traveled.")]
@@ -61,6 +63,7 @@ namespace HurricaneVR.Framework.Weapons.Bow
[Header("SFX")]
public AudioClip StringClip;
public float StringMinPitch = 1f;
public float StringMaxPitch = 1.25f;
@@ -137,8 +140,6 @@ namespace HurricaneVR.Framework.Weapons.Bow
}
}
private void Update()
{
@@ -147,7 +148,6 @@ namespace HurricaneVR.Framework.Weapons.Bow
protected virtual void UpdateBow()
{
}
private void FixedUpdate()
@@ -159,12 +159,10 @@ namespace HurricaneVR.Framework.Weapons.Bow
protected virtual void BeforeFixedUpdateBow()
{
}
protected virtual void AfterFixedUpdateBow()
{
}
protected virtual void FixedUpdateBow()
@@ -272,22 +270,20 @@ namespace HurricaneVR.Framework.Weapons.Bow
protected virtual void PlayStringSFX(float nockDistance)
{
var pitch = nockDistance.Remap(0, StringLimit, StringMinPitch, StringMaxPitch);
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(StringClip, NockGrabbable.transform.position, pitch, 1f);
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(StringClip, NockGrabbable.transform.position, pitch, 1f);
}
protected virtual void PlayReleasedSFX()
{
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(ReleasedSFX.GetRandom(), NockGrabbable.transform.position);
if (SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(ReleasedSFX.GetRandom(), NockGrabbable.transform.position);
}
protected virtual void OnGrabbed(HVRGrabberBase arg0, HVRGrabbable arg1)
{
}
protected virtual void OnReleased(HVRGrabberBase arg0, HVRGrabbable arg1)
{
}
private void BeforeNockHovered(HVRGrabberBase grabber, HVRGrabbable grabbable)
@@ -318,7 +314,7 @@ namespace HurricaneVR.Framework.Weapons.Bow
var grabbable = arrow.Grabbable;
grabbable.ForceRelease();
//grabbable.ForceRelease();
grabbable.CanBeGrabbed = false;
grabbable.Rigidbody.sleepThreshold = 0f;
grabbable.Grabbed.AddListener(OnNockedArrowGrabbed);
@@ -332,6 +328,7 @@ namespace HurricaneVR.Framework.Weapons.Bow
if (NockHand)
{
NockHand.DisableHandCollision(Arrow.Grabbable);
NockHand.TryGrab(NockGrabbable, true);
NockHand = null;
}
@@ -369,17 +366,16 @@ namespace HurricaneVR.Framework.Weapons.Bow
{
StartCoroutine(EnableBowHandCollisionRoutine(arg0, Arrow.Grabbable));
}
BowHand = null;
}
protected virtual void OnStringReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
{
}
protected virtual void OnStringGrabbed(HVRHandGrabber hand, HVRGrabbable nock)
{
}
protected virtual void OnBowSocketed(HVRSocket arg0, HVRGrabbable arg1)
@@ -392,7 +388,6 @@ namespace HurricaneVR.Framework.Weapons.Bow
protected virtual void OnBowUnsocketed(HVRSocket arg0, HVRGrabbable arg1)
{
}
protected virtual void OnArrowDropped()
@@ -403,7 +398,6 @@ namespace HurricaneVR.Framework.Weapons.Bow
Arrow.Grabbable.CanBeGrabbed = true;
Arrow = null;
}
protected virtual void OnArrowRemoved(HVRArrow arrow)
@@ -429,10 +423,11 @@ namespace HurricaneVR.Framework.Weapons.Bow
{
if (!hand || !arrow)
yield break;
yield return new WaitForSeconds(.25f);
yield return new WaitForSeconds(1f);
if (BowHand && BowHand == hand || !arrow)
yield break;
UpdateBowHandCollision(hand, arrow, true);
Grabbable.IgnoreCollision(arrow, false);
}
public void OnDrawGizmosSelected()
@@ -457,6 +452,5 @@ namespace HurricaneVR.Framework.Weapons.Bow
public class HVRBowEvent : UnityEvent<HVRPhysicsBow>
{
}
}
@@ -1,4 +1,5 @@
using HurricaneVR.Framework.Core.Grabbers;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Grabbers;
using UnityEngine;
namespace HurricaneVR.Framework.Weapons.Bow
@@ -18,10 +19,21 @@ namespace HurricaneVR.Framework.Weapons.Bow
protected override void OnGrabbed(HVRGrabArgs args)
{
Debug.Log($"nocked");
//Debug.Log($"nocked");
args.Cancel = true;
Grabbed.Invoke(this, args.Grabbable);
ForceRelease();
//ForceRelease();
}
protected override void OnReleased(HVRGrabbable grabbable)
{
}
protected override void OnHoverEnter(HVRGrabbable grabbable)
{
if (grabbable.LeftHandGrabber) grabbable.LeftHandGrabber.IgnoreNextCollisionCheck = true;
if (grabbable.RightHandGrabber) grabbable.RightHandGrabber.IgnoreNextCollisionCheck = true;
base.OnHoverEnter(grabbable);
}
}
}
@@ -62,6 +62,10 @@ namespace HurricaneVR.Framework.Weapons.Guns
private Transform _grabbedPositionTracker;
/// <summary>
/// The offset of the cocking handle when it's grabbed
/// </summary>
protected float GrabOffset { get; set; }
public bool EmptyOpen { get; protected set; }
@@ -160,27 +164,27 @@ namespace HurricaneVR.Framework.Weapons.Guns
return;
}
var pullDirection = (Grabbable.HandGrabbers[0].TrackedController.position - _grabbedPositionTracker.transform.position);
var pullDirection = (Grabbable.HandGrabbers[0].TrackedController.position - _grabbedPositionTracker.position);
var backDirection = (MaxPositionWorld - ForwardPositionWorld).normalized * 10;
var amount = Vector3.Dot(pullDirection, backDirection);
var amount = Vector3.Dot(pullDirection, backDirection) * Difficulty;
if (amount > 0)
if (amount + GrabOffset > 0)
{
UpdatePosition(amount);
var distance = Vector3.Distance(transform.position, ForwardPositionWorld);
CheckEject(distance);
CheckChamberDistance(distance);
ClampPullBack(distance, BackDirectionWorld);
MoveBolt();
AnimateParts();
CheckLock(distance);
}
else
{
transform.localPosition = ForwardPosition;
}
var distance = Vector3.Distance(transform.position, ForwardPositionWorld);
CheckEject(distance);
CheckChamberDistance(distance);
ClampPullBack(distance, BackDirectionWorld);
MoveBolt();
AnimateParts();
CheckLock(distance);
}
}
@@ -202,8 +206,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
private void UpdatePosition(float amount)
{
transform.position = ForwardPositionWorld + BackDirectionWorld * (amount * Difficulty);
transform.position = ForwardPositionWorld + BackDirectionWorld * (amount + GrabOffset);
}
@@ -337,6 +340,8 @@ namespace HurricaneVR.Framework.Weapons.Guns
protected virtual void OnGrabbed(HVRHandGrabber grabber, HVRGrabbable slide)
{
GrabOffset = 0f;
if (ImmediateReleaseWhenOpen && EmptyOpen && LocksBack)
{
if (Bolt)
@@ -350,14 +355,17 @@ namespace HurricaneVR.Framework.Weapons.Guns
_previousVelocity = Vector3.zero;
if (Type == HVRCockingHandleType.Pump)
{
_grabbedPositionTracker.transform.position = grabber.GrabPoint.position;
_grabbedPositionTracker.position = grabber.GrabPoint.position;
}
else
{
_grabbedPositionTracker.transform.localPosition = transform.parent.InverseTransformPoint(_previousHandPosition);
_grabbedPositionTracker.localPosition = transform.parent.InverseTransformPoint(_previousHandPosition);
GrabOffset = Vector3.Distance(ForwardPositionWorld, transform.position);
}
}
protected virtual void OnReleased(HVRHandGrabber grabber, HVRGrabbable slide)
{
EmptyOpen = false;
@@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using HurricaneVR.Framework.Components;
@@ -36,7 +37,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
[Tooltip("Is chambering required to shoot")]
public bool RequiresChamberedBullet = true;
public FireType FireType = FireType.Single;
public GunFireType FireType = GunFireType.Single;
[Tooltip("Speed of the bullet prefab")]
public float BulletSpeed = 40f;
@@ -126,7 +127,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
private Coroutine _animationRoutine;
public UnityEvent Fired = new UnityEvent();
public GunHitEvent Hit = new GunHitEvent();
public HVRGunHitEvent Hit = new HVRGunHitEvent();
protected float TimeOfLastShot { get; set; }
@@ -554,7 +555,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
return;
}
if (FireType == FireType.Single)
if (FireType == GunFireType.Single)
{
if (Time.time - TimeOfLastShot < Cooldown)
return;
@@ -565,7 +566,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
return;
}
if (IsFiring && FireType == FireType.ThreeRoundBurst)
if (IsFiring && FireType == GunFireType.ThreeRoundBurst)
return;
IsFiring = true;
@@ -574,7 +575,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
public virtual void TriggerReleased()
{
if (FireType == FireType.Automatic)
if (FireType == GunFireType.Automatic)
{
IsFiring = false;
}
@@ -602,7 +603,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
PlayHaptics(Grabbable, Haptics.DryFire);
}
public virtual void UpdateTrackedBullets()
private void UpdateTrackedBullets()
{
for (int i = 0; i < _objects.Count; i++)
{
@@ -615,7 +616,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
if (Physics.Raycast(bullet.transform.position, tracker.Direction, out var hit, distance, HitLayerMask, QueryTriggerInteraction.Ignore))
{
OnHit(bullet, hit, tracker.Direction);
OnHit(hit, tracker.Direction);
bullet.SetActive(false);
_objects[i].SetRenderersActive(false);
}
@@ -708,7 +709,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
TimeOfLastShot = Time.time;
RoundsFired++;
if (FireType == FireType.ThreeRoundBurst && RoundsFired == 3)
if (FireType == GunFireType.ThreeRoundBurst && RoundsFired == 3)
{
IsFiring = false;
}
@@ -1005,7 +1006,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
}
protected virtual void OnHit(GameObject bullet, RaycastHit hit, Vector3 direction)
protected virtual void OnHit(RaycastHit hit, Vector3 direction)
{
var damageHandler = hit.collider.GetComponent<HVRDamageHandlerBase>();
if (damageHandler)
@@ -1020,7 +1021,7 @@ namespace HurricaneVR.Framework.Weapons.Guns
hit.collider.attachedRigidbody.AddForceAtPosition(direction.normalized * Force, hit.point, ForceMode.Impulse);
}
Hit.Invoke(damageHandler);
Hit.Invoke(new GunHitArgs(this, direction, hit));
}
public virtual void EjectBullet()
@@ -1126,4 +1127,39 @@ namespace HurricaneVR.Framework.Weapons.Guns
}
}
}
[Serializable]
public class HVRGunHitEvent : UnityEvent<GunHitArgs>
{
}
public struct GunHitArgs
{
public HVRGunBase Gun;
public Vector3 HitPoint;
public Vector3 Normal;
public Vector3 Direction;
public Collider Collider;
public Rigidbody Rb;
public float Distance;
public GunHitArgs(HVRGunBase gun, Vector3 direction, RaycastHit hit)
{
Gun = gun;
HitPoint = hit.point;
Normal = hit.normal;
Direction = direction;
Collider = hit.collider;
Rb = hit.collider.attachedRigidbody;
Distance = hit.distance;
}
}
public enum GunFireType
{
Single,
ThreeRoundBurst,
Automatic
}
}
@@ -1,4 +1,6 @@
using UnityEngine;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Grabbers;
using UnityEngine;
namespace HurricaneVR.Framework.Weapons.Guns
{
@@ -32,5 +34,15 @@ namespace HurricaneVR.Framework.Weapons.Guns
EjectCasing();
}
}
protected override void OnAmmoSocketed(HVRGrabberBase grabber, HVRGrabbable grabbable)
{
AmmoSocketedHaptics();
}
protected override void OnAmmoSocketReleased(HVRGrabberBase arg0, HVRGrabbable arg1)
{
}
}
}
@@ -11,14 +11,12 @@ namespace HurricaneVR.Framework.Weapons
public class HVRAmmoReleaseAction : HVRInputAction
{
public HVRRayCastGun HVRRayCastGun { get; private set; }
public HVRGunBase Gun { get; private set; }
protected override void Awake()
{
base.Awake();
HVRRayCastGun = GetComponent<HVRRayCastGun>();
Gun = GetComponent<HVRGunBase>();
}
@@ -41,10 +39,9 @@ namespace HurricaneVR.Framework.Weapons
release = controller.PrimaryButtonState.JustActivated;
}
if (release)
if (release && Gun)
{
HVRRayCastGun?.ReleaseAmmo();
Gun?.ReleaseAmmo();
Gun.ReleaseAmmo();
}
}
}
@@ -1,51 +1,92 @@
using FMODUnity;
using System.Collections.Generic;
using HurricaneVR.Framework.Core.Utils;
using UnityEngine;
using Random = UnityEngine.Random;
namespace HurricaneVR.Framework.Weapons
{
public class HVRGunSounds : MonoBehaviour
{
[SerializeField] private EventReference fired;
[SerializeField] private EventReference outOfAmmo;
[SerializeField] private EventReference slideBack;
[SerializeField] private EventReference slideForward;
[SerializeField] private EventReference loadMagazine;
[SerializeField] private EventReference unloadMagazine;
public AudioClip Fired;
public AudioClip OutOfAmmo;
//public AudioClip AmmoInserted;
//public AudioClip AmmoReleased;
public AudioClip SlideBack;
public AudioClip SlideForward;
public List<AudioClip> FiredVariations = new List<AudioClip>();
//public List<AudioClip> AmmoInsertedVariations = new List<AudioClip>();
//public List<AudioClip> AmmoReleasedVariations = new List<AudioClip>();
public List<AudioClip> SlideBackVariations = new List<AudioClip>();
public List<AudioClip> SlideForwardVariations = new List<AudioClip>();
private void Start()
{
AddVariation(Fired, FiredVariations);
//AddVariation(AmmoInserted, AmmoInsertedVariations);
//AddVariation(AmmoReleased, AmmoReleasedVariations);
AddVariation(SlideBack, SlideBackVariations);
AddVariation(SlideForward, SlideForwardVariations);
}
public virtual void PlayGunFire()
{
PlayClip(fired);
PlayVariation(FiredVariations);
}
//public virtual void PlayAmmoInserted()
//{
// PlayVariation(AmmoInsertedVariations);
//}
//public virtual void PlayAmmoReleased()
//{
// PlayVariation(AmmoReleasedVariations);
//}
public virtual void PlayOutOfAmmo()
{
PlayClip(outOfAmmo);
PlayClip(OutOfAmmo);
}
public virtual void PlaySlideForward()
{
PlayClip(slideForward);
PlayVariation(SlideForwardVariations);
}
public virtual void PlaySlideBack()
{
PlayClip(slideBack);
PlayVariation(SlideBackVariations);
}
public virtual void PlayLoadMagazine()
protected virtual void PlayVariation(List<AudioClip> variations)
{
PlayClip(loadMagazine);
if (variations.Count == 0)
return;
var index = Random.Range(0, variations.Count);
var sfx = variations[index];
PlayClip(sfx);
}
public virtual void PlayUnloadMagazine()
protected virtual void PlayClip(AudioClip clip)
{
PlayClip(unloadMagazine);
if (!clip)
return;
if(SFXPlayer.Instance) SFXPlayer.Instance.PlaySFX(clip, transform.position);
}
protected virtual void PlayClip(EventReference clip)
private void AddVariation(AudioClip clip, List<AudioClip> variations)
{
if (clip.IsNull) return;
RuntimeManager.PlayOneShot(clip.Guid, transform.position);
if (clip && !variations.Contains(clip))
{
variations.Add(clip);
}
}
}
}