using System; using System.Collections.Generic; using System.Threading; #if VCONTAINER_UNITASK_INTEGRATION using Cysharp.Threading.Tasks; #endif namespace VContainer.Unity { sealed class StartableLoopItem : IPlayerLoopItem, IDisposable { readonly IEnumerable entries; readonly EntryPointExceptionHandler exceptionHandler; bool disposed; public StartableLoopItem( IEnumerable entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; foreach (var x in entries) { try { x.Start(); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } } return false; } public void Dispose() => disposed = true; } sealed class PostStartableLoopItem : IPlayerLoopItem, IDisposable { readonly IEnumerable entries; readonly EntryPointExceptionHandler exceptionHandler; bool disposed; public PostStartableLoopItem( IEnumerable entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; foreach (var x in entries) { try { x.PostStart(); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } } return false; } public void Dispose() => disposed = true; } sealed class FixedTickableLoopItem : IPlayerLoopItem, IDisposable { readonly IReadOnlyList entries; readonly EntryPointExceptionHandler exceptionHandler; bool disposed; public FixedTickableLoopItem( IReadOnlyList entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; for (var i = 0; i < entries.Count; i++) { try { entries[i].FixedTick(); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } } return !disposed; } public void Dispose() => disposed = true; } sealed class PostFixedTickableLoopItem : IPlayerLoopItem, IDisposable { readonly IReadOnlyList entries; readonly EntryPointExceptionHandler exceptionHandler; bool disposed; public PostFixedTickableLoopItem( IReadOnlyList entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; for (var i = 0; i < entries.Count; i++) { try { entries[i].PostFixedTick(); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } } return !disposed; } public void Dispose() => disposed = true; } sealed class TickableLoopItem : IPlayerLoopItem, IDisposable { readonly IReadOnlyList entries; readonly EntryPointExceptionHandler exceptionHandler; bool disposed; public TickableLoopItem( IReadOnlyList entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; for (var i = 0; i < entries.Count; i++) { try { entries[i].Tick(); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } } return !disposed; } public void Dispose() => disposed = true; } sealed class PostTickableLoopItem : IPlayerLoopItem, IDisposable { readonly IReadOnlyList entries; readonly EntryPointExceptionHandler exceptionHandler; bool disposed; public PostTickableLoopItem( IReadOnlyList entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; for (var i = 0; i < entries.Count; i++) { try { entries[i].PostTick(); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } } return !disposed; } public void Dispose() => disposed = true; } sealed class LateTickableLoopItem : IPlayerLoopItem, IDisposable { readonly IReadOnlyList entries; readonly EntryPointExceptionHandler exceptionHandler; bool disposed; public LateTickableLoopItem( IReadOnlyList entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; for (var i = 0; i < entries.Count; i++) { try { entries[i].LateTick(); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } } return !disposed; } public void Dispose() => disposed = true; } sealed class PostLateTickableLoopItem : IPlayerLoopItem, IDisposable { readonly IReadOnlyList entries; readonly EntryPointExceptionHandler exceptionHandler; bool disposed; public PostLateTickableLoopItem( IReadOnlyList entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; for (var i = 0; i < entries.Count; i++) { try { entries[i].PostLateTick(); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } } return !disposed; } public void Dispose() => disposed = true; } #if VCONTAINER_UNITASK_INTEGRATION || UNITY_2021_3_OR_NEWER sealed class AsyncStartableLoopItem : IPlayerLoopItem, IDisposable { readonly IEnumerable entries; readonly EntryPointExceptionHandler exceptionHandler; readonly CancellationTokenSource cts = new CancellationTokenSource(); bool disposed; public AsyncStartableLoopItem( IEnumerable entries, EntryPointExceptionHandler exceptionHandler) { this.entries = entries; this.exceptionHandler = exceptionHandler; } public bool MoveNext() { if (disposed) return false; foreach (var x in entries) { #if VCONTAINER_UNITASK_INTEGRATION var task = x.StartAsync(cts.Token); if (exceptionHandler != null) { task.Forget(ex => exceptionHandler.Publish(ex)); } else { task.Forget(); } #else try { var task = x.StartAsync(cts.Token); _ = task.Forget(exceptionHandler); } catch (Exception ex) { if (exceptionHandler == null) throw; exceptionHandler.Publish(ex); } #endif } return false; } public void Dispose() { lock (entries) { if (disposed) return; disposed = true; } cts.Cancel(); cts.Dispose(); } } #endif }