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();
}
}
}