using System.Collections;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.UI.HandCoach
{
///
/// This class provides functionality to move the hand hint from a tracking position to a target position over time.
///
public class MoveToTarget : MonoBehaviour
{
[Tooltip("Object to track.")]
[SerializeField]
private GameObject trackingObject = null;
///
/// Object to track.
///
public GameObject TrackingObject
{
get
{
return trackingObject;
}
set
{
trackingObject = value;
}
}
[Tooltip("Target to move to.")]
[SerializeField]
private GameObject targetObject = null;
///
/// Target to move to.
///
public GameObject TargetObject
{
get
{
return targetObject;
}
set
{
targetObject = value;
}
}
[Tooltip("Shared parent between tracking and target objects used for relative local positions.")]
[SerializeField]
private GameObject rootObject = null;
///
/// Shared parent between tracking and target objects used for relative local positions.
///
public GameObject RootObject
{
get
{
return rootObject;
}
set
{
rootObject = value;
}
}
[Tooltip("Duration of move from tracking object to target object in seconds.")]
[SerializeField]
private float duration = 1.38f;
///
/// Duration of move from tracking object to target object in seconds.
///
public float Duration
{
get
{
return duration;
}
set
{
duration = value;
}
}
[Tooltip("Tunable offset to get the GameObject to arrive at the right target position.")]
[SerializeField]
private Vector3 targetOffset = new Vector3(0f, 0f, 0f);
///
/// Tunable offset to get the GameObject to arrive at the right target position.
///
public Vector3 TargetOffset
{
get
{
return targetOffset;
}
set
{
targetOffset = value;
}
}
[Tooltip("Lerp curve that controls the animation position over time from the trackingObject to the targetObject.")]
[SerializeField]
private AnimationCurve animationCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
///
/// Lerp curve that controls the animation position over time from the trackingObject to the targetObject.
///
public AnimationCurve AnimationCurve
{
get
{
return animationCurve;
}
set
{
animationCurve = value;
}
}
// The local position of this gameObject relative to the root object
private Vector3 relativePositionTrackingToRoot;
// The local position of targetObject relative to the root object
private Vector3 relativeTargetPositionToRoot;
// bool to determine when to stop the follow sequence
private bool followingTargetObject;
// Since this script can attach to an object with an animator, we need to update position in LateUpdate
private void LateUpdate()
{
if (TargetObject != null && RootObject != null)
{
relativeTargetPositionToRoot = GetRelativeLocalPosition(TargetObject, RootObject) + TargetOffset;
transform.parent.localPosition = relativePositionTrackingToRoot;
}
}
///
/// Starts coroutine to lerp from current position to target position
///
public void MoveToTargetPosition()
{
if (relativeTargetPositionToRoot != Vector3.zero)
{
followingTargetObject = false;
StartCoroutine(MoveHintSequence());
}
}
private IEnumerator MoveHintSequence()
{
Vector3 origin = relativePositionTrackingToRoot;
float t = 0;
while (t <= Duration)
{
relativePositionTrackingToRoot = Vector3.Lerp(origin, relativeTargetPositionToRoot, AnimationCurve.Evaluate(t / Duration));
t += Time.deltaTime;
yield return null;
}
}
///
/// Starts coroutine to follow the target object.
///
public void Follow()
{
if (TrackingObject != null && RootObject != null)
{
followingTargetObject = true;
StartCoroutine(FollowSequence());
}
}
private IEnumerator FollowSequence()
{
while (followingTargetObject)
{
relativePositionTrackingToRoot = GetRelativeLocalPosition(TrackingObject, RootObject);
yield return null;
}
}
private Vector3 GetRelativeLocalPosition(GameObject input, GameObject root)
{
return input.transform.position - root.transform.position;
}
}
}