namespace VRTK.Prefabs.Interactions.Controllables
{
using System;
using UnityEngine;
using UnityEngine.Events;
using Malimbe.MemberChangeMethod;
using Malimbe.XmlDocumentationAttribute;
using Malimbe.PropertySerializationAttribute;
using Zinnia.Data.Type;
using Zinnia.Data.Attribute;
///
/// Defines the event with the drive value.
///
[Serializable]
public class DriveUnityEvent : UnityEvent
{
}
///
/// The basis of the public interface that will drive a control in relation to a specified world axis.
///
/// The to operate with the facade.
/// The actual concrete implementation of the drive facade being used.
public abstract class DriveFacade : MonoBehaviour where TDrive : Drive where TSelf : DriveFacade
{
#region Reference Settings
///
/// The linked
///
[Serialized]
[field: Header("Reference Settings"), DocumentedByXml, Restricted]
public TDrive Drive { get; protected set; }
#endregion
#region Events
///
/// Emitted when the raw value changes with the raw value data.
///
[Header("Events"), DocumentedByXml]
public DriveUnityEvent ValueChanged = new DriveUnityEvent();
///
/// Emitted when the step value changes with the step value data.
///
[DocumentedByXml]
public DriveUnityEvent StepValueChanged = new DriveUnityEvent();
///
/// Emitted when the normalized value changes with the normalized value data.
///
[DocumentedByXml]
public DriveUnityEvent NormalizedValueChanged = new DriveUnityEvent();
///
/// Emitted when has been reached by the control.
///
[DocumentedByXml]
public DriveUnityEvent TargetValueReached = new DriveUnityEvent();
///
/// Emitted when the drive starts moving the control.
///
[DocumentedByXml]
public DriveUnityEvent StartedMoving = new DriveUnityEvent();
///
/// Emitted when the drive is no longer moving the control and it is stationary.
///
[DocumentedByXml]
public DriveUnityEvent StoppedMoving = new DriveUnityEvent();
#endregion
#region Drive Settings
///
/// The axis to operate the drive motion on.
///
[Serialized]
[field: Header("Drive Settings"), DocumentedByXml]
public DriveAxis.Axis DriveAxis { get; set; } = Controllables.DriveAxis.Axis.XAxis;
///
/// Determines if the drive should move the element to the set .
///
[Serialized]
[field: DocumentedByXml]
public bool MoveToTargetValue { get; set; } = true;
///
/// The normalized value to attempt to drive the control to if the is set to .
///
[Serialized]
[field: DocumentedByXml, Range(0f, 1f)]
public float TargetValue { get; set; } = 0.5f;
///
/// The speed in which the drive will attempt to move the control to the desired value.
///
[Serialized]
[field: DocumentedByXml]
public float DriveSpeed { get; set; } = 10f;
#endregion
#region Step Settings
///
/// The range of step values to use.
///
[Serialized]
[field: Header("Step Settings"), DocumentedByXml]
public FloatRange StepRange { get; set; } = new FloatRange(0f, 10f);
///
/// The increment to increase the steps in value by.
///
[Serialized]
[field: DocumentedByXml]
public float StepIncrement { get; set; } = 1f;
#endregion
///
/// Sets the to the position that the current step value represents.
///
public virtual void SetTargetValueByStepValue()
{
SetTargetValueByStepValue(Drive.StepValue);
}
///
/// Sets the to the position that the given step value represents.
///
/// The step value that represents the new target value.
public virtual void SetTargetValueByStepValue(float stepValue)
{
float normalizedStepValue = Mathf.InverseLerp(StepRange.minimum, StepRange.maximum, Mathf.Clamp(stepValue, StepRange.minimum, StepRange.maximum));
TargetValue = normalizedStepValue;
}
///
/// Forces the drive to move to the current step value at the given speed.
///
/// The speed the drive will move the control at.
public virtual void ForceSnapToStepValue(float driveSpeed)
{
MoveToTargetValue = true;
DriveSpeed = driveSpeed;
SetTargetValueByStepValue();
}
///
/// Calculates the axis to use for the given .
///
/// The new value.
protected virtual void CalculateDriveAxis(DriveAxis.Axis driveAxis)
{
Drive.CalculateDriveAxis(driveAxis);
}
///
/// Processes the drive's ability to automatically drive the control.
///
/// Whether the drive can automatically drive the control.
protected virtual void ProcessAutoDrive(bool autoDrive)
{
Drive.ConfigureAutoDrive(autoDrive);
}
///
/// Sets the new .
///
/// The new value.
protected virtual void SetTargetValue(float targetValue)
{
Drive.SetTargetValue(targetValue);
}
///
/// Processes the changes to the .
///
/// The new value.
/// Whether the new value should be processed.
protected virtual void ProcessDriveSpeed(float driveSpeed, bool moveToTargetValue)
{
Drive.ProcessDriveSpeed(driveSpeed, moveToTargetValue);
}
///
/// Called after has been changed.
///
[CalledAfterChangeOf(nameof(DriveAxis))]
protected virtual void OnAfterDriveAxisChange()
{
Drive.SetUp();
}
///
/// Called after has been changed.
///
[CalledAfterChangeOf(nameof(MoveToTargetValue))]
protected virtual void OnAfterMoveToTargetValueChange()
{
Drive.SetUp();
}
///
/// Called after has been changed.
///
[CalledAfterChangeOf(nameof(TargetValue))]
protected virtual void OnAfterTargetValueChange()
{
Drive.SetUp();
}
///
/// Called after has been changed.
///
[CalledAfterChangeOf(nameof(DriveSpeed))]
protected virtual void OnAfterDriveSpeedChange()
{
Drive.SetUp();
}
///
/// Called after has been changed.
///
[CalledAfterChangeOf(nameof(StepRange))]
protected virtual void OnAfterStepRangeChange()
{
Drive.SetUp();
}
///
/// Called after has been changed.
///
[CalledAfterChangeOf(nameof(StepIncrement))]
protected virtual void OnAfterStepIncrementChange()
{
Drive.SetUp();
}
}
}