Move third party assets to ThirdParty folder
This commit is contained in:
718
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrAnimatedTransform.cs
vendored
Normal file
718
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrAnimatedTransform.cs
vendored
Normal file
@@ -0,0 +1,718 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrAnimatedTransform.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using System;
|
||||
using UltimateXR.Animation.Interpolation;
|
||||
using UltimateXR.Core.Components;
|
||||
using UltimateXR.Extensions.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UltimateXR.Animation.Transforms
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that allows to animate transforms on objects or even camera properties. Both at runtime through scripting
|
||||
/// or at edit time through the inspector properties.
|
||||
/// </summary>
|
||||
public sealed class UxrAnimatedTransform : UxrComponent
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] private UxrAnimationMode _translationMode;
|
||||
[SerializeField] private UxrTransformTranslationSpace _translationSpace;
|
||||
[SerializeField] private Vector3 _translationSpeed;
|
||||
[SerializeField] private Vector3 _translationStart;
|
||||
[SerializeField] private Vector3 _translationEnd;
|
||||
[SerializeField] private bool _translationUseUnscaledTime;
|
||||
[SerializeField] private UxrInterpolationSettings _translationInterpolationSettings = new UxrInterpolationSettings();
|
||||
[SerializeField] private UxrAnimationMode _rotationMode;
|
||||
[SerializeField] private UxrTransformRotationSpace _rotationSpace;
|
||||
[SerializeField] private Vector3 _eulerSpeed;
|
||||
[SerializeField] private Vector3 _eulerStart;
|
||||
[SerializeField] private Vector3 _eulerEnd;
|
||||
[SerializeField] private bool _rotationUseUnscaledTime;
|
||||
[SerializeField] private UxrInterpolationSettings _rotationInterpolationSettings = new UxrInterpolationSettings();
|
||||
[SerializeField] private UxrAnimationMode _scalingMode;
|
||||
[SerializeField] private Vector3 _scalingSpeed;
|
||||
[SerializeField] private Vector3 _scalingStart;
|
||||
[SerializeField] private Vector3 _scalingEnd;
|
||||
[SerializeField] private bool _scalingUseUnscaledTime;
|
||||
[SerializeField] private UxrInterpolationSettings _scalingInterpolationSettings = new UxrInterpolationSettings();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Types & Data
|
||||
|
||||
/// <summary>
|
||||
/// Event called when the translation animation finished. This only applies to translation animations that end.
|
||||
/// </summary>
|
||||
public event Action TranslationFinished;
|
||||
|
||||
/// <summary>
|
||||
/// Event called when the rotation animation finished. This only applies to rotation animations that end.
|
||||
/// </summary>
|
||||
public event Action RotationFinished;
|
||||
|
||||
/// <summary>
|
||||
/// Event called when the scaling animation finished. This only applies to scaling animations that end.
|
||||
/// </summary>
|
||||
public event Action ScalingFinished;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the translation interpolation curve finished.
|
||||
/// If no translation interpolation curve was started it will return false.
|
||||
/// </summary>
|
||||
public bool HasTranslationFinished { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the rotation interpolation curve finished.
|
||||
/// If no rotation interpolation curve was started it will return false.
|
||||
/// </summary>
|
||||
public bool HasRotationFinished { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the scaling interpolation curve finished.
|
||||
/// If no scaling interpolation curve was started it will return false.
|
||||
/// </summary>
|
||||
public bool HasScalingFinished { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Starts a translation at a constant speed
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to apply the translation to</param>
|
||||
/// <param name="space">The space where the translation takes place</param>
|
||||
/// <param name="speed">The translation speed (units per second in X/Y/Z axes)</param>
|
||||
/// <param name="useUnscaledTime">
|
||||
/// If it is true then <see cref="Time.unscaledTime" /> will be used to count seconds. By default it is false meaning
|
||||
/// <see cref="Time.time" /> will be used instead.
|
||||
/// <see cref="Time.time" /> is affected by <see cref="Time.timeScale" /> which in many cases is used for application
|
||||
/// pauses or bullet-time effects, while <see cref="Time.unscaledTime" /> is not.
|
||||
/// </param>
|
||||
/// <returns>The animation component</returns>
|
||||
public static UxrAnimatedTransform Translate(GameObject gameObject, UxrTransformTranslationSpace space, Vector3 speed, bool useUnscaledTime = false)
|
||||
{
|
||||
UxrAnimatedTransform component = gameObject.GetOrAddComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (component)
|
||||
{
|
||||
component._translationMode = UxrAnimationMode.Speed;
|
||||
component._translationSpace = space;
|
||||
component._translationSpeed = speed;
|
||||
component._translationInterpolationSettings.UseUnscaledTime = useUnscaledTime;
|
||||
component.HasTranslationFinished = false;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a rotation at a constant speed
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to apply the rotation to</param>
|
||||
/// <param name="space">The space where the rotation takes place</param>
|
||||
/// <param name="speed">The rotation speed (degrees per second, per component X/Y/Z)</param>
|
||||
/// <param name="useUnscaledTime">
|
||||
/// If it is true then Time.unscaledTime will be used
|
||||
/// to count seconds. By default it is false meaning Time.time will be used instead.
|
||||
/// Time.time is affected by Time.timeScale which in many cases is used for application pauses
|
||||
/// or bullet-time effects, while Time.unscaledTime is not.
|
||||
/// </param>
|
||||
/// <returns>The animation component</returns>
|
||||
public static UxrAnimatedTransform Rotate(GameObject gameObject, UxrTransformRotationSpace space, Vector3 speed, bool useUnscaledTime = false)
|
||||
{
|
||||
UxrAnimatedTransform component = gameObject.GetOrAddComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (component)
|
||||
{
|
||||
component._rotationMode = UxrAnimationMode.Speed;
|
||||
component._rotationSpace = space;
|
||||
component._useEuler = true;
|
||||
component._eulerSpeed = speed;
|
||||
component._rotationInterpolationSettings.UseUnscaledTime = useUnscaledTime;
|
||||
component.HasRotationFinished = false;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts scaling at a constant speed
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to apply the scaling to</param>
|
||||
/// <param name="speed">The scaling speed (units per second in X/Y/Z axes)</param>
|
||||
/// <param name="useUnscaledTime">
|
||||
/// If it is true then Time.unscaledTime will be used
|
||||
/// to count seconds. By default it is false meaning Time.time will be used instead.
|
||||
/// Time.time is affected by Time.timeScale which in many cases is used for application pauses
|
||||
/// or bullet-time effects, while Time.unscaledTime is not.
|
||||
/// </param>
|
||||
/// <returns>The animation component</returns>
|
||||
public static UxrAnimatedTransform Scale(GameObject gameObject, Vector3 speed, bool useUnscaledTime = false)
|
||||
{
|
||||
UxrAnimatedTransform component = gameObject.GetOrAddComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (component)
|
||||
{
|
||||
component._scalingMode = UxrAnimationMode.Speed;
|
||||
component._scalingSpeed = speed;
|
||||
component._scalingInterpolationSettings.UseUnscaledTime = useUnscaledTime;
|
||||
component.HasScalingFinished = false;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a translation using an interpolation curve
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to apply the translation to</param>
|
||||
/// <param name="space">The space where the translation takes place</param>
|
||||
/// <param name="startPos">The start position</param>
|
||||
/// <param name="endPos">The end position</param>
|
||||
/// <param name="settings">The interpolation settings with the curve parameters</param>
|
||||
/// <param name="finishedCallback">
|
||||
/// Optional callback called when the animation finished. Only applies to non-looping
|
||||
/// animations.
|
||||
/// </param>
|
||||
/// <returns>The animation component</returns>
|
||||
public static UxrAnimatedTransform PositionInterpolation(GameObject gameObject, UxrTransformTranslationSpace space, Vector3 startPos, Vector3 endPos, UxrInterpolationSettings settings, Action finishedCallback = null)
|
||||
{
|
||||
UxrAnimatedTransform component = gameObject.GetOrAddComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (component)
|
||||
{
|
||||
component._translationMode = UxrAnimationMode.Interpolate;
|
||||
component._translationSpace = space;
|
||||
component._translationStart = startPos;
|
||||
component._translationEnd = endPos;
|
||||
component._translationInterpolationSettings = settings;
|
||||
component._translationFinishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a rotation using an interpolation curve
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to apply the rotation to</param>
|
||||
/// <param name="space">The space where the rotation takes place</param>
|
||||
/// <param name="startEuler">The start Euler angles</param>
|
||||
/// <param name="endEuler">The end Euler angles</param>
|
||||
/// <param name="settings">The interpolation settings with the curve parameters</param>
|
||||
/// <param name="finishedCallback">
|
||||
/// Optional callback called when the animation finished. Only applies to non-looping
|
||||
/// animations.
|
||||
/// </param>
|
||||
/// <returns>The animation component</returns>
|
||||
public static UxrAnimatedTransform RotationInterpolation(GameObject gameObject, UxrTransformRotationSpace space, Vector3 startEuler, Vector3 endEuler, UxrInterpolationSettings settings, Action finishedCallback = null)
|
||||
{
|
||||
UxrAnimatedTransform component = gameObject.GetOrAddComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (component)
|
||||
{
|
||||
component._rotationMode = UxrAnimationMode.Interpolate;
|
||||
component._useEuler = true;
|
||||
component._rotationSpace = space;
|
||||
component._eulerStart = startEuler;
|
||||
component._eulerEnd = endEuler;
|
||||
component._rotationInterpolationSettings = settings;
|
||||
component._rotationFinishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a rotation using an interpolation curve
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to apply the rotation to</param>
|
||||
/// <param name="space">The space where the rotation takes place</param>
|
||||
/// <param name="startRot">The start Quaternion orientation</param>
|
||||
/// <param name="endRot">The end Quaternion orientation</param>
|
||||
/// <param name="settings">The interpolation settings with the curve parameters</param>
|
||||
/// <param name="finishedCallback">
|
||||
/// Optional callback called when the animation finished. Only applies to non-looping
|
||||
/// animations.
|
||||
/// </param>
|
||||
/// <returns>The animation component</returns>
|
||||
public static UxrAnimatedTransform RotationInterpolation(GameObject gameObject, UxrTransformRotationSpace space, Quaternion startRot, Quaternion endRot, UxrInterpolationSettings settings, Action finishedCallback = null)
|
||||
{
|
||||
UxrAnimatedTransform component = gameObject.GetOrAddComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (component)
|
||||
{
|
||||
component._rotationMode = UxrAnimationMode.Interpolate;
|
||||
component._useEuler = false;
|
||||
component._rotationSpace = space;
|
||||
component._quaternionStart = startRot;
|
||||
component._quaternionEnd = endRot;
|
||||
component._rotationInterpolationSettings = settings;
|
||||
component._rotationFinishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts scaling using an interpolation curve
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to apply the scaling to</param>
|
||||
/// <param name="startScale">The start scale</param>
|
||||
/// <param name="endScale">The end scale</param>
|
||||
/// <param name="settings">The interpolation settings with the curve parameters</param>
|
||||
/// <param name="finishedCallback">
|
||||
/// Optional callback called when the animation finished. Only applies to non-looping
|
||||
/// animations.
|
||||
/// </param>
|
||||
/// <returns>The animation component</returns>
|
||||
public static UxrAnimatedTransform ScalingInterpolation(GameObject gameObject, Vector3 startScale, Vector3 endScale, UxrInterpolationSettings settings, Action finishedCallback = null)
|
||||
{
|
||||
UxrAnimatedTransform component = gameObject.GetOrAddComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (component)
|
||||
{
|
||||
component._scalingMode = UxrAnimationMode.Interpolate;
|
||||
component._scalingStart = startScale;
|
||||
component._scalingEnd = endScale;
|
||||
component._scalingInterpolationSettings = settings;
|
||||
component._scalingFinishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the position/rotation/scaling animations on an object if it has an <see cref="UxrAnimatedTransform" />
|
||||
/// component currently attached.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">Target GameObject</param>
|
||||
/// <param name="restoreOriginal">
|
||||
/// Whether to reset the position/rotation/scale values to the state before the animation
|
||||
/// started
|
||||
/// </param>
|
||||
public static void StopAll(GameObject gameObject, bool restoreOriginal = true)
|
||||
{
|
||||
UxrAnimatedTransform anim = gameObject.GetComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (anim)
|
||||
{
|
||||
anim.StopAll(restoreOriginal);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the translation animation on an object if it has an <see cref="UxrAnimatedTransform" />
|
||||
/// component currently attached.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">Target GameObject</param>
|
||||
/// <param name="restoreOriginal">Whether to reset the position to the state before the animation started.</param>
|
||||
public static void StopTranslation(GameObject gameObject, bool restoreOriginal = true)
|
||||
{
|
||||
UxrAnimatedTransform anim = gameObject.GetComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (anim)
|
||||
{
|
||||
anim.StopTranslation(restoreOriginal);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the rotation animation on an object if it has an <see cref="UxrAnimatedTransform" />
|
||||
/// component currently attached.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">Target GameObject</param>
|
||||
/// <param name="restoreOriginal">Whether to reset the rotation to the state before the animation started.</param>
|
||||
public static void StopRotation(GameObject gameObject, bool restoreOriginal = true)
|
||||
{
|
||||
UxrAnimatedTransform anim = gameObject.GetComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (anim)
|
||||
{
|
||||
anim.StopRotation(restoreOriginal);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the scaling animation on an object if it has an <see cref="UxrAnimatedTransform" />
|
||||
/// component currently attached.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">Target GameObject</param>
|
||||
/// <param name="restoreOriginal">Whether to reset the scale to the state before the animation started.</param>
|
||||
public static void StopScaling(GameObject gameObject, bool restoreOriginal = true)
|
||||
{
|
||||
UxrAnimatedTransform anim = gameObject.GetComponent<UxrAnimatedTransform>();
|
||||
|
||||
if (anim)
|
||||
{
|
||||
anim.StopScaling(restoreOriginal);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the position/rotation/scaling animations on an object if it has an <see cref="UxrAnimatedTransform" />
|
||||
/// component currently attached.
|
||||
/// </summary>
|
||||
/// <param name="restoreOriginal">
|
||||
/// Whether to reset the position/rotation/scale values to the state before the animation
|
||||
/// started
|
||||
/// </param>
|
||||
public void StopAll(bool restoreOriginal = true)
|
||||
{
|
||||
HasTranslationFinished = true;
|
||||
HasRotationFinished = true;
|
||||
HasScalingFinished = true;
|
||||
|
||||
if (restoreOriginal)
|
||||
{
|
||||
transform.localPosition = _initialLocalPosition;
|
||||
transform.localRotation = _initialLocalRotation;
|
||||
transform.localScale = _initialLocalScale;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the translation animation on an object if it has an <see cref="UxrAnimatedTransform" />
|
||||
/// component currently attached.
|
||||
/// </summary>
|
||||
/// <param name="restoreOriginal">Whether to reset the position to the state before the animation started.</param>
|
||||
public void StopTranslation(bool restoreOriginal = true)
|
||||
{
|
||||
HasTranslationFinished = true;
|
||||
|
||||
if (restoreOriginal)
|
||||
{
|
||||
transform.localPosition = _initialLocalPosition;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the rotation animation on an object if it has an <see cref="UxrAnimatedTransform" />
|
||||
/// component currently attached.
|
||||
/// </summary>
|
||||
/// <param name="restoreOriginal">Whether to reset the rotation to the state before the animation started.</param>
|
||||
public void StopRotation(bool restoreOriginal = true)
|
||||
{
|
||||
HasRotationFinished = true;
|
||||
|
||||
if (restoreOriginal)
|
||||
{
|
||||
transform.localRotation = _initialLocalRotation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the scaling animation on an object if it has an <see cref="UxrAnimatedTransform" />
|
||||
/// component currently attached.
|
||||
/// </summary>
|
||||
/// <param name="restoreOriginal">Whether to reset the scale to the state before the animation started.</param>
|
||||
public void StopScaling(bool restoreOriginal = true)
|
||||
{
|
||||
HasScalingFinished = true;
|
||||
|
||||
if (restoreOriginal)
|
||||
{
|
||||
transform.localScale = _initialLocalScale;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Stores some initial values.
|
||||
/// </summary>
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_scaleTimer = 0.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called each time the object is enabled. Reset timer and set the curve state to unfinished.
|
||||
/// The first time it's called it stores the original transform values.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
_startTimeTranslation = GetCurrentTime(_translationUseUnscaledTime, _translationMode, _translationInterpolationSettings);
|
||||
_startTimeRotation = GetCurrentTime(_rotationUseUnscaledTime, _rotationMode, _rotationInterpolationSettings);
|
||||
_startTimeScaling = GetCurrentTime(_scalingUseUnscaledTime, _scalingMode, _scalingInterpolationSettings);
|
||||
|
||||
HasTranslationFinished = false;
|
||||
HasRotationFinished = false;
|
||||
HasScalingFinished = false;
|
||||
|
||||
if (!_originalValuesStored)
|
||||
{
|
||||
_originalValuesStored = true;
|
||||
_initialLocalPosition = transform.localPosition;
|
||||
_initialLocalRotation = transform.localRotation;
|
||||
_initialLocalScale = transform.localScale;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs transform updates
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
// Translation ////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (!HasTranslationFinished)
|
||||
{
|
||||
switch (_translationMode)
|
||||
{
|
||||
case UxrAnimationMode.None: break;
|
||||
|
||||
case UxrAnimationMode.Speed:
|
||||
{
|
||||
Vector3 xAxis = Vector3.right;
|
||||
Vector3 yAxis = Vector3.up;
|
||||
Vector3 zAxis = Vector3.forward;
|
||||
|
||||
if (_translationSpace == UxrTransformTranslationSpace.Local)
|
||||
{
|
||||
xAxis = transform.right;
|
||||
yAxis = transform.up;
|
||||
zAxis = transform.forward;
|
||||
}
|
||||
else if (_translationSpace == UxrTransformTranslationSpace.Parent)
|
||||
{
|
||||
if (transform.parent != null)
|
||||
{
|
||||
xAxis = transform.parent.right;
|
||||
yAxis = transform.parent.up;
|
||||
zAxis = transform.parent.forward;
|
||||
}
|
||||
}
|
||||
|
||||
float deltaTime = GetDeltaTime(_translationUseUnscaledTime);
|
||||
transform.Translate(_translationSpeed.x * deltaTime * xAxis + _translationSpeed.y * deltaTime * yAxis + _translationSpeed.z * deltaTime * zAxis, Space.World);
|
||||
break;
|
||||
}
|
||||
|
||||
case UxrAnimationMode.Interpolate:
|
||||
{
|
||||
float time = GetCurrentTime(_translationUseUnscaledTime, _translationMode, _translationInterpolationSettings) - _startTimeTranslation;
|
||||
Vector3 position = UxrInterpolator.Interpolate(_translationStart, _translationEnd, time, _translationInterpolationSettings);
|
||||
|
||||
switch (_translationSpace)
|
||||
{
|
||||
case UxrTransformTranslationSpace.World:
|
||||
transform.position = position;
|
||||
break;
|
||||
|
||||
case UxrTransformTranslationSpace.Local:
|
||||
transform.localPosition = position;
|
||||
break;
|
||||
|
||||
case UxrTransformTranslationSpace.Parent:
|
||||
|
||||
if (transform.parent == null)
|
||||
{
|
||||
transform.position = position;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = transform.parent.position + transform.parent.GetScaledVector(position);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default: throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
if (_translationInterpolationSettings.CheckInterpolationHasFinished(time))
|
||||
{
|
||||
HasTranslationFinished = true;
|
||||
OnTranslationFinished();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UxrAnimationMode.Noise: // TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Rotation ////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (!HasRotationFinished)
|
||||
{
|
||||
switch (_rotationMode)
|
||||
{
|
||||
case UxrAnimationMode.None: break;
|
||||
|
||||
case UxrAnimationMode.Speed:
|
||||
{
|
||||
float deltaTime = GetDeltaTime(_rotationUseUnscaledTime);
|
||||
transform.Rotate(_eulerSpeed * deltaTime, _rotationSpace == UxrTransformRotationSpace.Local ? Space.Self : Space.World);
|
||||
break;
|
||||
}
|
||||
|
||||
case UxrAnimationMode.Interpolate:
|
||||
{
|
||||
float time = GetCurrentTime(_rotationUseUnscaledTime, _rotationMode, _rotationInterpolationSettings) - _startTimeRotation;
|
||||
Quaternion rotation = Quaternion.identity;
|
||||
|
||||
if (_useEuler)
|
||||
{
|
||||
Vector3 euler = UxrInterpolator.Interpolate(_eulerStart, _eulerEnd, time, _rotationInterpolationSettings);
|
||||
rotation = Quaternion.Euler(euler);
|
||||
}
|
||||
else
|
||||
{
|
||||
rotation = UxrInterpolator.Interpolate(_quaternionStart, _quaternionEnd, time, _rotationInterpolationSettings);
|
||||
}
|
||||
|
||||
switch (_rotationSpace)
|
||||
{
|
||||
case UxrTransformRotationSpace.World:
|
||||
transform.rotation = rotation;
|
||||
break;
|
||||
|
||||
case UxrTransformRotationSpace.Local:
|
||||
transform.localRotation = rotation;
|
||||
break;
|
||||
|
||||
default: throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
if (_rotationInterpolationSettings.CheckInterpolationHasFinished(time))
|
||||
{
|
||||
HasRotationFinished = true;
|
||||
OnRotationFinished();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UxrAnimationMode.Noise:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Scaling /////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (!HasScalingFinished)
|
||||
{
|
||||
switch (_scalingMode)
|
||||
{
|
||||
case UxrAnimationMode.None: break;
|
||||
|
||||
case UxrAnimationMode.Speed:
|
||||
_scaleTimer += GetDeltaTime(_scalingUseUnscaledTime);
|
||||
transform.localScale = _initialLocalScale + Vector3.Scale(_initialLocalScale, _scalingSpeed * _scaleTimer);
|
||||
break;
|
||||
|
||||
case UxrAnimationMode.Interpolate:
|
||||
{
|
||||
float time = GetCurrentTime(_scalingUseUnscaledTime, _scalingMode, _scalingInterpolationSettings) - _startTimeScaling;
|
||||
transform.localScale = UxrInterpolator.Interpolate(_scalingStart, _scalingEnd, time, _scalingInterpolationSettings);
|
||||
|
||||
if (_scalingInterpolationSettings.CheckInterpolationHasFinished(time))
|
||||
{
|
||||
HasScalingFinished = true;
|
||||
OnScalingFinished();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UxrAnimationMode.Noise:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Trigger Methods
|
||||
|
||||
private void OnTranslationFinished()
|
||||
{
|
||||
TranslationFinished?.Invoke();
|
||||
_translationFinishedCallback?.Invoke();
|
||||
}
|
||||
|
||||
private void OnRotationFinished()
|
||||
{
|
||||
RotationFinished?.Invoke();
|
||||
_rotationFinishedCallback?.Invoke();
|
||||
}
|
||||
|
||||
private void OnScalingFinished()
|
||||
{
|
||||
ScalingFinished?.Invoke();
|
||||
_scalingFinishedCallback?.Invoke();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current delta time depending on the timing used.
|
||||
/// </summary>
|
||||
/// <param name="useUnscaledTime">Whether to use the unscaled delta time or not</param>
|
||||
/// <returns>Correct delta time value to use</returns>
|
||||
private float GetDeltaTime(bool useUnscaledTime)
|
||||
{
|
||||
return useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current time in seconds. It computes the correct time, either <see cref="Time.unscaledTime" /> or
|
||||
/// <see cref="Time.time" />, depending on the animation configuration.
|
||||
/// </summary>
|
||||
/// <param name="useUnscaledTime">The default value if no interpolation is set up</param>
|
||||
/// <param name="mode">Animation mode</param>
|
||||
/// <param name="settings">
|
||||
/// The interpolation settings to use if animation is set to
|
||||
/// <see cref="UxrAnimationMode.Interpolate" />.
|
||||
/// </param>
|
||||
/// <returns>Correct time value to use</returns>
|
||||
private float GetCurrentTime(bool useUnscaledTime, UxrAnimationMode mode, UxrInterpolationSettings settings)
|
||||
{
|
||||
if (settings != null && mode == UxrAnimationMode.Interpolate)
|
||||
{
|
||||
return settings.UseUnscaledTime ? Time.unscaledTime : Time.time;
|
||||
}
|
||||
|
||||
return useUnscaledTime ? Time.unscaledTime : Time.time;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Types & Data
|
||||
|
||||
private bool _useEuler = true;
|
||||
private Quaternion _quaternionStart;
|
||||
private Quaternion _quaternionEnd;
|
||||
private float _scaleTimer;
|
||||
|
||||
private Action _translationFinishedCallback;
|
||||
private Action _rotationFinishedCallback;
|
||||
private Action _scalingFinishedCallback;
|
||||
|
||||
private bool _originalValuesStored;
|
||||
private Vector3 _initialLocalPosition;
|
||||
private Quaternion _initialLocalRotation;
|
||||
private Vector3 _initialLocalScale;
|
||||
|
||||
private float _startTimeTranslation;
|
||||
private float _startTimeRotation;
|
||||
private float _startTimeScaling;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
13
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrAnimatedTransform.cs.meta
vendored
Normal file
13
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrAnimatedTransform.cs.meta
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce7d381cb12d2be46a9bd814aa9e52a5
|
||||
timeCreated: 1516185390
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
355
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAt.cs
vendored
Normal file
355
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAt.cs
vendored
Normal file
@@ -0,0 +1,355 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrLookAt.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.Core;
|
||||
using UltimateXR.Core.Components;
|
||||
using UltimateXR.Core.Math;
|
||||
using UltimateXR.Extensions.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UltimateXR.Animation.Transforms
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that allows to continuously orientate an object looking at a specified point or along an axis.
|
||||
/// </summary>
|
||||
public sealed class UxrLookAt : UxrComponent
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] private UxrLookAtMode _mode = UxrLookAtMode.Target;
|
||||
[SerializeField] private Transform _target;
|
||||
[SerializeField] private UxrAxis _lookAxis = UxrAxis.Z;
|
||||
[SerializeField] private UxrAxis _upAxis = UxrAxis.Y;
|
||||
[SerializeField] private UxrAxis _matchDirection = UxrAxis.Z;
|
||||
[SerializeField] private bool _allowRotateAroundUp = true;
|
||||
[SerializeField] private bool _allowRotateAroundRight = true;
|
||||
[SerializeField] private bool _invertedLookAxis;
|
||||
[SerializeField] private bool _onlyOnce;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Makes an object look at a specific target.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The object that will look at the target</param>
|
||||
/// <param name="target">The target</param>
|
||||
/// <param name="lookAxis">The object look axis</param>
|
||||
/// <param name="upAxis">The object up vector</param>
|
||||
/// <param name="allowRotateAroundObjectUp">
|
||||
/// Should the lookAt alter the rotation around the vertical axis?
|
||||
/// </param>
|
||||
/// <param name="allowRotateAroundObjectRight">
|
||||
/// Should the lookAt alter the rotation around the horizontal axis?
|
||||
/// </param>
|
||||
/// <param name="invertedLookAxis">
|
||||
/// If true, the target's look axis will try to point at the opposite direction where the target is. By default this is
|
||||
/// false, meaning the look vector will try to point at the target
|
||||
/// </param>
|
||||
public static void MakeLookAt(GameObject gameObject,
|
||||
Transform target,
|
||||
UxrAxis lookAxis,
|
||||
UxrAxis upAxis,
|
||||
bool allowRotateAroundObjectUp = true,
|
||||
bool allowRotateAroundObjectRight = true,
|
||||
bool invertedLookAxis = false,
|
||||
bool onlyOnce = false)
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UxrLookAt lookAtComponent = gameObject.GetOrAddComponent<UxrLookAt>();
|
||||
|
||||
lookAtComponent._mode = UxrLookAtMode.Target;
|
||||
lookAtComponent._target = target;
|
||||
lookAtComponent._lookAxis = lookAxis;
|
||||
lookAtComponent._upAxis = upAxis;
|
||||
lookAtComponent._allowRotateAroundUp = allowRotateAroundObjectUp;
|
||||
lookAtComponent._allowRotateAroundRight = allowRotateAroundObjectRight;
|
||||
lookAtComponent._invertedLookAxis = invertedLookAxis;
|
||||
lookAtComponent._onlyOnce = onlyOnce;
|
||||
|
||||
lookAtComponent.PerformLookAt(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes an object look along a specific target's direction.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The object that will look at the target</param>
|
||||
/// <param name="target">The target</param>
|
||||
/// <param name="direction">The target axis</param>
|
||||
/// <param name="lookAxis">The object look axis</param>
|
||||
/// <param name="upAxis">The object up vector</param>
|
||||
/// <param name="allowRotateAroundUp">
|
||||
/// Should the lookAt alter the rotation around the vertical axis?
|
||||
/// </param>
|
||||
/// <param name="allowRotateAroundRight">
|
||||
/// Should the lookAt alter the rotation around the horizontal axis?
|
||||
/// </param>
|
||||
/// <param name="invertedForwardAxis">
|
||||
/// If true, the target's forward axis will try to point at the opposite direction where the target is. By default this
|
||||
/// is false, meaning the forward vector will try to point at the target
|
||||
/// </param>
|
||||
/// <param name="onlyOnce">Whether to perform the look at only once</param>
|
||||
public static void MatchTargetDirection(GameObject gameObject,
|
||||
Transform target,
|
||||
UxrAxis direction,
|
||||
UxrAxis lookAxis,
|
||||
UxrAxis upAxis,
|
||||
bool allowRotateAroundUp = true,
|
||||
bool allowRotateAroundRight = true,
|
||||
bool invertedForwardAxis = false,
|
||||
bool onlyOnce = false)
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UxrLookAt lookAtComponent = gameObject.GetOrAddComponent<UxrLookAt>();
|
||||
|
||||
lookAtComponent._mode = UxrLookAtMode.MatchTargetDirection;
|
||||
lookAtComponent._target = target;
|
||||
lookAtComponent._matchDirection = direction;
|
||||
lookAtComponent._lookAxis = lookAxis;
|
||||
lookAtComponent._upAxis = upAxis;
|
||||
lookAtComponent._allowRotateAroundUp = allowRotateAroundUp;
|
||||
lookAtComponent._allowRotateAroundRight = allowRotateAroundRight;
|
||||
lookAtComponent._invertedLookAxis = invertedForwardAxis;
|
||||
lookAtComponent._onlyOnce = onlyOnce;
|
||||
|
||||
lookAtComponent.PerformLookAt(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes an object look in a specific direction.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The object that will look at the given direction</param>
|
||||
/// <param name="direction">The world direction that the object will look at</param>
|
||||
/// <param name="lookAxis">The object look axis</param>
|
||||
/// <param name="upAxis">The object up vector</param>
|
||||
/// <param name="allowRotateAroundObjectUp">
|
||||
/// Should the lookAt alter the rotation around the vertical axis?
|
||||
/// </param>
|
||||
/// <param name="allowRotateAroundObjectRight">
|
||||
/// Should the lookAt alter the rotation around the horizontal axis?
|
||||
/// </param>
|
||||
/// <param name="invertedForwardAxis">
|
||||
/// If true, the target's forward axis will try to point at the opposite direction where the target is. By default this
|
||||
/// is false, meaning the forward vector will try to point at the target
|
||||
/// </param>
|
||||
/// <param name="onlyOnce">Whether to perform the look at only once</param>
|
||||
public static void MatchWorldDirection(GameObject gameObject,
|
||||
UxrAxis direction,
|
||||
UxrAxis lookAxis,
|
||||
UxrAxis upAxis,
|
||||
bool allowRotateAroundUp = true,
|
||||
bool allowRotateAroundRight = true,
|
||||
bool invertedForwardAxis = false,
|
||||
bool onlyOnce = false)
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UxrLookAt lookAtComponent = gameObject.GetOrAddComponent<UxrLookAt>();
|
||||
|
||||
lookAtComponent._mode = UxrLookAtMode.MatchWorldDirection;
|
||||
lookAtComponent._matchDirection = direction;
|
||||
lookAtComponent._lookAxis = lookAxis;
|
||||
lookAtComponent._upAxis = upAxis;
|
||||
lookAtComponent._allowRotateAroundUp = allowRotateAroundUp;
|
||||
lookAtComponent._allowRotateAroundRight = allowRotateAroundRight;
|
||||
lookAtComponent._invertedLookAxis = invertedForwardAxis;
|
||||
lookAtComponent._onlyOnce = onlyOnce;
|
||||
|
||||
lookAtComponent.PerformLookAt(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an UxrLookAt component if it exists.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to remove the component from</param>
|
||||
public static void RemoveLookAt(GameObject gameObject)
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UxrLookAt lookAtComponent = gameObject.GetComponent<UxrLookAt>();
|
||||
|
||||
if (lookAtComponent)
|
||||
{
|
||||
Destroy(lookAtComponent);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces to execute an instant LookAt.
|
||||
/// </summary>
|
||||
public void ForceLookAt()
|
||||
{
|
||||
PerformLookAt(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to events.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
UxrManager.AvatarsUpdated += UxrManager_AvatarsUpdated;
|
||||
|
||||
_initialLocalRotation = gameObject.transform.localRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribes from events.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
UxrManager.AvatarsUpdated -= UxrManager_AvatarsUpdated;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handling Methods
|
||||
|
||||
/// <summary>
|
||||
/// Called when the avatars finished updating. Performs the look at.
|
||||
/// </summary>
|
||||
private void UxrManager_AvatarsUpdated()
|
||||
{
|
||||
PerformLookAt(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Performs look at.
|
||||
/// </summary>
|
||||
private static void PerformLookAt(GameObject gameObject,
|
||||
Quaternion initialLocalRotation,
|
||||
UxrLookAtMode mode,
|
||||
Transform target,
|
||||
UxrAxis direction,
|
||||
UxrAxis lookAxis,
|
||||
UxrAxis upAxis,
|
||||
bool allowRotateAroundUp = true,
|
||||
bool allowRotateAroundRight = true,
|
||||
bool invertedForwardAxis = false)
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!allowRotateAroundUp && !allowRotateAroundRight)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 worldDir = Vector3.forward;
|
||||
|
||||
if (mode == UxrLookAtMode.Target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
worldDir = target.position - gameObject.transform.position;
|
||||
}
|
||||
else if (mode == UxrLookAtMode.MatchTargetDirection)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
worldDir = target.TransformDirection(direction);
|
||||
}
|
||||
else if (mode == UxrLookAtMode.MatchWorldDirection)
|
||||
{
|
||||
worldDir = direction;
|
||||
}
|
||||
|
||||
if (invertedForwardAxis)
|
||||
{
|
||||
worldDir = -worldDir;
|
||||
}
|
||||
|
||||
Quaternion sourceRot = TransformExt.GetWorldRotation(gameObject.transform.parent, initialLocalRotation);
|
||||
Quaternion rotation = Quaternion.identity;
|
||||
|
||||
if (allowRotateAroundUp && allowRotateAroundRight)
|
||||
{
|
||||
rotation = Quaternion.FromToRotation(sourceRot * lookAxis, worldDir);
|
||||
}
|
||||
else if (allowRotateAroundUp)
|
||||
{
|
||||
Vector3 axis = sourceRot * upAxis;
|
||||
|
||||
// Project on the up plane
|
||||
worldDir = Vector3.ProjectOnPlane(worldDir, axis);
|
||||
|
||||
float degrees = Vector3.SignedAngle(sourceRot * lookAxis, worldDir, axis);
|
||||
rotation = Quaternion.AngleAxis(degrees, axis);
|
||||
}
|
||||
else if (allowRotateAroundRight)
|
||||
{
|
||||
Vector3 axis = sourceRot * Vector3.Cross(upAxis, lookAxis);
|
||||
|
||||
// Project on the right plane
|
||||
worldDir = Vector3.ProjectOnPlane(worldDir, axis);
|
||||
|
||||
float degrees = Vector3.SignedAngle(sourceRot * lookAxis, worldDir, axis);
|
||||
rotation = Quaternion.AngleAxis(degrees, axis);
|
||||
}
|
||||
|
||||
gameObject.transform.rotation = rotation * sourceRot;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs look at.
|
||||
/// </summary>
|
||||
/// <param name="force">Whether to force the look-at</param>
|
||||
private void PerformLookAt(bool force)
|
||||
{
|
||||
if (_repeat || force)
|
||||
{
|
||||
PerformLookAt(gameObject, _initialLocalRotation, _mode, _target, _matchDirection, _lookAxis, _upAxis, _allowRotateAroundUp, _allowRotateAroundRight, _invertedLookAxis);
|
||||
|
||||
if (_onlyOnce)
|
||||
{
|
||||
_repeat = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Types & Data
|
||||
|
||||
private bool _repeat = true;
|
||||
private Quaternion _initialLocalRotation;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
13
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAt.cs.meta
vendored
Normal file
13
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAt.cs.meta
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3cad3f066ea9fd479a25cc2d4247f5a
|
||||
timeCreated: 1516189266
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
233
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAtLocalAvatar.cs
vendored
Normal file
233
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAtLocalAvatar.cs
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrLookAtLocalAvatar.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.Avatar;
|
||||
using UltimateXR.Core;
|
||||
using UltimateXR.Core.Components;
|
||||
using UltimateXR.Extensions.Unity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UltimateXR.Animation.Transforms
|
||||
{
|
||||
/// <summary>
|
||||
/// Component that allows to continuously orientate an object looking at the local avatar camera.
|
||||
/// If there is no local avatar, it will use the first enabled camera.
|
||||
/// </summary>
|
||||
public class UxrLookAtLocalAvatar : UxrComponent
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] private bool _allowRotateAroundY = true;
|
||||
[SerializeField] private bool _allowRotateAroundX = true;
|
||||
[SerializeField] private bool _invertedForwardAxis;
|
||||
[SerializeField] private bool _onlyOnce;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Types & Data
|
||||
|
||||
/// <summary>
|
||||
/// Should the lookAt alter the rotation around the vertical axis?
|
||||
/// </summary>
|
||||
public bool AllowRotateAroundVerticalAxis
|
||||
{
|
||||
get => _allowRotateAroundY;
|
||||
set => _allowRotateAroundY = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should the lookAt alter the rotation around the horizontal axis?
|
||||
/// </summary>
|
||||
public bool AllowRotateAroundHorizontalAxis
|
||||
{
|
||||
get => _allowRotateAroundX;
|
||||
set => _allowRotateAroundX = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, the target's forward axis will try to point at the opposite direction where the
|
||||
/// avatar is. By default this is false, meaning the forward vector will try to point at
|
||||
/// the avatar.
|
||||
/// </summary>
|
||||
public bool InvertedForwardAxis
|
||||
{
|
||||
get => _invertedForwardAxis;
|
||||
set => _invertedForwardAxis = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, will only perform the lookat the first time it is called. Useful for explosions
|
||||
/// or similar effects in VR.
|
||||
/// </summary>
|
||||
public bool OnlyOnce
|
||||
{
|
||||
get => _onlyOnce;
|
||||
set => _onlyOnce = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Makes an object look at the local avatar continuously over time.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The object that will look at the local avatar</param>
|
||||
/// <param name="allowRotateAroundVerticalAxis">
|
||||
/// Should the lookAt alter the rotation around the vertical axis?
|
||||
/// </param>
|
||||
/// <param name="allowRotateAroundHorizontalAxis">
|
||||
/// Should the lookAt alter the rotation around the horizontal axis?
|
||||
/// </param>
|
||||
/// <param name="invertedForwardAxis">
|
||||
/// If true, the target's forward axis will try to point at the opposite direction where the avatar is. By default this
|
||||
/// is false, meaning the forward vector will try to point at the avatar
|
||||
/// </param>
|
||||
/// <returns>The look-at component</returns>
|
||||
public UxrLookAtLocalAvatar MakeLookAt(GameObject gameObject, bool allowRotateAroundVerticalAxis, bool allowRotateAroundHorizontalAxis, bool invertedForwardAxis)
|
||||
{
|
||||
UxrLookAtLocalAvatar lookAtComponent = gameObject.GetOrAddComponent<UxrLookAtLocalAvatar>();
|
||||
|
||||
lookAtComponent._allowRotateAroundY = allowRotateAroundVerticalAxis;
|
||||
lookAtComponent._allowRotateAroundX = allowRotateAroundHorizontalAxis;
|
||||
lookAtComponent._invertedForwardAxis = invertedForwardAxis;
|
||||
|
||||
return lookAtComponent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes an object look at the local avatar a single time.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The object that will look at the local avatar</param>
|
||||
/// <param name="allowRotateAroundVerticalAxis">
|
||||
/// Should the lookAt alter the rotation around the vertical axis?
|
||||
/// </param>
|
||||
/// <param name="allowRotateAroundHorizontalAxis">
|
||||
/// Should the lookAt alter the rotation around the horizontal axis?
|
||||
/// </param>
|
||||
/// <param name="invertedForwardAxis">
|
||||
/// If true, the target's forward axis will try to point at the opposite direction where the avatar is. By default this
|
||||
/// is false, meaning the forward vector will try to point at the avatar
|
||||
/// </param>
|
||||
public static void MakeLookAtOnlyOnce(GameObject gameObject, bool allowRotateAroundVerticalAxis, bool allowRotateAroundHorizontalAxis, bool invertedForwardAxis)
|
||||
{
|
||||
PerformLookAt(gameObject.transform, allowRotateAroundVerticalAxis, allowRotateAroundHorizontalAxis, invertedForwardAxis);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an UxrLookAtLocalAvatar component if it exists.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to remove the component from</param>
|
||||
public static void RemoveLookAt(GameObject gameObject)
|
||||
{
|
||||
if (gameObject)
|
||||
{
|
||||
UxrLookAtLocalAvatar lookAtComponent = gameObject.GetComponent<UxrLookAtLocalAvatar>();
|
||||
|
||||
if (lookAtComponent)
|
||||
{
|
||||
Destroy(lookAtComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to events.
|
||||
/// </summary>
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
UxrManager.AvatarsUpdated += UxrManager_AvatarsUpdated;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribes from events.
|
||||
/// </summary>
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
UxrManager.AvatarsUpdated -= UxrManager_AvatarsUpdated;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handling Methods
|
||||
|
||||
/// <summary>
|
||||
/// Called after avatars are updated. Performs look at.
|
||||
/// </summary>
|
||||
private void UxrManager_AvatarsUpdated()
|
||||
{
|
||||
if (_repeat)
|
||||
{
|
||||
PerformLookAt(transform, _allowRotateAroundY, _allowRotateAroundX, _invertedForwardAxis);
|
||||
|
||||
if (_onlyOnce)
|
||||
{
|
||||
_repeat = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Performs look at.
|
||||
/// </summary>
|
||||
/// <param name="transform">The Transform that will look at the local avatar</param>
|
||||
/// <param name="allowRotateAroundVerticalAxis">
|
||||
/// Should the lookAt alter the rotation around the vertical axis?
|
||||
/// </param>
|
||||
/// <param name="allowRotateAroundHorizontalAxis">
|
||||
/// Should the lookAt alter the rotation around the horizontal axis?
|
||||
/// </param>
|
||||
/// <param name="invertedForwardAxis">
|
||||
/// If true, the target's forward axis will try to point at the opposite direction where the avatar is. By default this
|
||||
/// is false, meaning the forward vector will try to point at the avatar
|
||||
/// </param>
|
||||
private static void PerformLookAt(Transform transform, bool allowRotateAroundVerticalAxis, bool allowRotateAroundHorizontalAxis, bool invertedForwardAxis)
|
||||
{
|
||||
Camera currentCamera = UxrAvatar.LocalOrFirstEnabledCamera;
|
||||
|
||||
if (currentCamera == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 lookAt = currentCamera.transform.position - transform.position;
|
||||
|
||||
if (allowRotateAroundHorizontalAxis == false)
|
||||
{
|
||||
lookAt.y = 0.0f;
|
||||
}
|
||||
|
||||
if (allowRotateAroundVerticalAxis == false)
|
||||
{
|
||||
lookAt = Vector3.ProjectOnPlane(lookAt, transform.right);
|
||||
}
|
||||
|
||||
if (lookAt != Vector3.zero)
|
||||
{
|
||||
transform.rotation = Quaternion.LookRotation(invertedForwardAxis ? -lookAt : lookAt);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Types & Data
|
||||
|
||||
private bool _repeat = true;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
13
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAtLocalAvatar.cs.meta
vendored
Normal file
13
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAtLocalAvatar.cs.meta
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ac1f3fc45c4bd145acc5e43c81e68a0
|
||||
timeCreated: 1516189266
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
28
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAtMode.cs
vendored
Normal file
28
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAtMode.cs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrLookAtMode.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
namespace UltimateXR.Animation.Transforms
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerates the different modes for a "look at" operation.
|
||||
/// </summary>
|
||||
public enum UxrLookAtMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Look at the target.
|
||||
/// </summary>
|
||||
Target,
|
||||
|
||||
/// <summary>
|
||||
/// Align to a specific target's direction.
|
||||
/// </summary>
|
||||
MatchTargetDirection,
|
||||
|
||||
/// <summary>
|
||||
/// Use a direction in world-space coordinates.
|
||||
/// </summary>
|
||||
MatchWorldDirection
|
||||
}
|
||||
}
|
||||
3
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAtMode.cs.meta
vendored
Normal file
3
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrLookAtMode.cs.meta
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02436c0a376446f8a0d1bd6551062cd9
|
||||
timeCreated: 1645013745
|
||||
59
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrPositionInFrontOfCamera.cs
vendored
Normal file
59
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrPositionInFrontOfCamera.cs
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrPositionInFrontOfCamera.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
using UltimateXR.Avatar;
|
||||
using UltimateXR.Core.Components;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UltimateXR.Animation.Transforms
|
||||
{
|
||||
/// <summary>
|
||||
/// Positions an object in front of the VR camera with a height offset compared to it
|
||||
/// </summary>
|
||||
public sealed class UxrPositionInFrontOfCamera : UxrComponent
|
||||
{
|
||||
#region Inspector Properties/Serialized Fields
|
||||
|
||||
[SerializeField] private float _distance = 0.2f;
|
||||
[SerializeField] private float _heightOffset = -0.2f;
|
||||
[SerializeField] private Vector3 _eulerAngles = Vector3.zero;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
/// <summary>
|
||||
/// Performs transform
|
||||
/// </summary>
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (UxrAvatar.LocalAvatarCamera)
|
||||
{
|
||||
Transform cameraTransform = UxrAvatar.LocalAvatar.CameraTransform;
|
||||
Vector3 forward = UxrAvatar.LocalAvatar.ProjectedCameraForward;
|
||||
|
||||
if (forward != Vector3.zero)
|
||||
{
|
||||
forward.Normalize();
|
||||
|
||||
if ((cameraTransform.forward.y < 0.0f && Vector3.Dot(cameraTransform.forward, -Vector3.up) < 0.9f) || (cameraTransform.forward.y >= 0.0f && Vector3.Dot(cameraTransform.forward, Vector3.up) < 0.9f))
|
||||
{
|
||||
_forward = forward;
|
||||
}
|
||||
}
|
||||
|
||||
transform.SetPositionAndRotation(UxrAvatar.LocalAvatar.CameraPosition + _forward * _distance + Vector3.up * _heightOffset, Quaternion.LookRotation(_forward, Vector3.up) * Quaternion.Euler(_eulerAngles));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Types & Data
|
||||
|
||||
private Vector3 _forward;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 362c002065e08da499741afb371b4ce2
|
||||
timeCreated: 1516189266
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
23
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrTransformRotationSpace.cs
vendored
Normal file
23
Assets/ThirdParty/UltimateXR/Runtime/Scripts/Animation/Transforms/UxrTransformRotationSpace.cs
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrTransformRotationSpace.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
namespace UltimateXR.Animation.Transforms
|
||||
{
|
||||
/// <summary>
|
||||
/// Rotation space for rotation transforms.
|
||||
/// </summary>
|
||||
public enum UxrTransformRotationSpace
|
||||
{
|
||||
/// <summary>
|
||||
/// Local coordinates.
|
||||
/// </summary>
|
||||
Local,
|
||||
|
||||
/// <summary>
|
||||
/// World-space coordinates.
|
||||
/// </summary>
|
||||
World
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0929f4cc4bb4738b66759e46194abc3
|
||||
timeCreated: 1643217187
|
||||
@@ -0,0 +1,20 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="UxrTransformTranslationSpace.cs" company="VRMADA">
|
||||
// Copyright (c) VRMADA, All rights reserved.
|
||||
// </copyright>
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
namespace UltimateXR.Animation.Transforms
|
||||
{
|
||||
/// <summary>
|
||||
/// The space in which we can translate an object. World will translate an object along the global X/Y/Z axes, Local
|
||||
/// will translate it along the object's local X/Y/Z axes and Parent will translate it along its parent's local X/Y/Z
|
||||
/// axes.
|
||||
/// In case there is no parent, Parent mode will be the same as using World mode.
|
||||
/// </summary>
|
||||
public enum UxrTransformTranslationSpace
|
||||
{
|
||||
Local,
|
||||
World,
|
||||
Parent
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 356a7200eac84052a91973033c18129b
|
||||
timeCreated: 1643216925
|
||||
Reference in New Issue
Block a user