using System; using System.Timers; using EcsRx.Extensions; using EcsRx.MicroRx.Subjects; namespace EcsRx.Scheduling { /// /// This default implementation only provides millisecond level accuracy /// however in most cases it will instead use a platform specific implementation /// which will be as accurate as the underlying platform provides /// public class DefaultUpdateScheduler : IUpdateScheduler { private readonly Timer _timer; private DateTime _previousDateTime; private readonly Subject _onPreUpdate = new Subject(); private readonly Subject _onUpdate = new Subject(); private readonly Subject _onPostUpdate = new Subject(); public ElapsedTime ElapsedTime { get; private set; } public IObservable OnUpdate => _onUpdate; public IObservable OnPreUpdate => _onPreUpdate; public IObservable OnPostUpdate => _onPostUpdate; public DefaultUpdateScheduler(int desiredFps = 60) { _timer = new Timer { Interval = 1000f / desiredFps }; _timer.Elapsed += UpdateTick; _previousDateTime = DateTime.Now; _timer.Start(); } private void UpdateTick(object sender, ElapsedEventArgs e) { var deltaTime = e.SignalTime - _previousDateTime; var totalTime = ElapsedTime.TotalTime + deltaTime; ElapsedTime = new ElapsedTime(deltaTime, totalTime); _onPreUpdate.OnNext(ElapsedTime); _onUpdate.OnNext(ElapsedTime); _onPostUpdate.OnNext(ElapsedTime); _previousDateTime = e.SignalTime; } public void Dispose() { _timer.Stop(); _timer.Dispose(); _onUpdate.Dispose(); _onPreUpdate.Dispose(); _onPostUpdate.Dispose(); } } }