namespace Tilia.Interactions.Interactables.Interactables
{
using System;
using System.Collections;
using Tilia.Interactions.Interactables.Interactors;
using UnityEngine;
using UnityEngine.Events;
using Zinnia.Extension;
///
/// Attempts to grab the given Interactable to the given Interactor.
///
public class InteractableGrabber : MonoBehaviour
{
///
/// Defines the event with the .
///
[Serializable]
public class UnityEvent : UnityEvent { }
[Tooltip("The Interactor to grab to.")]
[SerializeField]
private InteractorFacade interactor;
///
/// The Interactor to grab to.
///
public InteractorFacade Interactor
{
get
{
return interactor;
}
set
{
interactor = value;
}
}
[Tooltip("The Interactable to grab.")]
[SerializeField]
private InteractableFacade interactable;
///
/// The Interactable to grab.
///
public InteractableFacade Interactable
{
get
{
return interactable;
}
set
{
interactable = value;
}
}
///
/// Emitted when the Grab has occurred.
///
public UnityEvent Grabbed = new UnityEvent();
///
/// A reusable instance of .
///
protected static readonly WaitForEndOfFrame DelayInstruction = new WaitForEndOfFrame();
///
/// The routine for managing the grab.
///
protected Coroutine grabRoutine;
///
/// Clears .
///
public virtual void ClearInteractor()
{
if (!this.IsValidState())
{
return;
}
Interactor = default;
}
///
/// Clears .
///
public virtual void ClearInteractable()
{
if (!this.IsValidState())
{
return;
}
Interactable = default;
}
///
/// Sets the from the given .
///
/// The object to search for the Interactor on.
public virtual void SetInteractorFromGameObject(GameObject interactor)
{
Interactor = interactor.TryGetComponent(true, true);
}
///
/// Sets the from the given .
///
/// The object to search for the Interactable on.
public virtual void SetInteractableFromGameObject(GameObject interactable)
{
Interactable = interactable.TryGetComponent(true, true);
}
///
/// Attempts to grab the to the .
///
public virtual void DoGrab()
{
if (!this.IsValidState() || Interactor == null || Interactable == null)
{
return;
}
if (Interactable.IsGrabbed)
{
Interactable.Ungrab();
}
CancelGrabRoutine();
grabRoutine = StartCoroutine(GrabAtEndOfFrame());
}
protected virtual void OnDisable()
{
CancelGrabRoutine();
}
///
/// Performs the grab at the end of the current frame.
///
/// Coroutine enumerator.
protected virtual IEnumerator GrabAtEndOfFrame()
{
yield return DelayInstruction;
if (Interactor.GrabConfiguration.GrabAction.Value)
{
bool cachedSetting = Interactor.GrabConfiguration.TouchBeforeForceGrab;
Interactor.GrabConfiguration.TouchBeforeForceGrab = false;
Interactor.Grab(Interactable);
Interactor.GrabConfiguration.TouchBeforeForceGrab = cachedSetting;
Grabbed?.Invoke(Interactable);
}
}
///
/// Cancels the existing running grab coroutine.
///
protected virtual void CancelGrabRoutine()
{
if (grabRoutine == null)
{
return;
}
StopCoroutine(grabRoutine);
grabRoutine = null;
}
}
}