/// <summary> /// Adds a micro thread function to the <paramref name="scriptSystem"/> that executes after waiting specified delay. /// </summary> /// <param name="scriptSystem">The <see cref="ScriptSystem"/>.</param> /// <param name="action">The micro thread function to execute.</param> /// <param name="delay">The amount of time to wait for.</param> /// <param name="priority">The priority of the micro thread action being added.</param> /// <returns>The <see cref="MicroThread"/>.</returns> /// <exception cref="ArgumentNullException"> If <paramref name="scriptSystem"/> or <paramref name="action"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="delay"/> is less than zero.</exception> /// <remarks> /// If the <paramref name="action"/> is a <see cref="ScriptComponent"/> instance method the micro thread will be automatically stopped if the <see cref="ScriptComponent"/> or <see cref="Entity"/> is removed. /// </remarks> public static MicroThread AddTask( this ScriptSystem scriptSystem, Func <Task> action, TimeSpan delay, long priority = 0L) { if (scriptSystem == null) { throw new ArgumentNullException(nameof(scriptSystem)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } return(scriptSystem.AddTask(DoTask, priority)); //C# 7 Local function could also use a variable Func<Task> DoEvent = async () => { ... }; async Task DoTask() { var scriptDelegateWatcher = new ScriptDelegateWatcher(action); await scriptSystem.WaitFor(delay, scriptDelegateWatcher); if (scriptSystem.Game.IsRunning && scriptDelegateWatcher.IsActive) { await action(); } } }
/// <summary> /// Adds a micro thread function to the <paramref name="scriptSystem"/> that executes after waiting specified delay and repeats execution. /// </summary> /// <param name="scriptSystem">The <see cref="ScriptSystem"/>.</param> /// <param name="action">The micro thread function to execute.</param> /// <param name="delay">The amount of time to wait for.</param> /// <param name="repeatEvery">The amount of time to wait for between repetition.</param> /// <param name="priority">The priority of the micro thread action being added.</param> /// <returns>The <see cref="MicroThread"/>.</returns> /// <exception cref="ArgumentNullException"> If <paramref name="scriptSystem"/> or <paramref name="action"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="delay"/> or <paramref name="repeatEvery"/> is less than zero.</exception> /// <remarks> /// If the <paramref name="action"/> is a <see cref="ScriptComponent"/> instance method the micro thread will be automatically stopped if the <see cref="ScriptComponent"/> or <see cref="Entity"/> is removed. /// </remarks> public static MicroThread AddAction( this ScriptSystem scriptSystem, Action action, TimeSpan delay, TimeSpan repeatEvery, long priority = 0L) { if (scriptSystem == null) { throw new ArgumentNullException(nameof(scriptSystem)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } if (delay <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(delay), "Must be greater than zero."); } if (repeatEvery <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(repeatEvery), "Must be greater than zero."); } return(scriptSystem.AddTask(DoTask, priority)); //C# 7 Local function could also use a variable Func<Task> DoEvent = async () => { ... }; async Task DoTask() { var elapsedTime = new TimeSpan(0); var scriptDelegateWatcher = new ScriptDelegateWatcher(action); while (scriptSystem.Game.IsRunning && scriptDelegateWatcher.IsActive) { elapsedTime += scriptSystem.Game.UpdateTime.Elapsed; if (elapsedTime >= delay) { elapsedTime -= delay; delay = repeatEvery; action(); } await scriptSystem.NextFrame(); } } }
/// <summary> /// Adds a micro thread function to the <paramref name="scriptSystem"/> that executes after waiting specified delay and repeats execution. /// </summary> /// <param name="scriptSystem">The <see cref="ScriptSystem"/>.</param> /// <param name="action">The micro thread function to execute. The parameter is the progress over time from 0.0f to 1.0f.</param> /// <param name="duration">The duration of the time to execute the micro thread function for.</param> /// <param name="priority">The priority of the micro thread action being added.</param> /// <returns>The <see cref="MicroThread"/>.</returns> /// <exception cref="ArgumentNullException"> If <paramref name="scriptSystem"/> or <paramref name="action"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="duration"/> is less than zero.</exception> /// <remarks> /// If the <paramref name="action"/> is a <see cref="ScriptComponent"/> instance method the micro thread will be automatically stopped if the <see cref="ScriptComponent"/> or <see cref="Entity"/> is removed. /// </remarks> public static MicroThread AddOverTimeAction( this ScriptSystem scriptSystem, Action <float> action, TimeSpan duration, long priority = 0L) { if (scriptSystem == null) { throw new ArgumentNullException(nameof(scriptSystem)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } if (duration <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(duration), "Must be greater than zero."); } return(scriptSystem.AddTask(DoTask, priority)); //C# 7 Local function could also use a variable Func<Task> DoEvent = async () => { ... }; async Task DoTask() { var elapsedTime = new TimeSpan(0); var scriptDelegateWatcher = new ScriptDelegateWatcher(action); while (scriptSystem.Game.IsRunning && scriptDelegateWatcher.IsActive) { elapsedTime += scriptSystem.Game.UpdateTime.Elapsed; if (elapsedTime >= duration) { action(1.0f); break; } else { var progress = (float)(elapsedTime.TotalSeconds / duration.TotalSeconds); action(progress); } await scriptSystem.NextFrame(); } } }
/// <summary> /// Adds a micro thread function to the <paramref name="scriptSystem"/> that executes when the event is published. /// </summary> /// <typeparam name="T">The type of the event handler parameter.</typeparam> /// <param name="scriptSystem">The <see cref="ScriptSystem"/>.</param> /// <param name="receiver">The event reciever to listen to for.</param> /// <param name="action">The micro thread function to execute.</param> /// <param name="priority">The priority of the micro thread action being added.</param> /// <returns>The <see cref="MicroThread"/>.</returns> /// <exception cref="ArgumentNullException"> If <paramref name="scriptSystem"/>, <paramref name="receiver"/> or <paramref name="action"/> is <see langword="null"/>.</exception> /// <remarks> /// If the <paramref name="action"/> is a <see cref="ScriptComponent"/> instance method the micro thread will be automatically stopped if the <see cref="ScriptComponent"/> or <see cref="Entity"/> is removed. /// </remarks> public static MicroThread AddOnEventTask <T>( this ScriptSystem scriptSystem, EventReceiver <T> receiver, Func <T, Task> action, long priority = 0L) { if (scriptSystem == null) { throw new ArgumentNullException(nameof(scriptSystem)); } if (receiver == null) { throw new ArgumentNullException(nameof(receiver)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } return(scriptSystem.AddTask(DoEvent, priority)); //C# 7 Local function could also use a variable Func<Task> DoEvent = async () => { ... }; async Task DoEvent() { var scriptDelegateWatcher = new ScriptDelegateWatcher(action); while (scriptSystem.Game.IsRunning && scriptDelegateWatcher.IsActive) { if (receiver.TryReceive(out var data)) { await action(data); } await scriptSystem.NextFrame(); } } }
/// <summary> /// Waits for the specified delay <paramref name="delay"/> . /// </summary> /// <param name="scriptSystem">The <see cref="ScriptSystem"/>.</param> /// <param name="delay">The amount of time to wait.</param> /// <param name="scriptDelegateWatcher">Allows to stop waiting if <see cref="ScriptComponent"/> is not active.</param> /// <returns>The <see cref="Task"/> to await.</returns> internal static async Task WaitFor(this ScriptSystem scriptSystem, TimeSpan delay, ScriptDelegateWatcher scriptDelegateWatcher) { if (scriptSystem == null) { throw new ArgumentNullException(nameof(scriptSystem)); } if (delay <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(delay), "Must be greater than zero."); } while (scriptSystem.Game.IsRunning && scriptDelegateWatcher.IsActive && delay >= TimeSpan.Zero) { delay -= scriptSystem.Game.UpdateTime.Elapsed; await scriptSystem.NextFrame(); } }