| #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member | 
|   | 
| using System; | 
| using System.Threading; | 
| using UnityEngine; | 
|   | 
| namespace Cysharp.Threading.Tasks.Triggers | 
| { | 
|     public abstract class AsyncTriggerBase<T> : MonoBehaviour, IUniTaskAsyncEnumerable<T> | 
|     { | 
|         TriggerEvent<T> triggerEvent; | 
|   | 
|         internal protected bool calledAwake; | 
|         internal protected bool calledDestroy; | 
|   | 
|         void Awake() | 
|         { | 
|             calledAwake = true; | 
|         } | 
|   | 
|         void OnDestroy() | 
|         { | 
|             if (calledDestroy) return; | 
|             calledDestroy = true; | 
|   | 
|             triggerEvent.SetCompleted(); | 
|         } | 
|   | 
|         internal void AddHandler(ITriggerHandler<T> handler) | 
|         { | 
|             if (!calledAwake) | 
|             { | 
|                 PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this)); | 
|             } | 
|   | 
|             triggerEvent.Add(handler); | 
|         } | 
|   | 
|         internal void RemoveHandler(ITriggerHandler<T> handler) | 
|         { | 
|             if (!calledAwake) | 
|             { | 
|                 PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this)); | 
|             } | 
|   | 
|             triggerEvent.Remove(handler); | 
|         } | 
|   | 
|         protected void RaiseEvent(T value) | 
|         { | 
|             triggerEvent.SetResult(value); | 
|         } | 
|   | 
|         public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default) | 
|         { | 
|             return new AsyncTriggerEnumerator(this, cancellationToken); | 
|         } | 
|   | 
|         sealed class AsyncTriggerEnumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, ITriggerHandler<T> | 
|         { | 
|             static Action<object> cancellationCallback = CancellationCallback; | 
|   | 
|             readonly AsyncTriggerBase<T> parent; | 
|             CancellationToken cancellationToken; | 
|             CancellationTokenRegistration registration; | 
|             bool called; | 
|             bool isDisposed; | 
|   | 
|             public AsyncTriggerEnumerator(AsyncTriggerBase<T> parent, CancellationToken cancellationToken) | 
|             { | 
|                 this.parent = parent; | 
|                 this.cancellationToken = cancellationToken; | 
|             } | 
|   | 
|             public void OnCanceled(CancellationToken cancellationToken = default) | 
|             { | 
|                 completionSource.TrySetCanceled(cancellationToken); | 
|             } | 
|   | 
|             public void OnNext(T value) | 
|             { | 
|                 Current = value; | 
|                 completionSource.TrySetResult(true); | 
|             } | 
|   | 
|             public void OnCompleted() | 
|             { | 
|                 completionSource.TrySetResult(false); | 
|             } | 
|   | 
|             public void OnError(Exception ex) | 
|             { | 
|                 completionSource.TrySetException(ex); | 
|             } | 
|   | 
|             static void CancellationCallback(object state) | 
|             { | 
|                 var self = (AsyncTriggerEnumerator)state; | 
|                 self.DisposeAsync().Forget(); // sync | 
|   | 
|                 self.completionSource.TrySetCanceled(self.cancellationToken); | 
|             } | 
|   | 
|             public T Current { get; private set; } | 
|             ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; } | 
|             ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; } | 
|   | 
|             public UniTask<bool> MoveNextAsync() | 
|             { | 
|                 cancellationToken.ThrowIfCancellationRequested(); | 
|                 completionSource.Reset(); | 
|   | 
|                 if (!called) | 
|                 { | 
|                     called = true; | 
|   | 
|                     TaskTracker.TrackActiveTask(this, 3); | 
|                     parent.AddHandler(this); | 
|                     if (cancellationToken.CanBeCanceled) | 
|                     { | 
|                         registration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this); | 
|                     } | 
|                 } | 
|   | 
|                 return new UniTask<bool>(this, completionSource.Version); | 
|             } | 
|   | 
|             public UniTask DisposeAsync() | 
|             { | 
|                 if (!isDisposed) | 
|                 { | 
|                     isDisposed = true; | 
|                     TaskTracker.RemoveTracking(this); | 
|                     registration.Dispose(); | 
|                     parent.RemoveHandler(this); | 
|                 } | 
|   | 
|                 return default; | 
|             } | 
|         } | 
|   | 
|         class AwakeMonitor : IPlayerLoopItem | 
|         { | 
|             readonly AsyncTriggerBase<T> trigger; | 
|   | 
|             public AwakeMonitor(AsyncTriggerBase<T> trigger) | 
|             { | 
|                 this.trigger = trigger; | 
|             } | 
|   | 
|             public bool MoveNext() | 
|             { | 
|                 if (trigger.calledAwake) return false; | 
|                 if (trigger == null) | 
|                 { | 
|                     trigger.OnDestroy(); | 
|                     return false; | 
|                 } | 
|                 return true; | 
|             } | 
|         } | 
|     } | 
|   | 
|     public interface IAsyncOneShotTrigger | 
|     { | 
|         UniTask OneShotAsync(); | 
|     } | 
|   | 
|     public partial class AsyncTriggerHandler<T> : IAsyncOneShotTrigger | 
|     { | 
|         UniTask IAsyncOneShotTrigger.OneShotAsync() | 
|         { | 
|             core.Reset(); | 
|             return new UniTask((IUniTaskSource)this, core.Version); | 
|         } | 
|     } | 
|   | 
|     public sealed partial class AsyncTriggerHandler<T> : IUniTaskSource<T>, ITriggerHandler<T>, IDisposable | 
|     { | 
|         static Action<object> cancellationCallback = CancellationCallback; | 
|   | 
|         readonly AsyncTriggerBase<T> trigger; | 
|   | 
|         CancellationToken cancellationToken; | 
|         CancellationTokenRegistration registration; | 
|         bool isDisposed; | 
|         bool callOnce; | 
|   | 
|         UniTaskCompletionSourceCore<T> core; | 
|   | 
|         internal CancellationToken CancellationToken => cancellationToken; | 
|   | 
|         ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; } | 
|         ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; } | 
|   | 
|         internal AsyncTriggerHandler(AsyncTriggerBase<T> trigger, bool callOnce) | 
|         { | 
|             if (cancellationToken.IsCancellationRequested) | 
|             { | 
|                 isDisposed = true; | 
|                 return; | 
|             } | 
|   | 
|             this.trigger = trigger; | 
|             this.cancellationToken = default; | 
|             this.registration = default; | 
|             this.callOnce = callOnce; | 
|   | 
|             trigger.AddHandler(this); | 
|   | 
|             TaskTracker.TrackActiveTask(this, 3); | 
|         } | 
|   | 
|         internal AsyncTriggerHandler(AsyncTriggerBase<T> trigger, CancellationToken cancellationToken, bool callOnce) | 
|         { | 
|             if (cancellationToken.IsCancellationRequested) | 
|             { | 
|                 isDisposed = true; | 
|                 return; | 
|             } | 
|   | 
|             this.trigger = trigger; | 
|             this.cancellationToken = cancellationToken; | 
|             this.callOnce = callOnce; | 
|   | 
|             trigger.AddHandler(this); | 
|   | 
|             if (cancellationToken.CanBeCanceled) | 
|             { | 
|                 registration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this); | 
|             } | 
|   | 
|             TaskTracker.TrackActiveTask(this, 3); | 
|         } | 
|   | 
|         static void CancellationCallback(object state) | 
|         { | 
|             var self = (AsyncTriggerHandler<T>)state; | 
|             self.Dispose(); | 
|   | 
|             self.core.TrySetCanceled(self.cancellationToken); | 
|         } | 
|   | 
|         public void Dispose() | 
|         { | 
|             if (!isDisposed) | 
|             { | 
|                 isDisposed = true; | 
|                 TaskTracker.RemoveTracking(this); | 
|                 registration.Dispose(); | 
|                 trigger.RemoveHandler(this); | 
|             } | 
|         } | 
|   | 
|         T IUniTaskSource<T>.GetResult(short token) | 
|         { | 
|             try | 
|             { | 
|                 return core.GetResult(token); | 
|             } | 
|             finally | 
|             { | 
|                 if (callOnce) | 
|                 { | 
|                     Dispose(); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         void ITriggerHandler<T>.OnNext(T value) | 
|         { | 
|             core.TrySetResult(value); | 
|         } | 
|   | 
|         void ITriggerHandler<T>.OnCanceled(CancellationToken cancellationToken) | 
|         { | 
|             core.TrySetCanceled(cancellationToken); | 
|         } | 
|   | 
|         void ITriggerHandler<T>.OnCompleted() | 
|         { | 
|             core.TrySetCanceled(CancellationToken.None); | 
|         } | 
|   | 
|         void ITriggerHandler<T>.OnError(Exception ex) | 
|         { | 
|             core.TrySetException(ex); | 
|         } | 
|   | 
|         void IUniTaskSource.GetResult(short token) | 
|         { | 
|             ((IUniTaskSource<T>)this).GetResult(token); | 
|         } | 
|   | 
|         UniTaskStatus IUniTaskSource.GetStatus(short token) | 
|         { | 
|             return core.GetStatus(token); | 
|         } | 
|   | 
|         UniTaskStatus IUniTaskSource.UnsafeGetStatus() | 
|         { | 
|             return core.UnsafeGetStatus(); | 
|         } | 
|   | 
|         void IUniTaskSource.OnCompleted(Action<object> continuation, object state, short token) | 
|         { | 
|             core.OnCompleted(continuation, state, token); | 
|         } | 
|     } | 
| } |