Files
ZeroVR/ZeroPacientVR/Assets/HurricaneVR/Framework/Scripts/Components/HVRPhysicsDial.cs
T

160 lines
4.6 KiB
C#

using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Grabbers;
using HurricaneVR.Framework.Core.ScriptableObjects;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared;
using UnityEngine;
using UnityEngine.Serialization;
namespace HurricaneVR.Framework.Components
{
[RequireComponent(typeof(Rigidbody))]
public class HVRPhysicsDial : MonoBehaviour
{
[SerializeField] public HVRGrabbable Grabbable;
[Header("Settings")]
[Tooltip("Local axis of rotation")]
public HVRAxis Axis;
[Tooltip("Rigidbody to connect the joint to")]
public Rigidbody ConnectedBody;
[Tooltip("If true the angular velocity will be zero'd out on release.")]
public bool StopOnRelease = true;
public bool DisableGravity = true;
[Header("Joint Limits")]
public bool LimitRotation;
[Tooltip("Minimum Angle about the axis of rotation")]
public float MinAngle;
[Tooltip("Maximum rotation about the axis of rotation")]
public float MaxAngle;
[Header("Joint Settings")]
[Tooltip("Angular Damper when the dial is grabbed")]
public float GrabbedDamper = 3;
[Tooltip("Angular Damper when the dial is not grabbed")]
public float Damper = 3;
public float Spring;
[Header("Editor")]
[SerializeField]
protected Quaternion JointStartRotation;
[Header("Debugging Tools")]
public float TargetAngularVelocity = 0f;
public Rigidbody Rigidbody { get; private set; }
public ConfigurableJoint Joint { get; set; }
protected virtual void Awake()
{
Rigidbody = this.GetRigidbody();
Rigidbody.useGravity = !DisableGravity;
if (!Grabbable) 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);
SetupJoint();
AfterJointCreated(Joint);
}
protected virtual void Start()
{
}
protected virtual void Update()
{
if (TargetAngularVelocity > 0f || TargetAngularVelocity < 0f) Joint.targetAngularVelocity = new Vector3(TargetAngularVelocity, 0f, 0f);
}
private void OnDialReleased(HVRHandGrabber arg0, HVRGrabbable arg1)
{
Joint.SetAngularXDrive(Spring, Damper, 10000f);
if (StopOnRelease)
{
Rigidbody.angularVelocity = Vector3.zero;
}
}
private void OnDialGrabbed(HVRHandGrabber arg0, HVRGrabbable arg1)
{
Joint.SetAngularXDrive(0f, GrabbedDamper, 10000f);
}
protected virtual void SetupJoint()
{
var currentRotation = transform.localRotation;
transform.localRotation = JointStartRotation;
Joint = gameObject.AddComponent<ConfigurableJoint>();
Joint.connectedBody = ConnectedBody;
Joint.LockLinearMotion();
Joint.LockAngularYMotion();
Joint.LockAngularZMotion();
Joint.anchor = Vector3.zero;
Joint.axis = Axis.GetVector();
if (LimitRotation)
{
ResetLimits();
}
else
{
Joint.angularXMotion = ConfigurableJointMotion.Free;
}
Joint.secondaryAxis = Joint.axis.OrthogonalVector();
Joint.SetAngularXDrive(Spring, Damper, 10000f);
Joint.projectionAngle = 1f;
Joint.projectionDistance = .01f;
Joint.projectionMode = JointProjectionMode.PositionAndRotation;
transform.localRotation = currentRotation;
}
protected virtual void AfterJointCreated(ConfigurableJoint joint)
{
}
public void SetLimits(float minAngle, float maxAngle)
{
Joint.LimitAngularXMotion();
Joint.SetAngularXHighLimit(minAngle);
Joint.SetAngularXLowLimit(maxAngle);
}
public void ResetLimits()
{
Joint.LimitAngularXMotion();
Joint.SetAngularXHighLimit(-MinAngle);
Joint.SetAngularXLowLimit(-MaxAngle);
}
}
}