Beispiel #1
0
        /// <summary>
        /// Raises the <see cref="Exit"/> event.
        /// </summary>
        /// <param name="eventArgs">
        /// <see cref="StateEventArgs"/> object that provides the arguments for the event.
        /// </param>
        /// <remarks>
        /// <strong>Notes to Inheritors:</strong> When overriding <see cref="OnExit"/> in a derived
        /// class, be sure to call the base class's <see cref="OnExit"/> method so that registered
        /// delegates receive the event.
        /// </remarks>
        protected virtual void OnExit(StateEventArgs eventArgs)
        {
            var handler = Exit;

            if (handler != null)
            {
                handler(this, eventArgs);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Raises the <see cref="Action"/> event.
        /// </summary>
        /// <param name="eventArgs">
        /// <see cref="StateEventArgs"/> object that provides the arguments for the event.
        /// </param>
        /// <remarks>
        /// <strong>Notes to Inheritors:</strong> When overriding <see cref="OnAction"/> in a derived
        /// class, be sure to call the base class's <see cref="OnAction"/> method so that registered
        /// delegates receive the event.
        /// </remarks>
        internal protected virtual void OnAction(StateEventArgs eventArgs)
        {
            var handler = Action;

            if (handler != null)
            {
                handler(this, eventArgs);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Raises the <see cref="Update"/> event.
        /// </summary>
        /// <param name="eventArgs">
        /// <see cref="StateEventArgs"/> object that provides the arguments for the event.
        /// </param>
        /// <remarks>
        /// <strong>Notes to Inheritors:</strong> When overriding <see cref="OnUpdate"/> in a derived
        /// class, be sure to call the base class's <see cref="OnUpdate"/> method so that registered
        /// delegates receive the event.
        /// </remarks>
        protected virtual void OnUpdate(StateEventArgs eventArgs)
        {
            var handler = Update;

            if (handler != null)
            {
                handler(this, eventArgs);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Updates the active state.
        /// </summary>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        internal void UpdateState(StateEventArgs eventArgs)
        {
            if (Count == 0)
            {
                return; // Nothing to do.
            }
            Debug.Assert(ActiveState != null, "Cannot update state. Active state is not set.");
            Debug.Assert(LastActiveState != null, "Last active state is not set.");

            ActiveState.UpdateState(eventArgs);
        }
Beispiel #5
0
        /// <summary>
        /// Performs state transitions.
        /// </summary>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        /// <returns>
        /// The firing transition; or <see langword="null"/> if no transition is firing.
        /// </returns>
        internal Transition UpdateTransitions(StateEventArgs eventArgs)
        {
            if (ActiveState == null)
            {
                // No state active. --> Transition into a state.
                // This happens at the first step of a state machine.
                EnterState(null, eventArgs);
                return(null);
            }

            // Check transitions of active state.
            return(ActiveState.UpdateTransitions(eventArgs));
        }
Beispiel #6
0
        /// <summary>
        /// Updates the state.
        /// </summary>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        internal void UpdateState(StateEventArgs eventArgs)
        {
            // Sub-states are updated first.
            if (_parallelSubStates != null)
            {
                foreach (var stateCollection in _parallelSubStates)
                {
                    stateCollection.UpdateState(eventArgs);
                }
            }

            // Raise Update event.
            OnUpdate(eventArgs);
        }
Beispiel #7
0
        /// <summary>
        /// Exits to the specified target state.
        /// </summary>
        /// <param name="transition">The firing transition.</param>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        internal void ExitState(Transition transition, StateEventArgs eventArgs)
        {
            if (Count == 0 || ActiveState == null)
            {
                return; // Nothing to do.
            }
            // Call exit on current state. The method will call true if the
            // state was exited. If the ActiveState contains the target state,
            // the method will return false and the ActiveState will still be active.
            bool exited = ActiveState.ExitState(transition, eventArgs);

            if (exited)
            {
                ActiveState = null;
            }
        }
Beispiel #8
0
        /// <summary>
        /// Enters the state.
        /// </summary>
        /// <param name="transition">The firing transition.</param>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        internal void EnterState(Transition transition, StateEventArgs eventArgs)
        {
            if (!IsActive)
            {
                // State is not active. Raise Enter event.
                OnEnter(eventArgs);
            }

            // Call Enter for sub-states.
            if (_parallelSubStates != null)
            {
                foreach (var stateCollection in _parallelSubStates)
                {
                    stateCollection.EnterState(transition, eventArgs);
                }
            }
        }
Beispiel #9
0
        /// <summary>
        /// Exits to the specified target state.
        /// </summary>
        /// <param name="transition">The firing transition.</param>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        /// <returns>
        /// <see langword="true"/> if this state was exited. <see langword="false"/> if this state is
        /// still active because the target state is a sub-state of this state.
        /// </returns>
        internal bool ExitState(Transition transition, StateEventArgs eventArgs)
        {
            Debug.Assert(IsActive, "Exit should only be called for active states.");

            if (transition != null && !Transitions.Contains(transition) && Contains(transition.TargetState))
            {
                // The transition is not from this state and the target is a sub-state
                // --> We do not leave the current state!
                // We have to find the sub-state collection that contains the target. In this sub-state
                // collection the active state will exit (and the target state will be entered later).
                if (_parallelSubStates != null)
                {
                    foreach (var stateCollection in _parallelSubStates)
                    {
                        if (stateCollection.ContainsRecursive(transition.TargetState))
                        {
                            stateCollection.ExitState(transition, eventArgs);
                        }
                    }
                }

                return(false);

                // This approach assumes that there are no transitions from a state to a state in a
                // parallel set. This is not explicitly forbidden (it is never verified in the state
                // machine).
                // Programmers must not create such transitions and graphical state machine editors
                // should prohibit such constructs.
            }

            // The target state is no sub-state. --> Exit all sub-state collections.
            if (_parallelSubStates != null)
            {
                foreach (var stateCollection in _parallelSubStates)
                {
                    stateCollection.ExitState(null, eventArgs);
                }
            }

            // Raise Exit event.
            OnExit(eventArgs);

            return(true);
        }
Beispiel #10
0
        /// <summary>
        /// Enters a new state.
        /// </summary>
        /// <param name="transition">The transition. (Can be <see langword="null"/>.)</param>
        /// <param name="eventArgs">
        /// The <see cref="StateEventArgs"/> instance containing the required data.
        /// </param>
        internal void EnterState(Transition transition, StateEventArgs eventArgs)
        {
            if (Count == 0)
            {
                // Abort, nothing to do.
                return;
            }

            // Current active state (can be null).
            var newActiveState = ActiveState;

            if (transition != null && ContainsRecursive(transition.TargetState))
            {
                // The target state is a state or sub-state.
                // The new active state must be the state that contains the target state.
                newActiveState = GetChild(transition.TargetState);
                Debug.Assert(newActiveState != null, "New active state not found.");
            }

            if (newActiveState == null)
            {
                // We don't know which state to enter - enter history/initial state.
                if (SaveHistory && LastActiveState != null)
                {
                    newActiveState = LastActiveState;
                }
                else
                {
                    newActiveState = InitialState;
                }
            }

            // Enter the new state.
            newActiveState.EnterState(transition, eventArgs);

            // Now that state was entered we remember it as the active state.
            ActiveState     = newActiveState;
            LastActiveState = newActiveState;
        }
Beispiel #11
0
        internal Transition UpdateTransitions(StateEventArgs eventArgs)
        {
            Transition firingTransition = null;

            // Update sub-state transitions first.
            if (_parallelSubStates != null)
            {
                foreach (var stateCollection in _parallelSubStates)
                {
                    firingTransition = stateCollection.UpdateTransitions(eventArgs);
                    if (firingTransition != null && !stateCollection.ContainsRecursive(firingTransition.TargetState))
                    {
                        // The transition target is outside the sub-state collection.
                        // More parallel transition updates are only allowed for internal transitions.
                        break;
                    }

                    // There was no transition or the transition was an internal transition.
                    // We can check the next parallel state set.
                }
            }

            // Abort if a transition was performed.
            if (firingTransition != null)
            {
                return(firingTransition);
            }

            // Check transitions of this state.
            foreach (var transition in Transitions)
            {
                if (transition.TargetState == null)
                {
                    throw new InvalidOperationException("TargetState of transition must not be null.");
                }
                //if (transition.TargetState.StateMachine != StateMachine)
                //  throw new InvalidOperationException("TargetState of transition must not belong to different state machine.");

                // Check transition.
                bool fired = transition.Update(eventArgs.DeltaTime);
                if (fired)
                {
                    // Get state collection that contains this state and the target state.
                    var stateCollection = StateCollection.GetCollection(this, transition.TargetState);

                    // Exit states.
                    stateCollection.ExitState(transition, eventArgs);

                    // Execute transition action.
                    transition.OnAction(eventArgs);

                    // Enter states.
                    stateCollection.EnterState(transition, eventArgs);

                    // Do not update other transitions after first transition has fired.
                    return(transition);
                }
            }

            return(null);
        }