using System; using System.Collections.Generic; using System.Linq; using ModestTree; using ModestTree.Util; #if ZEN_SIGNALS_ADD_UNIRX using UniRx; #endif namespace Zenject { public class TickableManager { [Inject(Optional = true, Source = InjectSources.Local)] readonly List _tickables = null; [Inject(Optional = true, Source = InjectSources.Local)] readonly List _fixedTickables = null; [Inject(Optional = true, Source = InjectSources.Local)] readonly List _lateTickables = null; [Inject(Optional = true, Source = InjectSources.Local)] readonly List> _priorities = null; [Inject(Optional = true, Id = "Fixed", Source = InjectSources.Local)] readonly List> _fixedPriorities = null; [Inject(Optional = true, Id = "Late", Source = InjectSources.Local)] readonly List> _latePriorities = null; #if ZEN_SIGNALS_ADD_UNIRX readonly Subject _tickStream = new Subject(); readonly Subject _lateTickStream = new Subject(); readonly Subject _fixedTickStream = new Subject(); #endif readonly TickablesTaskUpdater _updater = new TickablesTaskUpdater(); readonly FixedTickablesTaskUpdater _fixedUpdater = new FixedTickablesTaskUpdater(); readonly LateTickablesTaskUpdater _lateUpdater = new LateTickablesTaskUpdater(); bool _isPaused; [Inject] public TickableManager() { } #if ZEN_SIGNALS_ADD_UNIRX public IObservable TickStream { get { return _tickStream; } } public IObservable LateTickStream { get { return _lateTickStream; } } public IObservable FixedTickStream { get { return _fixedTickStream; } } #endif public IEnumerable Tickables { get { return _tickables; } } public bool IsPaused { get { return _isPaused; } set { _isPaused = value; } } [Inject] public void Initialize() { InitTickables(); InitFixedTickables(); InitLateTickables(); } void InitFixedTickables() { foreach (var type in _fixedPriorities.Select(x => x.First)) { Assert.That(type.DerivesFrom(), "Expected type '{0}' to drive from IFixedTickable while checking priorities in TickableHandler", type); } foreach (var tickable in _fixedTickables) { // Note that we use zero for unspecified priority // This is nice because you can use negative or positive for before/after unspecified var matches = _fixedPriorities.Where(x => tickable.GetType().DerivesFromOrEqual(x.First)).Select(x => x.Second).ToList(); int priority = matches.IsEmpty() ? 0 : matches.Distinct().Single(); _fixedUpdater.AddTask(tickable, priority); } } void InitTickables() { foreach (var type in _priorities.Select(x => x.First)) { Assert.That(type.DerivesFrom(), "Expected type '{0}' to drive from ITickable while checking priorities in TickableHandler", type); } foreach (var tickable in _tickables) { // Note that we use zero for unspecified priority // This is nice because you can use negative or positive for before/after unspecified var matches = _priorities.Where(x => tickable.GetType().DerivesFromOrEqual(x.First)).Select(x => x.Second).ToList(); int priority = matches.IsEmpty() ? 0 : matches.Distinct().Single(); _updater.AddTask(tickable, priority); } } void InitLateTickables() { foreach (var type in _latePriorities.Select(x => x.First)) { Assert.That(type.DerivesFrom(), "Expected type '{0}' to drive from ILateTickable while checking priorities in TickableHandler", type); } foreach (var tickable in _lateTickables) { // Note that we use zero for unspecified priority // This is nice because you can use negative or positive for before/after unspecified var matches = _latePriorities.Where(x => tickable.GetType().DerivesFromOrEqual(x.First)).Select(x => x.Second).ToList(); int priority = matches.IsEmpty() ? 0 : matches.Distinct().Single(); _lateUpdater.AddTask(tickable, priority); } } public void Add(ITickable tickable, int priority) { _updater.AddTask(tickable, priority); } public void Add(ITickable tickable) { Add(tickable, 0); } public void AddLate(ILateTickable tickable, int priority) { _lateUpdater.AddTask(tickable, priority); } public void AddLate(ILateTickable tickable) { AddLate(tickable, 0); } public void AddFixed(IFixedTickable tickable, int priority) { _fixedUpdater.AddTask(tickable, priority); } public void AddFixed(IFixedTickable tickable) { _fixedUpdater.AddTask(tickable, 0); } public void Remove(ITickable tickable) { _updater.RemoveTask(tickable); } public void RemoveLate(ILateTickable tickable) { _lateUpdater.RemoveTask(tickable); } public void RemoveFixed(IFixedTickable tickable) { _fixedUpdater.RemoveTask(tickable); } public void Update() { if(IsPaused) { return; } _updater.OnFrameStart(); _updater.UpdateAll(); #if ZEN_SIGNALS_ADD_UNIRX _tickStream.OnNext(Unit.Default); #endif } public void FixedUpdate() { if(IsPaused) { return; } _fixedUpdater.OnFrameStart(); _fixedUpdater.UpdateAll(); #if ZEN_SIGNALS_ADD_UNIRX _fixedTickStream.OnNext(Unit.Default); #endif } public void LateUpdate() { if(IsPaused) { return; } _lateUpdater.OnFrameStart(); _lateUpdater.UpdateAll(); #if ZEN_SIGNALS_ADD_UNIRX _lateTickStream.OnNext(Unit.Default); #endif } } }