using System; using UnityEngine; [RequireComponent(typeof(Rigidbody))] [RequireComponent(typeof(VelocityTracker))] public class WfGrabbableObject : VRGrabbable { public Rigidbody rigidBody { get; private set; } public VelocityTracker velocityTrack { get; private set; } protected override void Awake() { base.Awake(); this.rigidBody = base.GetComponent(); this.velocityTrack = base.GetComponent(); } public override void GrabBegin(VRGrabber hand, Collider grabPoint) { base.GrabBegin(hand, grabPoint); } public override void GrabEnd(Vector3 linearVelocity, Vector3 angularVelocity) { float magnitude = linearVelocity.magnitude; if (this.throwForceThreshold <= magnitude) { if (this.onThrowObjectCorrectionVelocityEvent != null) { this.onThrowObjectCorrectionVelocityEvent(ref linearVelocity, ref angularVelocity); } base.GrabEnd(linearVelocity * this.throwForceRate, angularVelocity); if (this.isThrowCorrection) { this.PlayLookRotationAnime(Quaternion.LookRotation(linearVelocity.normalized * -1f)); } } else { base.GrabEnd(linearVelocity * Mathf.Max(1f, magnitude / this.throwForceThreshold * this.throwForceRate), angularVelocity); } if (this.onThrowObjectEvent != null) { this.onThrowObjectEvent(this, this.throwForceThreshold > magnitude); } } public void PlayLookRotationAnime(Quaternion targetRotation) { this.backupRotation = base.transform.rotation; this.targetRotation = targetRotation; this.isRotationAnime = true; this.animeValue = (this.animeValue2 = 0f); this.lastY = 0f; this.rigidBody.freezeRotation = true; } public void StopLookRotationAnime() { this.isRotationAnime = false; this.rigidBody.freezeRotation = false; } public void Update() { if (this.isRotationAnime) { this.animeValue += ((this.trackedLinearCorrectionTime != 0f) ? (1f / this.trackedLinearCorrectionTime * Time.deltaTime) : 1f); Mathf.Clamp(this.animeValue, 0f, 1f); if (1f <= this.animeValue) { Vector3 trackedLinearVelocity = this.velocityTrack.TrackedLinearVelocity; float num = Vector3.Dot(Vector3.down, trackedLinearVelocity); if (0f < num) { if (this.animeValue2 == 0f) { this.backupRotation = base.transform.rotation; } this.animeValue2 += ((this.fallDownCorrectionTime != 0f) ? (1f / this.fallDownCorrectionTime * Time.deltaTime) : 1f); Mathf.Clamp(this.animeValue2, 0f, 1f); Vector3 forward = (trackedLinearVelocity.normalized * -1f + new Vector3(0f, -0.65f, 0f)).normalized; float y = (forward.y >= this.lastY) ? forward.y : this.lastY; forward = new Vector3(forward.x, y, forward.z); base.transform.rotation = Quaternion.Lerp(this.backupRotation, Quaternion.LookRotation(forward), this.animeValue2); } else { Vector3 forward = trackedLinearVelocity.normalized * -1f; this.lastY = forward.y; } } else { base.transform.rotation = Quaternion.Lerp(this.backupRotation, this.targetRotation, this.animeValue); } } } private void OnCollisionEnter(Collision collision) { this.StopLookRotationAnime(); this.rigidBody.velocity = Vector3.zero; if (this.onCollisionEnter != null) { this.onCollisionEnter(this, collision); } } [SerializeField] protected bool isThrowCorrection; [SerializeField] protected float trackedLinearCorrectionTime; [SerializeField] protected float fallDownCorrectionTime; [SerializeField] protected float throwForceThreshold = 3f; [SerializeField] protected float throwForceRate = 1f; public WfGrabbableObject.OnThrowObjectEvent onThrowObjectEvent; public Action onCollisionEnter; public WfGrabbableObject.OnThrowObjectCorrectionVelocityEvent onThrowObjectCorrectionVelocityEvent; private Quaternion backupRotation; private Quaternion targetRotation; private bool isRotationAnime; private float animeValue; private float animeValue2; private float lastY; public delegate void OnThrowObjectEvent(WfGrabbableObject throwObject, bool mistakeThrow); public delegate void OnThrowObjectCorrectionVelocityEvent(ref Vector3 linearVelocity, ref Vector3 angularVelocity); }