using UnityEngine; public static class GameplayClock { private static bool initialized; private static bool paused; private static double chartStartDspTime; private static double pauseStartDspTime; private static double accumulatedPauseSeconds; private static float chartStartSongTime; public static bool IsInitialized => initialized; public static bool IsPaused => paused; public static float ChartStartSongTime => chartStartSongTime; public static double ChartStartDspTime => chartStartDspTime; public static void Reset() { initialized = false; paused = false; chartStartDspTime = 0d; pauseStartDspTime = 0d; accumulatedPauseSeconds = 0d; chartStartSongTime = 0f; } public static void StartChart(float initialSongTimeSeconds = 0f) { initialized = true; paused = false; chartStartDspTime = AudioSettings.dspTime; pauseStartDspTime = 0d; accumulatedPauseSeconds = 0d; chartStartSongTime = Mathf.Max(0f, initialSongTimeSeconds); } public static void Pause() { if (!initialized || paused) { return; } paused = true; pauseStartDspTime = AudioSettings.dspTime; } public static void Resume() { if (!initialized || !paused) { return; } accumulatedPauseSeconds += AudioSettings.dspTime - pauseStartDspTime; pauseStartDspTime = 0d; paused = false; } public static float NowSongTime { get { if (!initialized) { return 0f; } double currentDsp = paused ? pauseStartDspTime : AudioSettings.dspTime; double elapsed = currentDsp - chartStartDspTime - accumulatedPauseSeconds; return chartStartSongTime + Mathf.Max(0f, (float)elapsed); } } public static float SongTimeFromDsp(double dspTime) { if (!initialized) { return chartStartSongTime; } double effectivePause = accumulatedPauseSeconds; if (paused && dspTime > pauseStartDspTime) { dspTime = pauseStartDspTime; } double elapsed = dspTime - chartStartDspTime - effectivePause; return chartStartSongTime + Mathf.Max(0f, (float)elapsed); } public static float ToAbsoluteChartTime(float songTimelineTimeSeconds) { return chartStartSongTime + songTimelineTimeSeconds; } public static System.Collections.IEnumerator WaitForSeconds(float seconds) { if (seconds <= 0f) { yield break; } if (!initialized) { yield return new UnityEngine.WaitForSeconds(seconds); yield break; } float targetTime = NowSongTime + seconds; while (NowSongTime < targetTime) { yield return null; } } }