namespace VRTK.Prefabs.Locomotion.Movement.Climb
{
using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
using Malimbe.PropertySerializationAttribute;
using Malimbe.XmlDocumentationAttribute;
using Malimbe.MemberClearanceMethod;
using Malimbe.MemberChangeMethod;
using Zinnia.Data.Attribute;
using VRTK.Prefabs.Locomotion.BodyRepresentation;
using Malimbe.BehaviourStateRequirementMethod;
///
/// The public interface for the Climb prefab.
///
public class ClimbFacade : MonoBehaviour
{
#region Control Settings
///
/// The body representation to control.
///
[Serialized, Cleared]
[field: Header("Control Settings"), DocumentedByXml]
public BodyRepresentationFacade BodyRepresentationFacade { get; set; }
#endregion
#region Events
///
/// Emitted when a climb starts.
///
[Header("Events"), DocumentedByXml]
public UnityEvent ClimbStarted = new UnityEvent();
///
/// Emitted when the climb stops.
///
[DocumentedByXml]
public UnityEvent ClimbStopped = new UnityEvent();
#endregion
#region Reference Settings
///
/// Applies velocity when releasing from climb.
///
[Serialized]
[field: Header("Reference Settings"), DocumentedByXml, Restricted]
public ClimbVelocityApplier VelocityApplier { get; protected set; }
#endregion
///
/// The current source of the movement. The body will be moved in reverse direction in case this object moves.
///
public GameObject CurrentInteractor => Interactors.Count == 0 ? null : Interactors[Interactors.Count - 1];
///
/// The current optional offset of the movement. The body will be moved in case this object moves.
///
public GameObject CurrentInteractable => Interactables.Count == 0 ? null : Interactables[Interactors.Count - 1];
///
/// Whether a climb is happening right now.
///
public bool IsClimbing => Interactors.Count > 0 || Interactables.Count > 0;
///
/// The objects that define the source of movement in order they should be used. The last object defines .
///
public IReadOnlyList Interactors => VelocityApplier.Interactors.NonSubscribableElements;
///
/// The objects that define the optional offsets of movement in order they should be used. The last object defines .
///
public IReadOnlyList Interactables => VelocityApplier.Interactables.NonSubscribableElements;
///
/// Adds a source of movement for the body.
///
/// The object to use as a source of the movement.
[RequiresBehaviourState]
public virtual void AddInteractor(GameObject interactor)
{
VelocityApplier.Interactors.Add(interactor);
}
///
/// Removes a source of movement for the body.
///
/// The object used as a source of the movement.
[RequiresBehaviourState]
public virtual void RemoveInteractor(GameObject interactor)
{
if (!VelocityApplier.Interactors.Contains(interactor))
{
return;
}
VelocityApplier.Interactors.RemoveLastOccurrence(interactor);
VelocityApplier.ApplyVelocity();
}
///
/// Clears the sources of the movement.
///
[RequiresBehaviourState]
public virtual void ClearInteractors()
{
VelocityApplier.Interactors.Clear();
}
///
/// Adds an optional offset of movement for the body.
///
/// The object to use as an optional offset of the movement.
[RequiresBehaviourState]
public virtual void AddInteractable(GameObject interactable)
{
VelocityApplier.Interactables.Add(interactable);
}
///
/// Removes an optional offset of movement for the body.
///
/// The object used as an optional offset of the movement.
[RequiresBehaviourState]
public virtual void RemoveInteractable(GameObject interactable)
{
VelocityApplier.Interactables.RemoveLastOccurrence(interactable);
}
///
/// Clears the optional offsets of the movement.
///
[RequiresBehaviourState]
public virtual void ClearInteractables()
{
VelocityApplier.Interactables.Clear();
}
///
/// Sets a source to track the velocity from.
///
/// The tracked velocity source.
public virtual void SetVelocitySource(GameObject source)
{
VelocityApplier.VelocityProxy.ProxySource = source;
}
///
/// Sets the multiplier to apply to any tracked velocity.
///
/// The multiplier to apply to tracked velocity.
public virtual void SetVelocityMultiplier(Vector3 multiplier)
{
VelocityApplier.VelocityMultiplier.Collection.SetAt(multiplier, 1);
VelocityApplier.VelocityMultiplier.Collection.CurrentIndex = 0;
}
///
/// Called after has been changed.
///
[CalledAfterChangeOf(nameof(BodyRepresentationFacade))]
protected virtual void OnAfterBodyRepresentationFacadeChange()
{
VelocityApplier.ConfigureTargetPositionProperty();
}
}
}