namespace VRTK.Prefabs.Interactions.Controllables
{
using UnityEngine;
using Malimbe.XmlDocumentationAttribute;
using Malimbe.PropertySerializationAttribute;
using Malimbe.BehaviourStateRequirementMethod;
using Zinnia.Extension;
using Zinnia.Data.Type;
using Zinnia.Data.Attribute;
using Zinnia.Tracking.Velocity;
using Zinnia.Tracking.Follow.Modifier.Property.Rotation;
using VRTK.Prefabs.Interactions.Interactables;
///
/// A rotational drive that directly manipulates a to control the rotational angle without the use of any physics.
///
public class RotationalTransformDrive : RotationalDrive
{
#region Reference Settings
///
/// The that controls the movement of the drive.
///
[Serialized]
[field: Header("Reference Settings"), DocumentedByXml, Restricted]
public InteractableFacade Interactable { get; protected set; }
///
/// The that contains the meshes for the control.
///
[Serialized]
[field: DocumentedByXml, Restricted]
public GameObject InteractableMesh { get; protected set; }
///
/// The to drive the rotation of the control.
///
[Serialized]
[field: DocumentedByXml, Restricted]
public TransformPositionDifferenceRotation RotationModifier { get; protected set; }
///
/// The that applies artificial angular velocity to the control after releasing.
///
[Serialized]
[field: DocumentedByXml, Restricted]
public ArtificialVelocityApplier VelocityApplier { get; protected set; }
#endregion
///
[RequiresBehaviourState]
public override Vector3 CalculateDriveAxis(DriveAxis.Axis driveAxis)
{
Vector3 axisDirection = base.CalculateDriveAxis(driveAxis);
switch (driveAxis)
{
case DriveAxis.Axis.XAxis:
RotationModifier.FollowOnAxis = Vector3State.XOnly;
break;
case DriveAxis.Axis.YAxis:
RotationModifier.FollowOnAxis = Vector3State.YOnly;
break;
case DriveAxis.Axis.ZAxis:
RotationModifier.FollowOnAxis = Vector3State.ZOnly;
break;
}
return axisDirection;
}
///
[RequiresBehaviourState]
public override void CalculateHingeLocation(Vector3 newHingeLocation)
{
transform.localPosition = newHingeLocation;
InteractableMesh.transform.localPosition = newHingeLocation * -1f;
}
///
public override void ApplyExistingAngularVelocity(float multiplier = 1f)
{
VelocityApplier.AngularVelocity = AxisDirection * pseudoAngularVelocity * multiplier;
VelocityApplier.Apply();
}
///
protected override Transform GetDriveTransform()
{
return Interactable.transform;
}
///
protected override void AttemptApplyLimits()
{
if (ApplyLimits())
{
VelocityApplier.Velocity = Vector3.zero;
VelocityApplier.AngularVelocity = Vector3.zero;
}
}
///
protected override void ProcessAutoDrive(float driveSpeed)
{
if (Facade.MoveToTargetValue && !driveSpeed.ApproxEquals(0f))
{
GetDriveTransform().localRotation *= Quaternion.Euler(-AxisDirection * driveSpeed * Time.deltaTime);
}
}
}
}