Files
UnityPackages/Assets/Common/Timer/Runtime/Stopwatch.cs
2025-12-01 12:36:01 +08:00

120 lines
3.4 KiB
C#

using System;
using TriInspector;
using UnityEngine;
using UnityEngine.Serialization;
namespace Common.Timer.Runtime
{
[Serializable]
public class Stopwatch : Timer, IStopwatch
{
public override float CurrentTime
{
get
{
currentTime = Mathf.Clamp(currentTime, 0f, Duration);
return currentTime;
}
set => currentTime = Mathf.Clamp(value, 0f, Duration);
}
[Title("Settings (Stopwatch)")]
[SerializeField]
[FormerlySerializedAs("_duration")]
protected float duration;
[Group("Internal"), ShowInInspector, DisableInEditMode]
public virtual float Duration
{
get
{
duration = Mathf.Max(0.001f, duration);
return duration;
}
set => duration = Mathf.Max(0.001f, value);
}
[SerializeField]
[FormerlySerializedAs("_deactivateOnTimeReached")]
protected bool deactivateOnTimeReached;
public bool DeactivateOnTimeReached
{
get => deactivateOnTimeReached;
set => deactivateOnTimeReached = value;
}
[Group("Internal"), ShowInInspector, DisableInEditMode]
public virtual float RemainingTime
{
get => Mathf.Clamp(Duration - CurrentTime, 0f, Duration);
set => CurrentTime = Mathf.Clamp(Duration - value, 0f, Duration);
}
[Group("Internal"), ShowInInspector, DisableInEditMode]
public virtual float Progress
{
get => Duration == 0f ? 0f : Mathf.Clamp(CurrentTime / Duration, 0f, 1f);
set => CurrentTime = Mathf.Clamp(Duration * value, 0f, Duration);
}
[Group("Internal"), ReadOnly, ShowInInspector, DisableInEditMode]
public virtual bool IsTimeReached => CurrentTime >= Duration;
public event Action OnTimeReached;
public Stopwatch(bool isActive, float duration, bool deactivateOnTimeReached = false) : base(isActive)
{
this.duration = duration;
this.deactivateOnTimeReached = deactivateOnTimeReached;
}
public override void Tick()
{
if (IsTimeReached) return;
base.Tick();
if (!IsActive) return;
if (IsTimeReached) EndTime();
}
public override void SetTime(float value)
{
CurrentTime = value;
if (IsTimeReached) EndTime();
}
public virtual void SetDuration(float value)
{
Duration = value;
if (IsTimeReached) EndTime();
}
public virtual void SetRemainingTime(float value)
{
RemainingTime = value;
if (IsTimeReached) EndTime();
}
public virtual void SetProgress(float value)
{
Progress = value;
if (IsTimeReached) EndTime();
}
public virtual void EndTime()
{
currentTime = Duration;
InvokeOnTimeReached();
if (DeactivateOnTimeReached) Deactivate();
}
protected virtual void InvokeOnTimeReached()
{
OnTimeReached?.Invoke();
}
#if UNITY_EDITOR
[Group("Debug"), Button("End Time"), HideInEditMode]
private void EndTimer_Editor() => EndTime();
#endif
}
}