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();
}
}
}