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