2020-03-22 22:28:19 +01:00
using System ;
2019-06-22 17:24:50 +02:00
using System.Collections.Generic ;
2020-12-20 17:12:43 +01:00
using System.Diagnostics ;
2019-06-22 17:24:50 +02:00
namespace Coroutine {
2020-06-13 03:12:26 +02:00
/// <summary>
/// A reference to a currently running coroutine.
2021-03-18 16:38:34 +01:00
/// This is returned by <see cref="CoroutineHandler.Start(System.Collections.Generic.IEnumerator{Coroutine.Wait},string,int)"/>.
2020-06-13 03:12:26 +02:00
/// </summary>
2021-03-16 19:07:28 +01:00
public class ActiveCoroutine : IComparable < ActiveCoroutine > {
2019-06-22 17:24:50 +02:00
2020-06-13 02:58:54 +02:00
private readonly IEnumerator < Wait > enumerator ;
2020-12-20 17:12:43 +01:00
private readonly Stopwatch stopwatch ;
2020-06-13 02:58:54 +02:00
private Wait current ;
2020-06-13 03:12:26 +02:00
/// <summary>
/// This property stores whether or not this active coroutine is finished.
/// A coroutine is finished if all of its waits have passed, or if it <see cref="WasCanceled"/>.
/// </summary>
2020-02-28 22:27:38 +01:00
public bool IsFinished { get ; private set ; }
2020-06-13 03:12:26 +02:00
/// <summary>
/// This property stores whether or not this active coroutine was cancelled using <see cref="Cancel"/>.
/// </summary>
2020-03-22 22:28:19 +01:00
public bool WasCanceled { get ; private set ; }
2020-06-13 03:12:26 +02:00
/// <summary>
2020-12-20 17:12:43 +01:00
/// The total amount of time that <see cref="MoveNext"/> took.
/// This is the amount of time that this active coroutine took for the entirety of its "steps", or yield statements.
/// </summary>
public TimeSpan TotalMoveNextTime { get ; private set ; }
/// <summary>
/// The total amount of times that <see cref="MoveNext"/> was invoked.
/// This is the amount of "steps" in your coroutine, or the amount of yield statements.
/// </summary>
public int MoveNextCount { get ; private set ; }
/// <summary>
2021-01-01 06:21:17 +01:00
/// The maximum amount of time that <see cref="MoveNext"/> took.
/// This is the maximum amount of time that each "step", or each yield statement, of this coroutine took to execute.
/// </summary>
public TimeSpan MaxMoveNextTime { get ; private set ; }
/// <summary>
2020-12-20 17:12:43 +01:00
/// The average amount of time that <see cref="MoveNext"/> took.
/// This is the average amount of time that each "step", or each yield statement, of this coroutine took to execute.
/// </summary>
public TimeSpan AverageMoveNextTime = > new TimeSpan ( this . TotalMoveNextTime . Ticks / this . MoveNextCount ) ;
/// <summary>
2020-06-13 03:12:26 +02:00
/// An event that gets fired when this active coroutine finishes or gets cancelled.
/// When this event is called, <see cref="IsFinished"/> is always true.
/// </summary>
public event FinishCallback OnFinished ;
2020-12-20 17:12:43 +01:00
/// <summary>
/// The name of this coroutine.
/// When not specified on startup of this coroutine, the name defaults to an empty string.
/// </summary>
public readonly string Name ;
2021-03-16 19:07:28 +01:00
/// <summary>
/// The priority of this coroutine. The higher the priority, the earlier it is advanced compared to other coroutines that advance around the same time.
/// When not specified at startup of this coroutine, the priority defaults to 0.
/// </summary>
public readonly int Priority ;
2019-06-22 17:24:50 +02:00
2021-03-16 19:07:28 +01:00
internal ActiveCoroutine ( IEnumerator < Wait > enumerator , string name , int priority , Stopwatch stopwatch ) {
2019-06-22 17:24:50 +02:00
this . enumerator = enumerator ;
2020-12-20 17:12:43 +01:00
this . Name = name ;
2021-03-16 19:07:28 +01:00
this . Priority = priority ;
this . stopwatch = stopwatch ;
2019-06-22 17:24:50 +02:00
}
2020-06-13 03:12:26 +02:00
/// <summary>
/// Cancels this coroutine, causing all subsequent <see cref="Wait"/>s and any code in between to be skipped.
/// </summary>
/// <returns>Whether the cancellation was successful, or this coroutine was already cancelled or finished</returns>
2020-03-26 02:30:29 +01:00
public bool Cancel ( ) {
if ( this . IsFinished | | this . WasCanceled )
return false ;
this . WasCanceled = true ;
this . IsFinished = true ;
this . OnFinished ? . Invoke ( this ) ;
return true ;
}
2020-02-28 22:27:38 +01:00
internal bool Tick ( double deltaSeconds ) {
2020-03-26 02:30:29 +01:00
if ( ! this . WasCanceled ) {
2020-06-13 02:58:54 +02:00
if ( this . current . Tick ( deltaSeconds ) )
2020-03-26 02:30:29 +01:00
this . MoveNext ( ) ;
}
2020-02-28 22:27:38 +01:00
return this . IsFinished ;
2019-06-22 17:24:50 +02:00
}
2020-02-28 22:27:38 +01:00
internal bool OnEvent ( Event evt ) {
2020-03-26 02:30:29 +01:00
if ( ! this . WasCanceled ) {
2020-06-13 02:58:54 +02:00
if ( this . current . OnEvent ( evt ) )
2020-03-26 02:30:29 +01:00
this . MoveNext ( ) ;
}
2020-02-28 22:27:38 +01:00
return this . IsFinished ;
2019-06-22 17:24:50 +02:00
}
2020-06-13 02:58:54 +02:00
internal bool MoveNext ( ) {
2020-12-20 17:12:43 +01:00
this . stopwatch . Restart ( ) ;
var result = this . enumerator . MoveNext ( ) ;
this . stopwatch . Stop ( ) ;
this . TotalMoveNextTime + = this . stopwatch . Elapsed ;
2021-03-16 19:10:25 +01:00
if ( this . stopwatch . Elapsed > this . MaxMoveNextTime )
2021-01-01 06:21:17 +01:00
this . MaxMoveNextTime = this . stopwatch . Elapsed ;
2020-12-20 17:12:43 +01:00
this . MoveNextCount + + ;
if ( ! result ) {
2020-03-26 02:30:29 +01:00
this . IsFinished = true ;
this . OnFinished ? . Invoke ( this ) ;
2020-06-13 02:58:54 +02:00
return false ;
2020-03-26 02:30:29 +01:00
}
2020-06-13 02:58:54 +02:00
this . current = this . enumerator . Current ;
return true ;
2020-03-22 22:28:19 +01:00
}
2020-06-13 02:58:54 +02:00
internal bool IsWaitingForEvent ( ) {
return this . current . IsWaitingForEvent ( ) ;
2019-06-22 17:24:50 +02:00
}
2020-06-13 03:12:26 +02:00
/// <summary>
/// A delegate method used by <see cref="ActiveCoroutine.OnFinished"/>.
/// </summary>
/// <param name="coroutine">The coroutine that finished</param>
2020-03-26 02:30:29 +01:00
public delegate void FinishCallback ( ActiveCoroutine coroutine ) ;
2020-03-22 22:28:19 +01:00
2021-03-16 19:07:28 +01:00
/// <inheritdoc />
public int CompareTo ( ActiveCoroutine other ) {
2021-03-17 01:13:57 +01:00
return other . Priority . CompareTo ( this . Priority ) ;
2021-03-16 19:07:28 +01:00
}
2019-06-22 17:24:50 +02:00
}
}