Add ultimate xr

This commit is contained in:
2024-08-06 21:58:35 +02:00
parent 864033bf10
commit 7165bacd9d
3952 changed files with 2162037 additions and 35 deletions

View File

@@ -0,0 +1,702 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrAnimatedMaterial.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using UltimateXR.Animation.Interpolation;
using UltimateXR.Core;
using UltimateXR.Core.Settings;
using UltimateXR.Extensions.Unity;
using UnityEngine;
namespace UltimateXR.Animation.Materials
{
/// <summary>
/// Component that allows to animate material properties.
/// </summary>
public class UxrAnimatedMaterial : UxrAnimatedComponent<UxrAnimatedMaterial>
{
#region Inspector Properties/Serialized Fields
[SerializeField] private bool _animateSelf = true;
[SerializeField] private GameObject _targetGameObject;
[SerializeField] private int _materialSlot;
[SerializeField] private UxrMaterialMode _materialMode = UxrMaterialMode.InstanceOnly;
[SerializeField] private bool _restoreWhenFinished = true;
[SerializeField] private UxrMaterialParameterType _parameterType = UxrMaterialParameterType.Vector4;
[SerializeField] private string _parameterName = "";
#endregion
#region Public Types & Data
/// <summary>
/// The default blink frequency
/// </summary>
public const float DefaultBlinkFrequency = 3.0f;
/// <summary>
/// Gets or sets if the original material value should be restored when finished.
/// </summary>
public bool RestoreWhenFinished
{
get => _restoreWhenFinished;
set => _restoreWhenFinished = value;
}
/// <summary>
/// Gets or sets whether the animation will be applied to the GameObject where the component is, or an external one.
/// </summary>
public bool AnimateSelf
{
get => _animateSelf;
set => _animateSelf = value;
}
/// <summary>
/// Gets or sets the target GameObject when <see cref="AnimateSelf" /> is true.
/// </summary>
public GameObject TargetGameObject
{
get => _targetGameObject;
set => _targetGameObject = value;
}
/// <summary>
/// Gets or sets the material slot to apply the material animation to.
/// </summary>
public int MaterialSlot
{
get => _materialSlot;
set => _materialSlot = value;
}
/// <summary>
/// Gets or sets the material mode, whether to use the instanced material or the shared material.
/// </summary>
public UxrMaterialMode MaterialMode
{
get => _materialMode;
set => _materialMode = value;
}
/// <summary>
/// Gets or sets the material's parameter type.
/// </summary>
public UxrMaterialParameterType ParameterType
{
get => _parameterType;
set => _parameterType = value;
}
/// <summary>
/// Gets or sets the material's parameter name.
/// </summary>
public string ParameterName
{
get => _parameterName;
set => _parameterName = value;
}
#endregion
#region Public Methods
/// <summary>
/// Starts an animation at a constant speed
/// </summary>
/// <param name="gameObject">The GameObject with the material to apply the animation to</param>
/// <param name="materialSlot">The renderer material slot where the material is</param>
/// <param name="materialMode">
/// The material mode. Use instance to animate the material of a single object,
/// use shared to also affect all other objects that share the same material
/// </param>
/// <param name="parameterType">Selects the type of the parameter to animate</param>
/// <param name="parameterName">
/// Selects the name of the parameter to animate.
/// This name is the name in the shader, not in the inspector!
/// </param>
/// <param name="speed">
/// The animation speed. For int/float values use .x, for Vector2 use x and y.
/// For Vector3 use x, y, z. etc.
/// </param>
/// <param name="durationSeconds">
/// Duration in seconds of the animation. Use a negative value to keep updating until stopped
/// manually.
/// </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>
/// <param name="finishedCallback">Optional callback when the animation finished</param>
/// <returns>The animation component</returns>
public static UxrAnimatedMaterial Animate(GameObject gameObject,
int materialSlot,
UxrMaterialMode materialMode,
UxrMaterialParameterType parameterType,
string parameterName,
Vector4 speed,
float durationSeconds = -1.0f,
bool useUnscaledTime = false,
Action finishedCallback = null)
{
UxrAnimatedMaterial component = gameObject.GetOrAddComponent<UxrAnimatedMaterial>();
if (component)
{
component._restoreWhenFinished = false;
component._animateSelf = true;
component._materialSlot = materialSlot;
component._materialMode = materialMode;
component._parameterType = parameterType;
component._parameterName = parameterName;
component.AnimationMode = UxrAnimationMode.Speed;
component.Speed = speed;
component.UseUnscaledTime = useUnscaledTime;
component.SpeedDurationSeconds = durationSeconds;
component._finishedCallback = finishedCallback;
component.Initialize();
component.StartTimer();
}
return component;
}
/// <summary>
/// Starts a material parameter animation using an interpolation curve
/// </summary>
/// <param name="gameObject">The GameObject with the material to apply the animation to</param>
/// <param name="materialSlot">The renderer material slot where the material is</param>
/// <param name="materialMode">
/// The material mode. Use instance to animate the material of a single object,
/// use shared to also affect all other objects that share the same material
/// </param>
/// <param name="parameterType">Selects the type of the parameter to animate</param>
/// <param name="parameterName">
/// Selects the name of the parameter to animate.
/// This name is the name in the shader, not in the inspector!
/// </param>
/// <param name="startValue">
/// The start value. For int/float values use .x, for Vector2 use x and y.
/// For Vector3 use x, y, z. etc.
/// </param>
/// <param name="endValue">
/// The end value. For int/float values use .x, for Vector2 use x and y.
/// For Vector3 use x, y, z. etc.
/// </param>
/// <param name="settings">The interpolation settings with the curve parameters</param>
/// <param name="finishedCallback">Optional callback when the animation finished</param>
/// <returns>The animation component</returns>
public static UxrAnimatedMaterial AnimateInterpolation(GameObject gameObject,
int materialSlot,
UxrMaterialMode materialMode,
UxrMaterialParameterType parameterType,
string parameterName,
Vector4 startValue,
Vector4 endValue,
UxrInterpolationSettings settings,
Action finishedCallback = null)
{
UxrAnimatedMaterial component = gameObject.GetOrAddComponent<UxrAnimatedMaterial>();
if (component)
{
component._restoreWhenFinished = false;
component._animateSelf = true;
component._materialSlot = materialSlot;
component._materialMode = materialMode;
component._parameterType = parameterType;
component._parameterName = parameterName;
component.AnimationMode = UxrAnimationMode.Interpolate;
component.InterpolatedValueStart = startValue;
component.InterpolatedValueEnd = endValue;
component.InterpolationSettings = settings;
component._finishedCallback = finishedCallback;
component.Initialize();
component.StartTimer();
component.InterpolatedValueWhenDisabled = component._valueBeforeAnimation;
}
return component;
}
/// <summary>
/// Starts a material parameter animation using noise
/// </summary>
/// <param name="gameObject">The GameObject with the material to apply the animation to</param>
/// <param name="materialSlot">The renderer material slot where the material is</param>
/// <param name="materialMode">
/// The material mode. Use instance to animate the material of a single object,
/// use shared to also affect all other objects that share the same material
/// </param>
/// <param name="parameterType">Selects the type of the parameter to animate</param>
/// <param name="parameterName">
/// Selects the name of the parameter to animate.
/// This name is the name in the shader, not in the inspector!
/// </param>
/// <param name="noiseTimeStart">The time in seconds the noise will start (Time.time or Time.unscaledTime value)</param>
/// <param name="noiseTimeDuration">The duration in seconds of the noise animation</param>
/// <param name="noiseValueStart">
/// The start value. For int/float values use .x, for Vector2 use x and y.
/// For Vector3 use x, y, z. etc.
/// </param>
/// <param name="noiseValueEnd">
/// The end value. For int/float values use .x, for Vector2 use x and y.
/// For Vector3 use x, y, z. etc.
/// </param>
/// <param name="noiseValueMin">
/// The minimum intensity value for the noise. For int/float values use .x, for Vector2 use x and y.
/// For Vector3 use x, y, z. etc.
/// </param>
/// <param name="noiseValueMax">
/// The maximum intensity value for the noise. For int/float values use .x, for Vector2 use x and y.
/// For Vector3 use x, y, z. etc.
/// </param>
/// <param name="noiseValueFrequency">
/// The noise frequency. For int/float values use .x, for Vector2 use x and y.
/// For Vector3 use x, y, z. etc.
/// </param>
/// <param name="finishedCallback">Optional callback when the animation finished</param>
/// <param name="useUnscaledTime">If true it will use Time.unscaledTime, if false it will use Time.time</param>
public static void AnimateNoise(GameObject gameObject,
int materialSlot,
UxrMaterialMode materialMode,
UxrMaterialParameterType parameterType,
string parameterName,
float noiseTimeStart,
float noiseTimeDuration,
Vector4 noiseValueStart,
Vector4 noiseValueEnd,
Vector4 noiseValueMin,
Vector4 noiseValueMax,
Vector4 noiseValueFrequency,
bool useUnscaledTime = false,
Action finishedCallback = null)
{
UxrAnimatedMaterial component = gameObject.GetOrAddComponent<UxrAnimatedMaterial>();
if (component)
{
component._restoreWhenFinished = false;
component._animateSelf = true;
component._materialSlot = materialSlot;
component._materialMode = materialMode;
component._parameterType = parameterType;
component._parameterName = parameterName;
component.AnimationMode = UxrAnimationMode.Noise;
component.NoiseTimeStart = noiseTimeStart;
component.NoiseDurationSeconds = noiseTimeDuration;
component.NoiseValueStart = noiseValueStart;
component.NoiseValueEnd = noiseValueEnd;
component.NoiseValueMin = noiseValueMin;
component.NoiseValueMax = noiseValueMax;
component.NoiseFrequency = noiseValueFrequency;
component.UseUnscaledTime = useUnscaledTime;
component._finishedCallback = finishedCallback;
component.Initialize();
component.StartTimer();
component.InterpolatedValueWhenDisabled = component._valueBeforeAnimation;
}
}
/// <summary>
/// Starts animating a GameObject's material making one if its float parameters blink.
/// </summary>
/// <param name="gameObject">GameObject whose material to animate</param>
/// <param name="varNameFloat">The float var name</param>
/// <param name="valueMin">The minimum float value in the blink</param>
/// <param name="valueMax">The maximum float value in the blink</param>
/// <param name="blinkFrequency">The blinking frequency</param>
/// <param name="durationSeconds">
/// The duration in seconds. Use a negative value to keep keep blinking until stopping
/// manually.
/// </param>
/// <param name="materialMode">The material mode</param>
/// <param name="finishedCallback">Optional callback when the animation finished</param>
/// <returns>Material animation component</returns>
public static UxrAnimatedMaterial AnimateFloatBlink(GameObject gameObject,
string varNameFloat,
float valueMin = 0.0f,
float valueMax = 1.0f,
float blinkFrequency = DefaultBlinkFrequency,
float durationSeconds = -1.0f,
UxrMaterialMode materialMode = UxrMaterialMode.InstanceOnly,
Action finishedCallback = null)
{
return AnimateInterpolation(gameObject,
0,
materialMode,
UxrMaterialParameterType.Float,
varNameFloat,
Vector4.one * valueMin,
Vector4.one * valueMax,
new UxrInterpolationSettings(1.0f / blinkFrequency * 0.5f, 0.0f, UxrEasing.EaseInOutSine, UxrLoopMode.PingPong, durationSeconds),
finishedCallback);
}
/// <summary>
/// Starts animating a GameObject's material making one if its color parameters blink.
/// </summary>
/// <param name="gameObject">GameObject whose material to animate</param>
/// <param name="varNameColor">The float var name</param>
/// <param name="colorOff">The minimum color value in the blink</param>
/// <param name="colorOn">The maximum color value in the blink</param>
/// <param name="blinkFrequency">The blinking frequency</param>
/// <param name="durationSeconds">
/// The duration in seconds. Use a negative value to keep keep blinking until stopping
/// manually.
/// </param>
/// <param name="materialMode">The material mode</param>
/// <param name="finishedCallback">Optional callback when the animation finished</param>
/// <returns>Material animation component</returns>
public static UxrAnimatedMaterial AnimateBlinkColor(GameObject gameObject,
string varNameColor,
Color colorOff,
Color colorOn,
float blinkFrequency = DefaultBlinkFrequency,
float durationSeconds = -1.0f,
UxrMaterialMode materialMode = UxrMaterialMode.InstanceOnly,
Action finishedCallback = null)
{
return AnimateInterpolation(gameObject,
0,
materialMode,
UxrMaterialParameterType.Color,
varNameColor,
colorOff,
colorOn,
new UxrInterpolationSettings(1.0f / blinkFrequency * 0.5f, 0.0f, UxrEasing.EaseInOutSine, UxrLoopMode.PingPong, durationSeconds),
finishedCallback);
}
/// <summary>
/// Restores the original (shared) material. This may have some performance advantages.
/// </summary>
public void RestoreOriginalSharedMaterial()
{
if (_renderer)
{
if (_materialSlot == 0)
{
_renderer.sharedMaterial = _originalMaterial;
}
else
{
_renderer.sharedMaterials = _originalMaterials;
}
}
}
#endregion
#region Unity
/// <summary>
/// Initializes internal variables
/// </summary>
protected override void Awake()
{
base.Awake();
Initialize();
}
#endregion
#region Event Trigger Methods
/// <inheritdoc cref="UxrAnimatedComponent{T}.OnFinished" />
protected override void OnFinished(UxrAnimatedMaterial anim)
{
base.OnFinished(anim);
if (RestoreWhenFinished && MaterialMode == UxrMaterialMode.InstanceOnly)
{
RestoreOriginalSharedMaterial();
}
_finishedCallback?.Invoke();
}
#endregion
#region Protected Overrides UxrAnimatedComponent<UxrAnimatedMaterial>
/// <summary>
/// Restores the original value before the animation started.
/// </summary>
protected override void RestoreOriginalValue()
{
if (_valueBeforeAnimationInitialized)
{
SetParameterValue(_valueBeforeAnimation);
}
}
/// <summary>
/// Gets the parameter value from the material
/// </summary>
/// <returns>
/// Vector4 containing the value. This value may not use all components depending on the parameter type.
/// </returns>
protected override Vector4 GetParameterValue()
{
if (_renderer && _materialSlot < _renderer.sharedMaterials.Length)
{
switch (_parameterType)
{
case UxrMaterialParameterType.Int:
if (_materialMode == UxrMaterialMode.InstanceOnly)
{
return _materialSlot == 0 ? new Vector4(_renderer.material.GetInt(_parameterName), 0, 0, 0) : new Vector4(_renderer.materials[_materialSlot].GetInt(_parameterName), 0, 0, 0);
}
else
{
return _materialSlot == 0 ? new Vector4(_renderer.sharedMaterial.GetInt(_parameterName), 0, 0, 0) : new Vector4(_renderer.sharedMaterials[_materialSlot].GetInt(_parameterName), 0, 0, 0);
}
case UxrMaterialParameterType.Float:
if (_materialMode == UxrMaterialMode.InstanceOnly)
{
return _materialSlot == 0 ? new Vector4(_renderer.material.GetFloat(_parameterName), 0, 0, 0) : new Vector4(_renderer.materials[_materialSlot].GetFloat(_parameterName), 0, 0, 0);
}
else
{
return _materialSlot == 0 ? new Vector4(_renderer.sharedMaterial.GetFloat(_parameterName), 0, 0, 0) : new Vector4(_renderer.sharedMaterials[_materialSlot].GetFloat(_parameterName), 0, 0, 0);
}
case UxrMaterialParameterType.Vector2:
case UxrMaterialParameterType.Vector3:
case UxrMaterialParameterType.Vector4:
if (_materialMode == UxrMaterialMode.InstanceOnly)
{
return _materialSlot == 0 ? _renderer.material.GetVector(_parameterName) : _renderer.materials[_materialSlot].GetVector(_parameterName);
}
else
{
return _materialSlot == 0 ? _renderer.sharedMaterial.GetVector(_parameterName) : _renderer.sharedMaterials[_materialSlot].GetVector(_parameterName);
}
case UxrMaterialParameterType.Color:
if (_materialMode == UxrMaterialMode.InstanceOnly)
{
return _materialSlot == 0 ? _renderer.material.GetColor(_parameterName) : _renderer.materials[_materialSlot].GetColor(_parameterName);
}
else
{
return _materialSlot == 0 ? _renderer.sharedMaterial.GetColor(_parameterName) : _renderer.sharedMaterials[_materialSlot].GetColor(_parameterName);
}
}
}
if (UxrGlobalSettings.Instance.LogLevelAnimation >= UxrLogLevel.Warnings)
{
Debug.LogWarning($"{UxrConstants.AnimationModule} Material slot {_materialSlot} for {this.GetPathUnderScene()} is not valid");
}
return Vector4.zero;
}
/// <summary>
/// Sets the material parameter value
/// </summary>
/// <param name="value">
/// Vector4 containing the value. This value may not use all components depending on the parameter type
/// </param>
protected override void SetParameterValue(Vector4 value)
{
Material[] materials = null;
if (_renderer && _materialSlot < _renderer.sharedMaterials.Length)
{
switch (_parameterType)
{
case UxrMaterialParameterType.Int:
if (_materialMode == UxrMaterialMode.InstanceOnly)
{
if (_materialSlot == 0)
{
_renderer.material.SetInt(_parameterName, Mathf.RoundToInt(value.x));
}
else
{
materials = _renderer.materials;
materials[_materialSlot].SetInt(_parameterName, Mathf.RoundToInt(value.x));
_renderer.materials = materials;
}
}
else
{
if (_materialSlot == 0)
{
_renderer.sharedMaterial.SetInt(_parameterName, Mathf.RoundToInt(value.x));
}
else
{
materials = _renderer.sharedMaterials;
materials[_materialSlot].SetInt(_parameterName, Mathf.RoundToInt(value.x));
_renderer.sharedMaterials = materials;
}
}
return;
case UxrMaterialParameterType.Float:
if (_materialMode == UxrMaterialMode.InstanceOnly)
{
if (_materialSlot == 0)
{
_renderer.material.SetFloat(_parameterName, value.x);
}
else
{
materials = _renderer.materials;
materials[_materialSlot].SetFloat(_parameterName, value.x);
_renderer.materials = materials;
}
}
else
{
if (_materialSlot == 0)
{
_renderer.sharedMaterial.SetFloat(_parameterName, value.x);
}
else
{
materials = _renderer.sharedMaterials;
materials[_materialSlot].SetFloat(_parameterName, value.x);
_renderer.sharedMaterials = materials;
}
}
return;
case UxrMaterialParameterType.Vector2:
case UxrMaterialParameterType.Vector3:
case UxrMaterialParameterType.Vector4:
if (_materialMode == UxrMaterialMode.InstanceOnly)
{
if (_materialSlot == 0)
{
_renderer.material.SetVector(_parameterName, value);
}
else
{
materials = _renderer.materials;
materials[_materialSlot].SetVector(_parameterName, value);
_renderer.materials = materials;
}
}
else
{
if (_materialSlot == 0)
{
_renderer.sharedMaterial.SetVector(_parameterName, value);
}
else
{
materials = _renderer.sharedMaterials;
materials[_materialSlot].SetVector(_parameterName, value);
_renderer.sharedMaterials = materials;
}
}
return;
case UxrMaterialParameterType.Color:
if (_materialMode == UxrMaterialMode.InstanceOnly)
{
if (_materialSlot == 0)
{
_renderer.material.SetColor(_parameterName, value);
}
else
{
materials = _renderer.materials;
materials[_materialSlot].SetColor(_parameterName, value);
_renderer.materials = materials;
}
}
else
{
if (_materialSlot == 0)
{
_renderer.sharedMaterial.SetColor(_parameterName, value);
}
else
{
materials = _renderer.sharedMaterials;
materials[_materialSlot].SetColor(_parameterName, value);
_renderer.sharedMaterials = materials;
}
}
return;
}
}
if (UxrGlobalSettings.Instance.LogLevelAnimation >= UxrLogLevel.Warnings)
{
Debug.LogWarning($"{UxrConstants.AnimationModule} Material slot " + _materialSlot + " for object " + name + " is not valid");
}
}
#endregion
#region Private Methods
/// <summary>
/// Initializes internal data
/// </summary>
private void Initialize()
{
if (_renderer == null)
{
_renderer = _animateSelf || !_targetGameObject ? GetComponent<Renderer>() : _targetGameObject.GetComponent<Renderer>();
if (_renderer)
{
if (_materialSlot == 0)
{
_originalMaterial = _renderer.sharedMaterial;
}
else
{
_originalMaterials = _renderer.sharedMaterials;
}
}
}
if (_renderer && !string.IsNullOrEmpty(_parameterName) && !_valueBeforeAnimationInitialized)
{
_valueBeforeAnimation = GetParameterValue();
_valueBeforeAnimationInitialized = true;
}
}
#endregion
#region Private Types & Data
private Renderer _renderer;
private Material _originalMaterial;
private Material[] _originalMaterials;
private bool _valueBeforeAnimationInitialized;
private Vector4 _valueBeforeAnimation;
private Action _finishedCallback;
#endregion
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 2bbad2839f9d42d41ba6b2d584190630
timeCreated: 1516185390
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,350 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrAnimatedTextureFlipbook.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using UltimateXR.Core;
using UltimateXR.Core.Components;
using UnityEngine;
using Random = UnityEngine.Random;
namespace UltimateXR.Animation.Materials
{
/// <summary>
/// Component that allows to animate a material's texture that contains multiple animation frames.
/// </summary>
public class UxrAnimatedTextureFlipbook : UxrComponent
{
#region Inspector Properties/Serialized Fields
[SerializeField] private bool _animateSelf = true;
[SerializeField] private GameObject _targetGameObject;
[SerializeField] private string _scaleOffsetVarName = UxrConstants.Shaders.StandardMainTextureScaleOffsetVarName;
[SerializeField] private int _flipBookColumns = 1;
[SerializeField] private int _flipBookRows = 1;
[SerializeField] private int _totalFrames = 1;
[SerializeField] private UxrFlipbookAnimationMode _loopMode = UxrFlipbookAnimationMode.SingleSequence;
[SerializeField] private bool _randomFrameStart;
[SerializeField] private float _fps = 10;
[SerializeField] private UxrFlipbookFinishedAction _whenFinished = UxrFlipbookFinishedAction.DoNothing;
[SerializeField] private bool _useUnscaledTime;
#endregion
#region Public Types & Data
/// <summary>
/// Called when the animation finished.
/// </summary>
public event Action Finished;
/// <summary>
/// Gets or sets the target renderer whose material will be animated.
/// </summary>
public Renderer TargetRenderer { get; set; }
/// <summary>
/// Gets or sets the material's shader scale/offset variable name, usually _MainTex_ST.
/// </summary>
public string ScaleOffsetVarName
{
get => _scaleOffsetVarName;
set => _scaleOffsetVarName = value;
}
/// <summary>
/// Gets or sets the number of columns in the texture animation sheet.
/// </summary>
public int FlipBookColumns
{
get => _flipBookColumns;
set => _flipBookColumns = value;
}
/// <summary>
/// Gets or sets the number of rows in the texture animation sheet.
/// </summary>
public int FlipBookRows
{
get => _flipBookRows;
set => _flipBookRows = value;
}
/// <summary>
/// Gets or sets the total number of frames in the texture animation sheet.
/// </summary>
public int TotalFrames
{
get => _totalFrames;
set => _totalFrames = value;
}
/// <summary>
/// Gets or sets the animation loop mode.
/// </summary>
public UxrFlipbookAnimationMode LoopMode
{
get => _loopMode;
set => _loopMode = value;
}
/// <summary>
/// Gets or sets whether to start the animation in a random frame position.
/// </summary>
public bool RandomFrameStart
{
get => _randomFrameStart;
set => _randomFrameStart = value;
}
/// <summary>
/// Gets or sets the frames per second to play the animation.
/// </summary>
public float FPS
{
get => _fps;
set => _fps = value;
}
/// <summary>
/// Gets or sets the action to perform when the animation finished. The only animation that can finish is when
/// <see cref="AnimationPlayMode" /> is <see cref="UxrFlipbookAnimationMode.SingleSequence" />.
/// </summary>
public UxrFlipbookFinishedAction WhenFinished
{
get => _whenFinished;
set => _whenFinished = value;
}
#endregion
#region Unity
/// <summary>
/// Initializes internal variables
/// </summary>
protected override void Awake()
{
base.Awake();
if (TargetRenderer == null)
{
TargetRenderer = _animateSelf || !_targetGameObject ? GetComponent<Renderer>() : _targetGameObject.GetComponent<Renderer>();
}
_hasFinished = false;
_frameStart = 0;
SetFrame(0);
}
/// <summary>
/// Called each time the object is enabled. Reset timer and set the curve state to unfinished.
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
_startTime = _useUnscaledTime ? Time.unscaledTime : Time.time;
_hasFinished = false;
_lastFrame = -1;
_lastLinearFrame = -1;
if (_randomFrameStart)
{
_frameStart = Mathf.RoundToInt(Random.value * (_totalFrames - 1));
}
if (TargetRenderer && _whenFinished == UxrFlipbookFinishedAction.DisableRenderer)
{
TargetRenderer.enabled = true;
}
}
/// <summary>
/// Enables the correct flipbook frame and checks if it finished
/// </summary>
private void Update()
{
if (_hasFinished)
{
return;
}
float currentTime = _useUnscaledTime ? Time.unscaledTime : Time.time;
int linearFrame = (int)((currentTime - _startTime) * _fps);
switch (_loopMode)
{
case UxrFlipbookAnimationMode.SingleSequence:
if (linearFrame >= _totalFrames)
{
ExecuteFinishAction();
_hasFinished = true;
}
else
{
SetFrame(_totalFrames > 0 ? (linearFrame + _frameStart) % _totalFrames : 0);
}
break;
case UxrFlipbookAnimationMode.Loop:
SetFrame(_totalFrames > 0 ? (linearFrame + _frameStart) % _totalFrames : 0);
break;
case UxrFlipbookAnimationMode.PingPong:
if (_totalFrames > 1)
{
if (linearFrame < _totalFrames)
{
SetFrame(linearFrame);
}
else
{
bool forward = ((linearFrame - _totalFrames) / (_totalFrames - 1) & 1) == 1;
int correctFrame = (linearFrame - _totalFrames) % (_totalFrames - 1);
SetFrame(forward ? correctFrame + 1 : _totalFrames - correctFrame - 2);
}
}
else if (_lastFrame != 0)
{
SetFrame(0);
}
break;
case UxrFlipbookAnimationMode.RandomFrame:
if (linearFrame != _lastLinearFrame)
{
SetFrame(Random.Range(0, _totalFrames));
}
break;
case UxrFlipbookAnimationMode.RandomFrameNoRepetition:
if (linearFrame != _lastLinearFrame)
{
if (_totalFrames < 2)
{
SetFrame(0);
}
else if (_totalFrames == 2)
{
SetFrame(_lastFrame == 0 ? 1 : 0);
}
else
{
int frame = Random.Range(0, _totalFrames);
while (frame == _lastFrame)
{
frame = Random.Range(0, _totalFrames);
}
SetFrame(frame);
}
}
break;
default: throw new ArgumentOutOfRangeException();
}
_lastLinearFrame = linearFrame;
}
#endregion
#region Private Methods
/// <summary>
/// Sets the current flipbook texture frame
/// </summary>
/// <param name="frame">Flipbook frame</param>
private void SetFrame(int frame)
{
if (TargetRenderer && _lastFrame != frame)
{
Vector4 vecScaleOffset = TargetRenderer.material.GetVector(_scaleOffsetVarName);
if (_flipBookColumns > 0)
{
int column = frame % _flipBookColumns;
vecScaleOffset.x = 1.0f / _flipBookColumns;
vecScaleOffset.z = column * vecScaleOffset.x;
}
if (_flipBookRows > 0 && _flipBookColumns > 0)
{
int row = frame / _flipBookColumns;
vecScaleOffset.y = 1.0f / _flipBookRows;
vecScaleOffset.w = 1.0f - (row + 1) * vecScaleOffset.y;
}
TargetRenderer.material.SetVector(_scaleOffsetVarName, vecScaleOffset);
_lastFrame = frame;
}
}
/// <summary>
/// Executes the action when the animation finished.
/// </summary>
private void ExecuteFinishAction()
{
Finished?.Invoke();
switch (_whenFinished)
{
case UxrFlipbookFinishedAction.DoNothing: break;
case UxrFlipbookFinishedAction.DisableRenderer:
if (TargetRenderer)
{
TargetRenderer.enabled = false;
}
break;
case UxrFlipbookFinishedAction.DisableGameObject:
if (TargetRenderer)
{
TargetRenderer.gameObject.SetActive(false);
}
break;
case UxrFlipbookFinishedAction.DestroyGameObject:
if (TargetRenderer)
{
Destroy(TargetRenderer.gameObject);
}
break;
default: throw new ArgumentOutOfRangeException();
}
}
#endregion
#region Private Types & Data
private int _frameStart;
private float _startTime;
private bool _hasFinished;
private int _lastFrame = -1;
private int _lastLinearFrame = -1;
#endregion
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 13ede170b3667dc4882754072020a994
timeCreated: 1516185390
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrFlipbookAnimationMode.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace UltimateXR.Animation.Materials
{
/// <summary>
/// The different animation modes available in <see cref="UxrAnimatedTextureFlipbook" />
/// </summary>
public enum UxrFlipbookAnimationMode
{
/// <summary>
/// Frames are played back in a sequence, ending with the last frame.
/// </summary>
SingleSequence,
/// <summary>
/// Frames are played back in a sequence up to the last frame. The sequence starts again from the beginning
/// indefinitely.
/// </summary>
Loop,
/// <summary>
/// Frames are played back in a sequence up to the last frame and then back to the beginning again. This process is
/// repeated indefinitely.
/// </summary>
PingPong,
/// <summary>
/// Random frames are played indefinitely.
/// </summary>
RandomFrame,
/// <summary>
/// Random frames are played indefinitely but there are never two same frames played one after the other.
/// </summary>
RandomFrameNoRepetition,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 04054975fe5140d6a343f675c1e9d284
timeCreated: 1643216355

View File

@@ -0,0 +1,34 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrFlipbookFinishedAction.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace UltimateXR.Animation.Materials
{
/// <summary>
/// What should be done when a <see cref="UxrAnimatedTextureFlipbook" /> animation finished. This is only supported
/// with <see cref="UxrFlipbookAnimationMode.SingleSequence" />.
/// </summary>
public enum UxrFlipbookFinishedAction
{
/// <summary>
/// Nothing happens when the animation finished.
/// </summary>
DoNothing,
/// <summary>
/// After showing the last frame, the renderer is disabled.
/// </summary>
DisableRenderer,
/// <summary>
/// After showing the last frame, the GameObject the component is attached to is disabled.
/// </summary>
DisableGameObject,
/// <summary>
/// After showing the last frame, the GameObject the component is attached to is destroyed.
/// </summary>
DestroyGameObject
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: eef28cb2025e45128264c3a742b1a9ac
timeCreated: 1643216370

View File

@@ -0,0 +1,24 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrMaterialMode.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace UltimateXR.Animation.Materials
{
/// <summary>
/// The material modes supported by <see cref="UxrAnimatedMaterial" />. It can animate the object's instanced material
/// or all the objects that share the same material.
/// </summary>
public enum UxrMaterialMode
{
/// <summary>
/// Animate this instance of the material only.
/// </summary>
InstanceOnly,
/// <summary>
/// Animate the material, so that all renderers that share the same material are affected too.
/// </summary>
Shared
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9746372080bd49198a73205527919f3e
timeCreated: 1643214925

View File

@@ -0,0 +1,43 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrMaterialParameterType.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace UltimateXR.Animation.Materials
{
/// <summary>
/// Material parameter types that can be animated by <see cref="UxrAnimatedMaterial" />.
/// </summary>
public enum UxrMaterialParameterType
{
/// <summary>
/// Integer value.
/// </summary>
Int,
/// <summary>
/// Single floating point value.
/// </summary>
Float,
/// <summary>
/// Vector2 value representing two floating points.
/// </summary>
Vector2,
/// <summary>
/// Vector3 value representing three floating points.
/// </summary>
Vector3,
/// <summary>
/// Vector4 value representing four floating points.
/// </summary>
Vector4,
/// <summary>
/// Color represented by 4 values RGBA.
/// </summary>
Color
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 18df256b817b45148477817eeaa9dc4d
timeCreated: 1643214917

View File

@@ -0,0 +1,89 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UxrMaterialRenderQueue.cs" company="VRMADA">
// Copyright (c) VRMADA, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using UltimateXR.Core.Components;
using UnityEngine;
namespace UltimateXR.Animation.Materials
{
/// <summary>
/// Component that changes the RenderQueue of a material. Changes will be applied at runtime.
/// </summary>
public class UxrMaterialRenderQueue : UxrComponent
{
#region Inspector Properties/Serialized Fields
[SerializeField] private bool _instanceOnly;
[SerializeField] private bool _everyFrame = true;
[SerializeField] private int _slot;
[SerializeField] private int _value;
#endregion
#region Unity
/// <summary>
/// Gets the component and applies the RenderQueue value.
/// </summary>
protected override void Start()
{
base.Start();
_renderer = GetComponent<Renderer>();
Apply();
}
/// <summary>
/// Applies the RenderQueue each frame if required.
/// </summary>
private void LateUpdate()
{
if (_everyFrame)
{
Apply();
}
}
#endregion
#region Private Methods
/// <summary>
/// Internal method that applies the RenderQueue value.
/// </summary>
private void Apply()
{
if (_renderer != null)
{
if (_instanceOnly)
{
Material[] materials = _renderer.materials;
if (_slot >= 0 && _slot < materials.Length)
{
materials[_slot].renderQueue = _value;
}
_renderer.materials = materials;
}
else
{
Material[] materials = _renderer.sharedMaterials;
if (_slot >= 0 && _slot < materials.Length)
{
materials[_slot].renderQueue = _value;
}
_renderer.sharedMaterials = materials;
}
}
}
#endregion
#region Private Types & Data
private Renderer _renderer;
#endregion
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 1f664d8d69876084f9aaa68e8d224537
timeCreated: 1527163303
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: