Example #1
0
        /// <inheritdoc />
        public override void Update(GameTime gameTime)
        {
            // This system should load from settings before becoming functional
            if (!Enabled)
            {
                return;
            }

            if (currentSceneInstance != sceneSystem?.SceneInstance)
            {
                // ReSharper disable once PossibleNullReferenceException
                UpdateScene(sceneSystem.SceneInstance);
            }

            if (pendingRebuild && currentSceneInstance != null)
            {
                scriptSystem.AddTask(async() =>
                {
                    // TODO EntityProcessors
                    // Currently have to wait a frame for transformations to update
                    // for example when calling Rebuild from the event that a component was added to the scene, this component will not be in the correct location yet
                    // since the TransformProcessor runs the next frame
                    await scriptSystem.NextFrame();
                    await Rebuild();
                });
                pendingRebuild = false;
            }
        }
Example #2
0
        public static MicroThread AddAction(
            this ScriptSystem scriptSystem,
            Action action,
            TimeSpan delay,
            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.");
            }

            return(scriptSystem.AddTask(DoTask, priority));

            //C# 7 Local function could also use a variable Func<Task> DoEvent = async () => { ... };
            async Task DoTask()
            {
                while (scriptSystem.Game.IsRunning && delay >= TimeSpan.Zero)
                {
                    delay -= scriptSystem.Game.UpdateTime.Elapsed;
                    await scriptSystem.NextFrame();
                }

                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>
        /// 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();
            }
        }
        public async Task Run()
        {
            while (!exited)
            {
                if (nextState != null)
                {
                    if (currentState != null)
                    {
                        await currentState.Exit(nextState);
                    }
                    var previousState = currentState;
                    currentState = nextState;

                    await currentState.Enter(previousState);
                }
                nextState = null;
                currentState?.Update();
                TimeInCurrentState += scriptSystem.Game.UpdateTime.Elapsed.TotalSeconds;
                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();
                }
            }
        }