295 lines
8.2 KiB
C#
295 lines
8.2 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using UnityEngine;
|
|
|
|
namespace Microsoft.MixedReality.Toolkit.UI
|
|
{
|
|
/// <summary>
|
|
/// Controls how the standard indeterminate loader moves and behaves over time.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This loader is calculated dynamically based on Sine and Cosine
|
|
/// </remarks>
|
|
[AddComponentMenu("Scripts/MRTK/SDK/LoaderController")]
|
|
public class LoaderController : MonoBehaviour
|
|
{
|
|
|
|
/// <summary>
|
|
/// Total strength of movement of the loading animation
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Total strength of movement of the loading animation")]
|
|
private float amplitude = 0.05f;
|
|
|
|
public float Amplitude
|
|
{
|
|
get => amplitude;
|
|
set => amplitude = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// How often <see cref="amplitude"/> happens
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("How often 'amplitude' happens")]
|
|
private float frequency = 3.0f;
|
|
|
|
public float Frequency
|
|
{
|
|
get => frequency;
|
|
set => frequency = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The base local position for the dots' parent
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("The base local position for the dots' parent")]
|
|
private float dotOffset = 0.05f;
|
|
|
|
public float DotOffset
|
|
{
|
|
get => dotOffset;
|
|
set => dotOffset = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The base scale unit for the dots' parent
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("The base scale unit for the dots' parent")]
|
|
private float dotSetScale = 0.06f;
|
|
|
|
public float DotSetScale
|
|
{
|
|
get => dotSetScale;
|
|
set => dotSetScale = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use low frequency oscillation with the Sine calculation.
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Use low frequency oscillation with the Sine calculation.")]
|
|
private bool lFOsin = false;
|
|
|
|
public bool LFOsin
|
|
{
|
|
get => lFOsin;
|
|
set => lFOsin = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use low frequency oscillation with the Cosine calculation.
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Use low frequency oscillation with the Cosine calculation.")]
|
|
private bool lFOcos = false;
|
|
|
|
public bool LFOcos
|
|
{
|
|
get => lFOcos;
|
|
set => lFOcos = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Low Frequency oscillation frequency
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Low frequency oscillation frequency")]
|
|
private float lFOfreq = 1.0f;
|
|
|
|
public float LFOfreq
|
|
{
|
|
get => lFOfreq;
|
|
set => lFOfreq = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Low Frequency oscillation amplitude
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Low Frequency oscillation amplitude")]
|
|
private float lFOamp = 0.1f;
|
|
|
|
public float LFOamp
|
|
{
|
|
get => lFOamp;
|
|
set => lFOamp = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reverses dots' orbit rotation path
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Reverses dots' orbit rotation path")]
|
|
private bool reverseOrbit = false;
|
|
|
|
public bool ReverseOrbit
|
|
{
|
|
get => reverseOrbit;
|
|
set => reverseOrbit = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inverts dots' position in orbit
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Inverts dots' position in orbit")]
|
|
private bool invertOrbitOffset = false;
|
|
|
|
public bool InvertOrbitOffset
|
|
{
|
|
get => invertOrbitOffset;
|
|
set => invertOrbitOffset = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Multiplier to dot's rotation calculation
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Multiplier to dot's rotation calculation")]
|
|
private float dotSpinMultiplier = 0.3f;
|
|
|
|
public float DotSpinMultiplier
|
|
{
|
|
get => dotSpinMultiplier;
|
|
set => dotSpinMultiplier = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Multiplier to dot's scale calculation
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("Multiplier to dot's scale calculation")]
|
|
private float dotScaleMultipler = 0.0f;
|
|
|
|
public float DotScaleMultipler
|
|
{
|
|
get => dotScaleMultipler;
|
|
set => dotScaleMultipler = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// When enabled, the dot scale uses Cosine to determine scale with including <see cref="dotSetScale"/>.
|
|
/// Otherwise, it will use Sine.
|
|
/// </summary>
|
|
[SerializeField]
|
|
[Tooltip("When enabled, the dot scale uses Cosine to determine scale with including 'dotSetScale'. Otherwise, it will use Sine.")]
|
|
private bool sinCosSplitScale = false;
|
|
|
|
public bool SinCosSplitScale
|
|
{
|
|
get => sinCosSplitScale;
|
|
set => sinCosSplitScale = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates the time cycle for the trigonometric functions
|
|
/// </summary>
|
|
private float Cycles
|
|
{
|
|
get
|
|
{
|
|
if (reverseOrbit)
|
|
{
|
|
return (frequency < 0.0f) ? (Time.time / 0.000001f) * -1.0f : (Time.time / frequency) * -1.0f;
|
|
}
|
|
else
|
|
{
|
|
return (frequency < 0.0f) ? Time.time / 0.000001f : Time.time / frequency;
|
|
}
|
|
}
|
|
}
|
|
|
|
private float degPerSec;
|
|
|
|
private Vector3 parentNewPos = Vector3.zero;
|
|
|
|
private Transform dot01;
|
|
private Vector3 dot01NewPos = Vector3.zero;
|
|
|
|
private Transform dot02;
|
|
private Vector3 dot02NewPos = Vector3.zero;
|
|
|
|
private const float tau = Mathf.PI * 2.0f;
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (dot01 == null)
|
|
{
|
|
dot01 = gameObject.transform.GetChild(0);
|
|
}
|
|
|
|
if (dot02 == null)
|
|
{
|
|
dot02 = gameObject.transform.GetChild(1);
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
degPerSec = Time.deltaTime * 360f;
|
|
|
|
AnimateParent();
|
|
AnimateDotTransforms();
|
|
}
|
|
|
|
private void AnimateParent()
|
|
{
|
|
float cosX = Mathf.Cos(Cycles * tau) * amplitude;
|
|
float sinY = Mathf.Sin(Cycles * tau) * amplitude;
|
|
|
|
if (invertOrbitOffset == true)
|
|
{
|
|
cosX = -cosX;
|
|
sinY = -sinY;
|
|
}
|
|
|
|
parentNewPos.Set(cosX, sinY, 0f);
|
|
transform.localPosition = parentNewPos;
|
|
|
|
if (lFOsin == true)
|
|
{
|
|
dotSpinMultiplier = Mathf.Sin(Time.time * lFOfreq) * lFOamp;
|
|
}
|
|
else if (lFOcos == true)
|
|
{
|
|
dotSpinMultiplier = Mathf.Cos(Time.time * lFOfreq) * lFOamp;
|
|
}
|
|
|
|
transform.Rotate(Vector3.forward * (degPerSec * dotSpinMultiplier));
|
|
|
|
}
|
|
|
|
private void AnimateDotTransforms()
|
|
{
|
|
// Set dot groups' scale
|
|
float sinScaleCalc = dotSetScale + Mathf.Sin(Cycles * tau / 2) * dotScaleMultipler;
|
|
float cosScaleCalc = dotSetScale + Mathf.Cos(Cycles * tau / 2) * dotScaleMultipler;
|
|
|
|
if (sinCosSplitScale == true)
|
|
{
|
|
dot01NewPos.Set(cosScaleCalc, cosScaleCalc, cosScaleCalc);
|
|
}
|
|
else
|
|
{
|
|
dot01NewPos.Set(sinScaleCalc, sinScaleCalc, sinScaleCalc);
|
|
}
|
|
|
|
dot01.localScale = dot01NewPos;
|
|
|
|
dot02NewPos.Set(sinScaleCalc, sinScaleCalc, sinScaleCalc);
|
|
dot02.localScale = dot02NewPos;
|
|
|
|
// Set dot groups' position Offset from Parent-Null Center
|
|
dot01NewPos.Set(dotOffset, dotOffset, 0f);
|
|
dot02NewPos.Set(-dotOffset, -dotOffset, 0f);
|
|
|
|
dot01.transform.localPosition = dot01NewPos;
|
|
dot02.transform.localPosition = dot02NewPos;
|
|
}
|
|
}
|
|
}
|