namespace VRTK.Prefabs.Interactions.Interactables.Grab
{
using UnityEngine;
using UnityEngine.Events;
using System;
using System.Linq;
using System.Collections.Generic;
using Malimbe.XmlDocumentationAttribute;
using Malimbe.PropertySerializationAttribute;
using Malimbe.BehaviourStateRequirementMethod;
using VRTK.Prefabs.Interactions.Interactors;
///
/// Registers listeners to the initial grab and final ungrab states of an and emits the as the event payload.
///
public class InteractableGrabStateRegistrar : MonoBehaviour
{
///
/// Defines the event with the specified .
///
[Serializable]
public class UnityEvent : UnityEvent
{
}
///
/// Determines whether to unsubscribe all registered listeners when the component is disabled.
///
[Serialized]
[field: DocumentedByXml]
public bool UnsubscribeOnDisable { get; set; } = true;
///
/// Emitted when the is grabbed.
///
public UnityEvent Grabbed = new UnityEvent();
///
/// Emitted when the is ungrabbed.
///
public UnityEvent Ungrabbed = new UnityEvent();
///
/// s that unsubscribe the added grab event listeners.
///
protected readonly Dictionary unsubscribeGrabActions = new Dictionary();
///
/// s that unsubscribe the added ungrab event listeners.
///
protected readonly Dictionary unsubscribeUngrabActions = new Dictionary();
///
/// Registers a listener on the given Ungrabbed event.
///
/// The interactable to register the ungrab event on.
[RequiresBehaviourState]
public virtual void RegisterUngrabbed(InteractableFacade ungrabbable)
{
if (ungrabbable == null || unsubscribeUngrabActions.ContainsKey(ungrabbable))
{
return;
}
void OnUngrabbed(InteractorFacade _) => InteractableUngrabbed(ungrabbable);
ungrabbable.LastUngrabbed.AddListener(OnUngrabbed);
unsubscribeUngrabActions[ungrabbable] = () => ungrabbable.LastUngrabbed.RemoveListener(OnUngrabbed);
}
///
/// Registers a listener on the given 's Ungrabbed event.
///
/// The to get the from to register the ungrab event on.
[RequiresBehaviourState]
public virtual void RegisterUngrabbed(GameObject ungrabbable)
{
if (ungrabbable == null)
{
return;
}
RegisterUngrabbed(ungrabbable.GetComponent());
}
///
/// Registers a listener on the given Grabbed event.
///
/// The interactable to register the grab event on.
[RequiresBehaviourState]
public virtual void RegisterGrabbed(InteractableFacade grabbable)
{
if (grabbable == null || unsubscribeGrabActions.ContainsKey(grabbable))
{
return;
}
void OnGrabbed(InteractorFacade _) => InteractableGrabbed(grabbable);
grabbable.FirstGrabbed.AddListener(OnGrabbed);
unsubscribeGrabActions[grabbable] = () => grabbable.FirstGrabbed.RemoveListener(OnGrabbed);
}
///
/// Registers a listener on the given 's Grabbed event.
///
/// The to get the from to register the grab event on.
[RequiresBehaviourState]
public virtual void RegisterGrabbed(GameObject grabbable)
{
if (grabbable == null)
{
return;
}
RegisterGrabbed(grabbable.GetComponent());
}
///
/// Unregisters a listener from the given Ungrabbed event.
///
/// The interactable to unregister the ungrab event from.
public virtual void UnregisterUngrabbed(InteractableFacade ungrabbable)
{
if (ungrabbable == null || !unsubscribeUngrabActions.TryGetValue(ungrabbable, out System.Action unsubscribeAction))
{
return;
}
unsubscribeAction();
unsubscribeUngrabActions.Remove(ungrabbable);
}
///
/// Unregisters a listener from the given 's Ungrabbed event.
///
/// The to get the from to unregister the ungrab event from.
public virtual void UnregisterUngrabbed(GameObject ungrabbable)
{
if (ungrabbable == null)
{
return;
}
UnregisterUngrabbed(ungrabbable.GetComponent());
}
///
/// Unregisters a listener from the given Grabbed event.
///
/// The interactable to unregister the grab event from.
public virtual void UnregisterGrabbed(InteractableFacade grabbable)
{
if (grabbable == null || !unsubscribeGrabActions.TryGetValue(grabbable, out System.Action unsubscribeAction))
{
return;
}
unsubscribeAction();
unsubscribeGrabActions.Remove(grabbable);
}
///
/// Unregisters a listener from the given 's Grabbed event.
///
/// The to get the from to unregister the grab event from.
public virtual void UnregisterGrabbed(GameObject grabbable)
{
if (grabbable == null)
{
return;
}
UnregisterGrabbed(grabbable.GetComponent());
}
///
/// Unregisters all listeners for all ungrabbed events.
///
public virtual void UnregisterAllUngrabbed()
{
foreach (InteractableFacade entry in unsubscribeUngrabActions.Keys.ToArray())
{
UnregisterUngrabbed(entry);
}
unsubscribeUngrabActions.Clear();
}
///
/// Unregisters all listeners for all grabbed events.
///
public virtual void UnregisterAllGrabbed()
{
foreach (InteractableFacade entry in unsubscribeGrabActions.Keys.ToArray())
{
UnregisterGrabbed(entry);
}
unsubscribeGrabActions.Clear();
}
///
/// Unregisters all listeners for all events.
///
public virtual void UnregisterAll()
{
UnregisterAllUngrabbed();
UnregisterAllGrabbed();
}
protected virtual void OnDisable()
{
if (UnsubscribeOnDisable)
{
UnregisterAll();
}
}
///
/// Processes the grabbed event on the given Interactable.
///
/// The Interactable to process the grab event for.
protected virtual void InteractableGrabbed(InteractableFacade interactable)
{
Grabbed?.Invoke(interactable);
}
///
/// Processes the ungrabbed event on the given Interactable.
///
/// The Interactable to process the ungrab event for.
protected virtual void InteractableUngrabbed(InteractableFacade interactable)
{
Ungrabbed?.Invoke(interactable);
}
}
}