Ejemplo n.º 1
0
        /// <summary>
        ///     Execute the supplied <paramref name="transition" />.
        /// </summary>
        /// <param name="transition">
        ///     Transition to be executed.
        /// </param>
        /// <returns>
        ///     <see langword="true" /> if a transition to a different state was performed
        ///     and the new state is not the exit state,
        ///     <see langword="false" /> if current state remains current.
        /// </returns>
        /// <remarks>
        ///     The method returns <see langword="false" /> when transitioning to the exit state
        ///     to prevent the state machine from looping directly over the enter state in the same
        ///     update tick to allow eventual parent state machines to move on to the next state.
        /// </remarks>
        private bool Execute([NotNull] ITransition transition)
        {
            IState targetState = transition.TargetState;

            if (targetState == _currentState)
            {
                return(false);
            }

            _currentState.Exit();

            transition.Execute(_currentState);
            Transitioning?.Invoke(_currentState, targetState);

            _currentState = targetState;
            _transitions.TryGetValue(_currentState, out _currentTransitions);

            _currentState.Enter();

            _completed = targetState == DefaultState.Exit;
            return(!_completed);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Attempt to trigger a transition with the specified token
        /// </summary>
        /// <param name="token">The token to trigger</param>
        /// <exception cref="ArgumentOutOfRangeException">Token does not exist</exception>
        /// <exception cref="ArgumentOutOfRangeException">No valid transition exists</exception>
        /// <exception cref="ArgumentException">Cannot perform a Pop</exception>
        public void DoTransition(string token)
        {
            // First check that we have that token defined
            if (!Tokens.Contains(token))
            {
                throw new ArgumentOutOfRangeException(nameof(token), token, "Given token is not defined.");
            }

            // And that we have a transition for this token
            if (!Transitions.Any(t => t.Token == token && t.From == CurrentState))
            {
                throw new ArgumentOutOfRangeException(nameof(token), token, $"No transition exists for {CurrentState} + {token}.");
            }

            // Get list of possible transitions...
            var possible = Transitions.Where(t => t.From == CurrentState && t.Token == token).ToList();


            // Check validity of transition
            do
            {
                var transition = possible.MinBy(t =>
                {
                    if (t.TransitionMode != Mode.Pop)
                    {
                        return(0);
                    }
                    var distanceTo = Stack.IndexOf(t.To);
                    return(distanceTo == -1 ? int.MaxValue : distanceTo);
                });
                Transitioning?.Invoke(transition);
                CurrentState.Leave();
                switch (transition.TransitionMode)
                {
                case Mode.Pop:
                    var pop = Stack.IndexOf(transition.To);
                    if (pop == -1)
                    {
                        possible.Remove(transition);
                        continue;
                    }
                    for (var i = 0; i < pop; i++)
                    {
                        Stack.RemoveAt(0);
                    }
                    break;

                case Mode.Push:
                    transition = Transitions.First(t => t.Token == token && t.From == CurrentState);
                    Stack.Insert(0, transition.To);
                    break;

                case Mode.PushPop:
                    transition = Transitions.First(t => t.Token == token && t.From == CurrentState);
                    if (Stack.Count > 0)
                    {
                        Stack.RemoveAt(0);
                    }
                    Stack.Insert(0, transition.To);
                    break;
                }
                CurrentState?.Enter();
                Transitioned?.Invoke(transition);
                return;
            } while (Transitions.Count > 0);
        }