//////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2007-2020 , Inc. All Rights Reserved. // //////////////////////////////////////////////////////////////////////////////// using UnityEngine; using UnityEngine.EventSystems; using GCSeries.Core.EventSystems; using GCSeries.Core.Input; namespace GCSeries.Core.Samples { public class Draggable : ZPointerInteractable, IBeginDragHandler, IDragHandler, IEndDragHandler { public bool Active = true; //////////////////////////////////////////////////////////////////////// // Public Methods //////////////////////////////////////////////////////////////////////// public override ZPointer.DragPolicy GetDragPolicy(ZPointer pointer) { if (pointer is ZMouse) { return ZPointer.DragPolicy.LockToScreenAlignedPlane; } if (pointer is ZStylus) { return ZPointer.DragPolicy.LockHitPosition; } return base.GetDragPolicy(pointer); } public virtual void OnBeginDrag(PointerEventData eventData) { if (!this.Active) return; ZPointerEventData pointerEventData = eventData as ZPointerEventData; if (pointerEventData == null || pointerEventData.button != PointerEventData.InputButton.Left) { return; } Pose pose = pointerEventData.Pointer.EndPointWorldPose; // Cache the initial grab state. this._initialGrabOffset = Quaternion.Inverse(this.transform.rotation) * (this.transform.position - pose.position); this._initialGrabRotation = Quaternion.Inverse(pose.rotation) * this.transform.rotation; // If the grabbable object has a rigidbody component, // mark it as kinematic during the grab. var rigidbody = this.GetComponent(); if (rigidbody != null) { this._isKinematic = rigidbody.isKinematic; rigidbody.isKinematic = true; } // Capture pointer events. pointerEventData.Pointer.CapturePointer(this.gameObject); } public virtual void OnDrag(PointerEventData eventData) { if (!this.Active) return; if (_initialGrabOffset == Vector3.zero) return; ZPointerEventData pointerEventData = eventData as ZPointerEventData; if (pointerEventData == null || pointerEventData.button != PointerEventData.InputButton.Left) { return; } Pose pose = pointerEventData.Pointer.EndPointWorldPose; // Update the grab object's rotation. this.transform.rotation = pose.rotation * this._initialGrabRotation; // Update the grab object's position. this.transform.position = pose.position + (this.transform.rotation * this._initialGrabOffset); } public virtual void OnEndDrag(PointerEventData eventData) { if (!this.Active) return; ZPointerEventData pointerEventData = eventData as ZPointerEventData; if (pointerEventData == null || pointerEventData.button != PointerEventData.InputButton.Left) { return; } // Release the pointer. pointerEventData.Pointer.CapturePointer(null); // If the grabbable object has a rigidbody component, // restore its original isKinematic state. var rigidbody = this.GetComponent(); if (rigidbody != null) { rigidbody.isKinematic = this._isKinematic; } _initialGrabOffset = Vector3.zero; } //////////////////////////////////////////////////////////////////////// // Private Members //////////////////////////////////////////////////////////////////////// private Vector3 _initialGrabOffset = Vector3.zero; private Quaternion _initialGrabRotation = Quaternion.identity; private bool _isKinematic = false; } }