using System; using System.Collections.Generic; using UnityEngine; [RequireComponent(typeof(Rigidbody))] [RequireComponent(typeof(VelocityTracker))] public class VRGrabber : MonoBehaviour { public void ForceRelease(VRGrabbable grabbable) { bool flag = this.m_grabbedObj != null && this.m_grabbedObj == grabbable; if (flag) { this.GrabEnd(); } } public void SetGripTransform(string name) { for (int i = 0; i < this.gripTransforms.Length; i++) { if (this.gripTransforms[i].name == name) { this.gripTransform = this.gripTransforms[i].transform; break; } } } private void Awake() { this.m_anchorOffsetPosition = base.transform.localPosition; this.m_anchorOffsetRotation = base.transform.localRotation; if (this.gripTransform == null) { this.gripTransform = this.gripTransforms[0].transform; } } private void Start() { this.m_velocityTracker = base.GetComponent(); this.m_lastPos = base.transform.position; this.m_lastRot = base.transform.rotation; this.m_parentTransform = base.gameObject.transform.parent.transform; } private void Update() { if (this.m_vrController == null) { return; } if (this.m_vrController.GetPressDown(AVRControllerButtons.BTN.TRIGGER)) { this.GrabBegin(); } else if (this.m_vrController.GetPressUp(AVRControllerButtons.BTN.TRIGGER)) { this.GrabEnd(); } } private void FixedUpdate() { if (this.m_vrController == null) { return; } Vector3 position = this.m_vrController.transform.position; Quaternion rotation = this.m_vrController.transform.rotation; Vector3 vector = this.m_parentTransform.TransformPoint(this.m_anchorOffsetPosition + position); Quaternion rot = this.m_parentTransform.rotation * rotation; base.GetComponent().MovePosition(vector); base.GetComponent().MoveRotation(rot); if (!this.m_useFixedJointForGrabbedObject && !this.m_parentHeldObject) { this.MoveGrabbedObject(vector, rot, false); } this.m_lastPos = base.transform.position; this.m_lastRot = base.transform.rotation; } private void OnDestroy() { if (this.m_grabbedObj != null) { this.GrabEnd(); } } private void OnTriggerEnter(Collider otherCollider) { VRGrabbable vrgrabbable = otherCollider.GetComponent() ?? otherCollider.GetComponentInParent(); if (vrgrabbable == null) { return; } int num = 0; this.m_grabCandidates.TryGetValue(vrgrabbable, out num); this.m_grabCandidates[vrgrabbable] = num + 1; } private void OnTriggerExit(Collider otherCollider) { VRGrabbable vrgrabbable = otherCollider.GetComponent() ?? otherCollider.GetComponentInParent(); if (vrgrabbable == null) { return; } int num = 0; if (!this.m_grabCandidates.TryGetValue(vrgrabbable, out num)) { return; } if (num > 1) { this.m_grabCandidates[vrgrabbable] = num - 1; } else { this.m_grabCandidates.Remove(vrgrabbable); } } private void CheckForGrabOrRelease(float prevFlex) { if (this.m_prevFlex >= 0.55f && prevFlex < 0.55f) { this.GrabBegin(); } else if (this.m_prevFlex <= 0.35f && prevFlex > 0.35f) { this.GrabEnd(); } } public void GrabBegin(VRGrabbable grabbable) { if (grabbable == null || this.m_grabbedObj != null || grabbable.GrabPoints == null || grabbable.GrabPoints.Length <= 0) { return; } this.OnTriggerEnter(grabbable.GrabPoints[0]); this.GrabVolumeEnable(true); this.GrabBegin(); } private void GrabBegin() { float num = float.MaxValue; VRGrabbable vrgrabbable = null; Collider grabPoint = null; foreach (VRGrabbable vrgrabbable2 in this.m_grabCandidates.Keys) { if (!vrgrabbable2.IsGrabbed || vrgrabbable2.AllowOffhandGrab) { for (int i = 0; i < vrgrabbable2.GrabPoints.Length; i++) { Collider collider = vrgrabbable2.GrabPoints[i]; Vector3 b = collider.ClosestPointOnBounds(this.gripTransform.position); float sqrMagnitude = (this.gripTransform.position - b).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; vrgrabbable = vrgrabbable2; grabPoint = collider; } } } } this.GrabVolumeEnable(false); if (vrgrabbable != null) { if (vrgrabbable.IsGrabbed) { vrgrabbable.GrabbedBy.OffhandGrabbed(vrgrabbable); } this.m_grabbedObj = vrgrabbable; this.m_grabbedObj.GrabBegin(this, grabPoint); if (this.m_useFixedJointForGrabbedObject) { FixedJoint fixedJoint = base.gameObject.GetComponent() ?? base.gameObject.AddComponent(); fixedJoint.connectedBody = this.m_grabbedObj.GetComponent(); } else { this.m_lastPos = base.transform.position; this.m_lastRot = base.transform.rotation; if (this.m_grabbedObj.SnapPosition) { this.m_grabbedObjectPosOff = this.gripTransform.localPosition; if (this.m_grabbedObj.SnapOffset) { Vector3 localPosition = this.m_grabbedObj.SnapOffset.localPosition; if (this.m_vrController.HandSide) { localPosition.x = -localPosition.x; } this.m_grabbedObjectPosOff += localPosition; } } else { Vector3 vector = this.m_grabbedObj.transform.position - base.transform.position; vector = Quaternion.Inverse(base.transform.rotation) * vector; this.m_grabbedObjectPosOff = vector; } if (this.m_grabbedObj.SnapOrientation) { this.m_grabbedObjectRotOff = this.gripTransform.localRotation; if (this.m_grabbedObj.SnapOffset) { this.m_grabbedObjectRotOff = this.m_grabbedObj.SnapOffset.rotation * this.m_grabbedObjectRotOff; } } else { Quaternion grabbedObjectRotOff = Quaternion.Inverse(base.transform.rotation) * this.m_grabbedObj.transform.rotation; this.m_grabbedObjectRotOff = grabbedObjectRotOff; } this.MoveGrabbedObject(this.m_lastPos, this.m_lastRot, true); if (this.m_parentHeldObject) { this.m_grabbedObj.transform.parent = base.transform; } } } } private void MoveGrabbedObject(Vector3 pos, Quaternion rot, bool forceTeleport = false) { if (this.m_grabbedObj == null) { return; } if (this.m_grabbedObj.SnapPosition && this.m_frameUpdateSnapPosition) { this.m_grabbedObjectPosOff = this.gripTransform.localPosition; if (this.m_grabbedObj.SnapOffset) { Vector3 localPosition = this.m_grabbedObj.SnapOffset.localPosition; if (this.m_vrController.HandSide) { localPosition.x = -localPosition.x; } this.m_grabbedObjectPosOff += localPosition; } this.m_grabbedObjectRotOff = this.gripTransform.localRotation; if (this.m_grabbedObj.SnapOffset) { this.m_grabbedObjectRotOff = this.m_grabbedObj.SnapOffset.rotation * this.m_grabbedObjectRotOff; } } Rigidbody grabbedRigidbody = this.m_grabbedObj.GrabbedRigidbody; Vector3 position = pos + rot * this.m_grabbedObjectPosOff; Quaternion quaternion = rot * this.m_grabbedObjectRotOff; if (forceTeleport) { grabbedRigidbody.transform.position = position; grabbedRigidbody.transform.rotation = quaternion; } else { grabbedRigidbody.MovePosition(position); grabbedRigidbody.MoveRotation(quaternion); } } public void GrabEnd(Vector3 trackedLinearVelocity, Vector3 TrackedAngularVelocity) { if (this.m_grabbedObj != null) { this.VRGrabbableRelease(trackedLinearVelocity, TrackedAngularVelocity); } this.GrabVolumeEnable(true); } public void GrabEnd() { if (this.m_grabbedObj != null) { bool flag = this.m_velocityTracker.TrackedLinearVelocity.magnitude >= 1f; Vector3 linearVelocity = Vector3.zero; Vector3 angularVelocity = Vector3.zero; if (flag) { linearVelocity = this.m_velocityTracker.TrackedLinearVelocity; angularVelocity = this.m_velocityTracker.TrackedAngularVelocity; } else { linearVelocity = this.m_velocityTracker.FrameLinearVelocity; angularVelocity = this.m_velocityTracker.FrameAngularVelocity; } this.VRGrabbableRelease(linearVelocity, angularVelocity); } this.GrabVolumeEnable(true); } private void VRGrabbableRelease(Vector3 linearVelocity, Vector3 angularVelocity) { Debug.Log(linearVelocity.ToString("G")); Debug.Log(angularVelocity.ToString("G")); UnityEngine.Object.Destroy(base.gameObject.GetComponent()); this.m_grabbedObj.GrabEnd(linearVelocity, angularVelocity); if (this.m_parentHeldObject) { this.m_grabbedObj.transform.parent = null; } this.m_grabbedObj = null; } private void GrabVolumeEnable(bool enabled) { if (this.m_grabVolumeEnabled == enabled) { return; } this.m_grabVolumeEnabled = enabled; for (int i = 0; i < this.m_grabVolumes.Length; i++) { Collider collider = this.m_grabVolumes[i]; collider.enabled = this.m_grabVolumeEnabled; } if (!this.m_grabVolumeEnabled) { this.m_grabCandidates.Clear(); } } private void OffhandGrabbed(VRGrabbable grabbable) { if (this.m_grabbedObj == grabbable) { this.VRGrabbableRelease(Vector3.zero, Vector3.zero); } } public const float THRESH_GRAB_BEGIN = 0.55f; public const float THRESH_GRAB_END = 0.35f; public const float THRESH_THROW_SPEED = 1f; [SerializeField] private bool m_useFixedJointForGrabbedObject; [SerializeField] private bool m_parentHeldObject; [SerializeField] private VRGrabber.GripTransformData[] gripTransforms; [SerializeField] private Collider[] m_grabVolumes; [SerializeField] public AVRControllerButtons m_vrController; [SerializeField] private bool m_frameUpdateSnapPosition; private VelocityTracker m_velocityTracker; private bool m_grabVolumeEnabled = true; private Vector3 m_lastPos; private Quaternion m_lastRot; private Quaternion m_anchorOffsetRotation; private Vector3 m_anchorOffsetPosition; private float m_prevFlex; private Transform m_parentTransform; private VRGrabbable m_grabbedObj; private Vector3 m_grabbedObjectPosOff; private Quaternion m_grabbedObjectRotOff; private Dictionary m_grabCandidates = new Dictionary(); private Transform gripTransform; [Serializable] private struct GripTransformData { public Transform transform; public string name; } }