namespace VRTK.Prefabs.Interactions.Interactors { using UnityEngine; using UnityEngine.Events; using System; using System.Collections.Generic; using Malimbe.MemberChangeMethod; using Malimbe.PropertySerializationAttribute; using Malimbe.MemberClearanceMethod; using Malimbe.XmlDocumentationAttribute; using Zinnia.Action; using Zinnia.Extension; using Zinnia.Data.Type; using Zinnia.Data.Attribute; using Zinnia.Tracking.Velocity; using VRTK.Prefabs.Interactions.Interactables; /// /// The public interface into the Interactor Prefab. /// public class InteractorFacade : MonoBehaviour { /// /// Defines the event with the . /// [Serializable] public class UnityEvent : UnityEvent { } #region Interactor Settings /// /// The that will initiate the Interactor grab mechanism. /// [Serialized, Cleared] [field: Header("Interactor Settings"), DocumentedByXml] public BooleanAction GrabAction { get; set; } /// /// The to measure the interactors current velocity. /// [Serialized, Cleared] [field: DocumentedByXml] public VelocityTrackerProcessor VelocityTracker { get; set; } /// /// The time between initiating the and touching an Interactable to be considered a valid grab. /// [Serialized] [field: DocumentedByXml] public float GrabPrecognition { get; set; } = 0.1f; #endregion #region Interactor Events /// /// Emitted when the Interactor starts touching a valid Interactable. /// [Header("Interactor Events"), DocumentedByXml] public UnityEvent Touched = new UnityEvent(); /// /// Emitted when the Interactor stops touching a valid Interactable. /// [DocumentedByXml] public UnityEvent Untouched = new UnityEvent(); /// /// Emitted when the Interactor starts grabbing a valid Interactable. /// [DocumentedByXml] public UnityEvent Grabbed = new UnityEvent(); /// /// Emitted when the Interactor stops grabbing a valid Interactable. /// [DocumentedByXml] public UnityEvent Ungrabbed = new UnityEvent(); #endregion #region Reference Settings /// /// The linked Touch Internal Setup. /// [Serialized] [field: Header("Reference Settings"), DocumentedByXml, Restricted] public TouchInteractorConfigurator TouchConfiguration { get; protected set; } /// /// The linked Grab Internal Setup. /// [Serialized] [field: DocumentedByXml, Restricted] public GrabInteractorConfigurator GrabConfiguration { get; protected set; } #endregion /// /// A collection of currently touched GameObjects. /// public IReadOnlyList TouchedObjects => TouchConfiguration.TouchedObjects; /// /// The currently active touched GameObject. /// public GameObject ActiveTouchedObject => TouchConfiguration.ActiveTouchedObject; /// /// A collection of currently grabbed GameObjects. /// public IReadOnlyList GrabbedObjects => GrabConfiguration.GrabbedObjects; /// /// Attempt to attach a that contains an to this . /// /// The GameObject that the Interactable is on. public virtual void Grab(GameObject interactable) { Grab(interactable.TryGetComponent(true, true)); } /// /// Attempt to attach an to this . /// /// The Interactable to attempt to grab. public virtual void Grab(InteractableFacade interactable) { Grab(interactable, null, null); } /// /// Attempt to attach an found in the given to this . /// /// The collision data containing a valid Interactable. public virtual void Grab(SurfaceData data) { if (data == null || data.CollisionData.transform == null) { return; } Grab(data.CollisionData.transform.gameObject.TryGetComponent(true, true), null, null); } /// /// Attempt to attach an to this utilizing custom collision data. /// /// The Interactable to attempt to grab. /// Custom collision data. /// Custom collider data. public virtual void Grab(InteractableFacade interactable, Collision collision, Collider collider) { GrabConfiguration.Grab(interactable, collision, collider); } /// /// Attempt to ungrab currently grabbed Interactables to the current Interactor. /// public virtual void Ungrab() { GrabConfiguration.Ungrab(); } /// /// Notifies the interactor that it is touching an interactable. /// /// The interactable being touched. public virtual void NotifyOfTouch(InteractableFacade interactable) { Touched?.Invoke(interactable); } /// /// Notifies the interactor that it is no longer touching an interactable. /// /// The interactable being untouched. public virtual void NotifyOfUntouch(InteractableFacade interactable) { Untouched?.Invoke(interactable); } /// /// Notifies the interactor that it is grabbing an interactable. /// /// The interactable being grabbed. public virtual void NotifyOfGrab(InteractableFacade interactable) { Grabbed?.Invoke(interactable); GrabConfiguration.GrabbedObjectsCollection.AddUnique(interactable.gameObject); } /// /// Notifies the interactor that it is no longer grabbing an interactable. /// /// The interactable being ungrabbed. public virtual void NotifyOfUngrab(InteractableFacade interactable) { Ungrabbed?.Invoke(interactable); GrabConfiguration.GrabbedObjectsCollection.Remove(interactable.gameObject); GrabConfiguration.StopGrabbingPublisher.ClearActiveCollisions(); } /// /// Called after has been changed. /// [CalledAfterChangeOf(nameof(GrabAction))] protected virtual void OnAfterGrabActionChange() { GrabConfiguration.ConfigureGrabAction(); } /// /// Called after has been changed. /// [CalledAfterChangeOf(nameof(VelocityTracker))] protected virtual void OnAfterVelocityTrackerChange() { GrabConfiguration.ConfigureVelocityTrackers(); } /// /// Called after has been changed. /// [CalledAfterChangeOf(nameof(GrabPrecognition))] protected virtual void OnAfterGrabPrecognitionChange() { GrabConfiguration.ConfigureGrabPrecognition(); } } }