// Copyright (c) 2025-2026 GeWuYou // SPDX-License-Identifier: Apache-2.0 using GFramework.Core.Abstractions.Coroutine; namespace GFramework.Godot.Coroutine; /// /// Godot 时间源实现,用于为协程调度器提供缩放时间或真实时间数据。 /// /// /// 时间提供函数。 /// 在默认模式下该函数返回“本帧增量”;在绝对时间模式下该函数返回“当前绝对时间(秒)”。 /// /// /// 是否把 返回值解释为绝对时间。 /// 启用后, 会通过相邻两次读数计算 。 /// public sealed class GodotTimeSource(Func timeProvider, bool useAbsoluteTime = false) : ITimeSource { private readonly Func _timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider)); private bool _initialized; private double _lastAbsoluteTime; /// /// 获取当前累计时间。 /// public double CurrentTime { get; private set; } /// /// 获取上一帧的时间增量。 /// public double DeltaTime { get; private set; } /// /// 更新时间源,计算新的时间增量与累计时间。 /// public void Update() { var value = _timeProvider(); if (useAbsoluteTime) { if (!_initialized) { _initialized = true; _lastAbsoluteTime = value; CurrentTime = value; DeltaTime = 0; return; } // 对绝对时间源做单调钳制,避免 provider 回拨后把 CurrentTime 也拉回去。 var nextTime = Math.Max(value, _lastAbsoluteTime); DeltaTime = nextTime - _lastAbsoluteTime; _lastAbsoluteTime = nextTime; CurrentTime = nextTime; return; } DeltaTime = value; CurrentTime += DeltaTime; } /// /// 创建基于 Godot 单调时钟的真实时间源。 /// /// 返回一个不受场景暂停与时间缩放影响的时间源实例。 public static GodotTimeSource CreateRealtime() { return new GodotTimeSource( () => Time.GetTicksUsec() / 1_000_000.0, useAbsoluteTime: true); } /// /// 重置时间源到初始状态。 /// public void Reset() { CurrentTime = 0; DeltaTime = 0; _initialized = false; _lastAbsoluteTime = 0; } }