Files
2025-05-15 15:37:45 +08:00

154 lines
4.5 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Playables;
// ScreenFx © NullTale - https://twitter.com/NullTale/
namespace ScreenFx
{
[DefaultExecutionOrder(-10)]
[RequireComponent(typeof(PlayableDirector))]
public class DirectorState : MonoBehaviour
{
[Tooltip("Speed relative")]
public double m_Speed = 1d;
[Tooltip("Up speed multiplier")]
public double m_UpSpeed = 1d;
[Tooltip("Down speed multiplier")]
public double m_DownSpeed = 1d;
[Tooltip("Normalized Up move interpolation")]
public float m_UpLerp;
[Tooltip("Normalized Down move interpolation")]
public float m_DownLerp;
[Tooltip("Director time remap")]
public Optional<AnimationCurve> m_Interpolation;
private PlayableDirector m_Director;
private double m_Time;
private double m_Duration;
[Tooltip("Use unscaled time")]
public bool m_UnScaledTime = true;
[SerializeField] [Range(0, 1)]
private double m_DesiredTime;
public double DesiredTime
{
get => m_DesiredTime;
set
{
var val = Math.Clamp(value, 0, 1);
if (val == m_DesiredTime)
return;
m_DesiredTime = val;
enabled = true;
}
}
public bool IsOn
{
get => m_DesiredTime == 1d;
set => SetTime(value);
}
public bool IsComplete => enabled == false;
public PlayableDirector Director => m_Director;
// =======================================================================
public void SetTimeImmediate(float normalizedTime)
{
#if UNITY_EDITOR
if (Application.isPlaying == false && m_Director == null)
m_Director = GetComponent<PlayableDirector>();
#endif
DesiredTime = normalizedTime;
m_Time = m_DesiredTime * m_Duration;
m_Director.time = m_Interpolation.Enabled ? m_Interpolation.Value.Evaluate((float)(m_Time / m_Duration)) * m_Duration : m_Time;
m_Director.Evaluate();
}
public void SetTime(float normalizedTime)
{
DesiredTime = normalizedTime;
}
public void SetTime(bool state)
{
DesiredTime = state ? 1d : 0d;
}
private void Awake()
{
m_Director = GetComponent<PlayableDirector>();
m_Director.Stop();
m_Duration = m_Director.duration;
m_Time = m_Duration * DesiredTime;
m_Director.timeUpdateMode = DirectorUpdateMode.Manual;
m_Director.extrapolationMode = DirectorWrapMode.Hold;
}
private void OnEnable()
{
m_Director.time = m_Time;
m_Director.Evaluate();
}
private void OnValidate()
{
if (m_Director == null)
return;
if (m_Director.duration * DesiredTime != m_Director.time)
enabled = true;
}
private void Update()
{
var desiredTime = m_Director.duration * DesiredTime;
if (m_Time == desiredTime)
{
enabled = false;
return;
}
var deltaTime = m_UnScaledTime ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
if (desiredTime > m_Director.time)
{
m_Time += m_UpSpeed * m_Speed * deltaTime;
m_Time = Mathf.Lerp((float)m_Time, (float)desiredTime, m_UpLerp * deltaTime);
if (m_Time > desiredTime)
m_Time = desiredTime;
}
else
{
m_Time -= m_DownSpeed * m_Speed * deltaTime;
m_Time = Mathf.Lerp((float)m_Time, (float)desiredTime, m_DownLerp * deltaTime);
if (m_Time < desiredTime)
m_Time = desiredTime;
}
m_Director.time = m_Interpolation.Enabled ? m_Interpolation.Value.Evaluate((float)(m_Time / m_Duration)) * m_Duration : m_Time;
m_Director.Evaluate();
}
public void On()
{
SetTime(true);
}
public void Off()
{
SetTime(false);
}
}
}