using System.Collections;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.UI.HandCoach
{
///
/// This class provides functionality to rotate the hand hint around a pivot point over time.
///
public class RotateAroundPoint : MonoBehaviour
{
[Tooltip("Parent object centered at rotation center.")]
[SerializeField]
private Transform centeredParent = null;
///
/// Parent object centered at rotation center.
///
public Transform CenteredParent
{
get
{
return centeredParent;
}
set
{
centeredParent = value;
}
}
[Tooltip("Hand hint parent to rotate inverse to centeredParent to keep hand orientation the same.")]
[SerializeField]
private Transform inverseParent = null;
///
/// Hand hint parent to rotate inverse to centeredParent to keep hand orientation the same.
///
public Transform InverseParent
{
get
{
return inverseParent;
}
set
{
inverseParent = value;
}
}
[Tooltip("Point to start movement at.")]
[SerializeField]
private Transform pivotPosition = null;
///
/// Point to start movement at.
///
public Transform PivotPosition
{
get
{
return pivotPosition;
}
set
{
pivotPosition = value;
}
}
[Tooltip("Duration of rotation around the CenteredParent in seconds.")]
[SerializeField]
private float duration = 1.38f;
///
/// Duration of rotation around the CenteredParent in seconds.
///
public float Duration
{
get
{
return duration;
}
set
{
duration = value;
}
}
[Tooltip("Lerp curve that controls the animation rotation over time.")]
[SerializeField]
private AnimationCurve animationCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
///
/// Lerp curve that controls the animation rotation over time.
///
public AnimationCurve AnimationCurve
{
get
{
return animationCurve;
}
set
{
animationCurve = value;
}
}
[Tooltip("How many degrees to rotate along each axis.")]
[SerializeField]
private Vector3 rotationVector = new Vector3(0f, 90f, 0f);
///
/// How many degrees to rotate along each axis.
///
public Vector3 RotationVector
{
get
{
return rotationVector;
}
set
{
rotationVector = value;
}
}
private Vector3 centeredParentRotate;
private Vector3 hintPosition;
// used to allow position changing in LateUpdate() and position correction in RotateHintSequence()
private bool updatePosition = true;
// since this script can attach to an object with an animator, we need to update position in LateUpdate
public void LateUpdate()
{
// set inverseParent position based on DeterminePivot()
if (updatePosition)
{
InverseParent.localPosition = hintPosition;
}
// set centeredParent rotation based on RotateToTarget()
CenteredParent.localEulerAngles = centeredParentRotate;
// set inverseParent rotation based on RotateToTarget() and parent object
InverseParent.localEulerAngles = -centeredParentRotate;
}
///
/// Start the rotation sequence.
///
public void RotateToTarget()
{
StartCoroutine(RotateHintSequence());
}
///
/// Reset position to the PivotPosition.
///
public IEnumerator ResetAndDeterminePivot()
{
// reset rotation and wait a frame to ensure the centeredParent is set in LateUpdate
centeredParentRotate = new Vector3(0f, 0f, 0f);
yield return null;
int index = 0;
updatePosition = true;
StartCoroutine(TrackPositionSequence(index));
}
// tracks the pivot determined above
private IEnumerator TrackPositionSequence(int index)
{
while (updatePosition)
{
hintPosition = PivotPosition.localPosition;
yield return null;
}
}
// lerp from current position to target position
private IEnumerator RotateHintSequence()
{
updatePosition = false;
Vector3 centeredOrigin = CenteredParent.localEulerAngles;
Vector3 targetOrigin = centeredOrigin + RotationVector;
float t = 0;
while (t <= Duration)
{
centeredParentRotate = Vector3.Lerp(centeredOrigin, targetOrigin, AnimationCurve.Evaluate(t / duration));
t += Time.deltaTime;
yield return null;
}
// after we reach the target, we still want to be stabilized
while (!updatePosition)
{
centeredParentRotate = targetOrigin;
yield return null;
}
}
}
}