You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
7.2 KiB
206 lines
7.2 KiB
//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== |
|
|
|
using HTC.UnityPlugin.ColliderEvent; |
|
using HTC.UnityPlugin.Utility; |
|
using System; |
|
using UnityEngine; |
|
using UnityEngine.Events; |
|
using UnityEngine.Serialization; |
|
|
|
namespace HTC.UnityPlugin.Vive |
|
{ |
|
[AddComponentMenu("HTC/VIU/Object Grabber/Basic Grabbable", 0)] |
|
public class BasicGrabbable : GrabbableBase<BasicGrabbable.Grabber> |
|
, IColliderEventDragStartHandler |
|
, IColliderEventDragFixedUpdateHandler |
|
, IColliderEventDragUpdateHandler |
|
, IColliderEventDragEndHandler |
|
{ |
|
[Serializable] |
|
public class UnityEventGrabbable : UnityEvent<BasicGrabbable> { } |
|
|
|
public class Grabber : IGrabber |
|
{ |
|
private static ObjectPool<Grabber> m_pool; |
|
|
|
public static Grabber Get(ColliderButtonEventData eventData) |
|
{ |
|
if (m_pool == null) |
|
{ |
|
m_pool = new ObjectPool<Grabber>(() => new Grabber()); |
|
} |
|
|
|
var grabber = m_pool.Get(); |
|
grabber.eventData = eventData; |
|
return grabber; |
|
} |
|
|
|
public static void Release(Grabber grabber) |
|
{ |
|
grabber.eventData = null; |
|
m_pool.Release(grabber); |
|
} |
|
|
|
public ColliderButtonEventData eventData { get; private set; } |
|
|
|
public RigidPose grabberOrigin |
|
{ |
|
get |
|
{ |
|
return new RigidPose(eventData.eventCaster.transform); |
|
} |
|
} |
|
|
|
public RigidPose grabOffset { get; set; } |
|
} |
|
|
|
private IndexedTable<ColliderButtonEventData, Grabber> m_eventGrabberSet; |
|
|
|
public bool alignPosition; |
|
public bool alignRotation; |
|
public Vector3 alignPositionOffset; |
|
public Vector3 alignRotationOffset; |
|
|
|
[Range(MIN_FOLLOWING_DURATION, MAX_FOLLOWING_DURATION)] |
|
[FormerlySerializedAs("followingDuration")] |
|
[SerializeField] |
|
private float m_followingDuration = DEFAULT_FOLLOWING_DURATION; |
|
[FormerlySerializedAs("overrideMaxAngularVelocity")] |
|
[SerializeField] |
|
private bool m_overrideMaxAngularVelocity = true; |
|
[FormerlySerializedAs("unblockableGrab")] |
|
[SerializeField] |
|
private bool m_unblockableGrab = true; |
|
[SerializeField] |
|
private ColliderButtonEventData.InputButton m_grabButton = ColliderButtonEventData.InputButton.Trigger; |
|
[SerializeField] |
|
private bool m_allowMultipleGrabbers = true; |
|
[FormerlySerializedAs("afterGrabbed")] |
|
[SerializeField] |
|
private UnityEventGrabbable m_afterGrabbed = new UnityEventGrabbable(); |
|
[FormerlySerializedAs("beforeRelease")] |
|
[SerializeField] |
|
private UnityEventGrabbable m_beforeRelease = new UnityEventGrabbable(); |
|
[FormerlySerializedAs("onDrop")] |
|
[SerializeField] |
|
private UnityEventGrabbable m_onDrop = new UnityEventGrabbable(); // change rigidbody drop velocity here |
|
|
|
public override float followingDuration { get { return m_followingDuration; } set { m_followingDuration = Mathf.Clamp(value, MIN_FOLLOWING_DURATION, MAX_FOLLOWING_DURATION); } } |
|
|
|
public override bool overrideMaxAngularVelocity { get { return m_overrideMaxAngularVelocity; } set { m_overrideMaxAngularVelocity = value; } } |
|
|
|
public bool unblockableGrab { get { return m_unblockableGrab; } set { m_unblockableGrab = value; } } |
|
|
|
public UnityEventGrabbable afterGrabbed { get { return m_afterGrabbed; } } |
|
|
|
public UnityEventGrabbable beforeRelease { get { return m_beforeRelease; } } |
|
|
|
public UnityEventGrabbable onDrop { get { return m_onDrop; } } |
|
|
|
public ColliderButtonEventData grabbedEvent { get { return isGrabbed ? currentGrabber.eventData : null; } } |
|
|
|
public ColliderButtonEventData.InputButton grabButton |
|
{ |
|
get |
|
{ |
|
return m_grabButton; |
|
} |
|
set |
|
{ |
|
m_grabButton = value; |
|
MaterialChanger.SetAllChildrenHeighlightButton(gameObject, value); |
|
} |
|
} |
|
|
|
private bool moveByVelocity { get { return !unblockableGrab && grabRigidbody != null && !grabRigidbody.isKinematic; } } |
|
|
|
[Obsolete("Use grabRigidbody instead")] |
|
public Rigidbody rigid { get { return grabRigidbody; } set { grabRigidbody = value; } } |
|
|
|
#if UNITY_EDITOR |
|
protected virtual void OnValidate() |
|
{ |
|
MaterialChanger.SetAllChildrenHeighlightButton(gameObject, m_grabButton); |
|
} |
|
#endif |
|
|
|
protected override void Awake() |
|
{ |
|
base.Awake(); |
|
MaterialChanger.SetAllChildrenHeighlightButton(gameObject, m_grabButton); |
|
|
|
afterGrabberGrabbed += () => m_afterGrabbed.Invoke(this); |
|
beforeGrabberReleased += () => m_beforeRelease.Invoke(this); |
|
onGrabberDrop += () => m_onDrop.Invoke(this); |
|
} |
|
|
|
protected virtual void OnDisable() |
|
{ |
|
ClearGrabbers(true); |
|
ClearEventGrabberSet(); |
|
} |
|
|
|
private void ClearEventGrabberSet() |
|
{ |
|
if (m_eventGrabberSet == null) { return; } |
|
|
|
for (int i = m_eventGrabberSet.Count - 1; i >= 0; --i) |
|
{ |
|
Grabber.Release(m_eventGrabberSet.GetValueByIndex(i)); |
|
} |
|
|
|
m_eventGrabberSet.Clear(); |
|
} |
|
|
|
public virtual void OnColliderEventDragStart(ColliderButtonEventData eventData) |
|
{ |
|
if (eventData.button != m_grabButton) { return; } |
|
|
|
if (!m_allowMultipleGrabbers) |
|
{ |
|
ClearGrabbers(false); |
|
ClearEventGrabberSet(); |
|
} |
|
|
|
var grabber = Grabber.Get(eventData); |
|
var offset = RigidPose.FromToPose(grabber.grabberOrigin, new RigidPose(transform)); |
|
if (alignPosition) { offset.pos = alignPositionOffset; } |
|
if (alignRotation) { offset.rot = Quaternion.Euler(alignRotationOffset); } |
|
grabber.grabOffset = offset; |
|
|
|
if (m_eventGrabberSet == null) { m_eventGrabberSet = new IndexedTable<ColliderButtonEventData, Grabber>(); } |
|
m_eventGrabberSet.Add(eventData, grabber); |
|
|
|
AddGrabber(grabber); |
|
} |
|
|
|
public virtual void OnColliderEventDragFixedUpdate(ColliderButtonEventData eventData) |
|
{ |
|
if (isGrabbed && moveByVelocity && currentGrabber.eventData == eventData) |
|
{ |
|
OnGrabRigidbody(); |
|
} |
|
} |
|
|
|
public virtual void OnColliderEventDragUpdate(ColliderButtonEventData eventData) |
|
{ |
|
if (isGrabbed && !moveByVelocity && currentGrabber.eventData == eventData) |
|
{ |
|
RecordLatestPosesForDrop(Time.time, 0.05f); |
|
OnGrabTransform(); |
|
} |
|
} |
|
|
|
public virtual void OnColliderEventDragEnd(ColliderButtonEventData eventData) |
|
{ |
|
if (m_eventGrabberSet == null) { return; } |
|
|
|
Grabber grabber; |
|
if (!m_eventGrabberSet.TryGetValue(eventData, out grabber)) { return; } |
|
|
|
RemoveGrabber(grabber); |
|
m_eventGrabberSet.Remove(eventData); |
|
Grabber.Release(grabber); |
|
} |
|
} |
|
} |