Skip to content
| Marketplace
Sign in
Visual Studio>Tools>StateMachineEditor2017
StateMachineEditor2017

StateMachineEditor2017

Saul Scudder

|
925 installs
| (1) | Free
From an XML state machine skeleton code for an event driven state machine is generated, This package contains the generator and a tool to design the xml skeleton
Download

State Machine Editor

The State Machine Editor

The State Machine Editor is a tool that converts an XML description of a 'state machine' to source code in c# or other languages. A tool to convert user input to the XML is included.

An example xml script is loaded from a button under the help selection, it shows the format and can be used to test the different kinds of code generation.

A state machine is a set of Transitions where a starting 'State' receives an 'Event', performs an 'Action' and arrives at a final 'State'. A set of these transitions can model complex processes.

The State Machine Editor can translate xml state machine models into c#, c++ or vb code, some work is needed to integrate the code into c++ or vb project however complete projects are generated for c#.

Features:

  • UI tools to create xml models of State Machines from user selections.
    • States, Actions and Events are added by pressing an add button and naming them.
    • Transitions from one state to another are added by selecting an 'Initial State', an 'Event', an 'Action' to be performed and a 'Final State', then presing Add Transition
    • An expander displays a list of all transitions in a state machine. Selecting in the list re-selects the individual parts of the transition chosen. To be viewed or deleted.
    • A button in the tool's help expander generates an example state machine.
    • Unused states or dead ends can be traced using the Analize tool on the menu.
  • Edit sessions are persisted by saving and loading the xml.
  • A button press converts xml models into source code. Either:
    • A complete state machine in c#.
    • c++ or vb (may need edits to use.)
    • In c# Windows Console projects with the state machine source and test events
    • c# WPF projects with the state machine source and test events
    • c# WPF projects with a different class design in a State Machine Pattern.
    • Parts for a very simple MVC project.

The 2nd generated API for the state machines uses the State Machine Pattern

In the generated c# and WPF project a button is created to trigger processing each event. Each state class has StateEntry, StateExit and Action events. The current state changes when an Action returns true. The Test Project generated maps each state's events to show the machine status.

        ... in MainWindow.xmal.cs       public void OnLoaded(object obj, System.EventArgs e)        {            this.SetUpEvents();            this._stateMachineMonster.StateChanged += this.OnStateChanged;            ...        }        ...        public void SetUpEvents()        {            IState baseState = this._stateMachineMonster.CurrentState;            if (("Moving" == baseState.StateName))            {                Moving stateobj = ((Moving)(baseState));                stateobj.LookAbout += this.AnyAction;                stateobj.ChompEnemy += this.AnyAction;                stateobj.ChargeEnemy += this.AnyAction;                stateobj.Nothing += this.AnyAction;                stateobj.GoToFriend += this.AnyAction;                stateobj.StateEntry += this.AnyEntry;                stateobj.StateExit += this.AnyExit;                return;            }            if (("Chasing" == baseState.StateName))            {

In the statemachine class the current state is checked for an Action for the stateevent and either a new state name or null is returned. The StateChanged event is for use when the new CurrentState needs further initialization after it is changed.

     ... in the statemachine class events change the State class instance in an IState interface object 'CurrentState'         public void MachineEventArrival(string stateevent)        {    // test if the stateevent runs an action if so run it and return a new statename or null            string state = this.CurrentState.StateEventCheck(stateevent);       // if the state remains the current state no StateEntry, StateChange or StateExit events need to be run            if ((state == this.CurrentState.StateName))            {                return;            }            if ((state != null))            {    // runs the old state class's StateExit event                this.CurrentState.OnExit(stateevent);      // puts the new state class in CurrentState                this.StateFromStateName(state);      // if it is being used by someone run the StateChange event                     if ((this.StateChanged != null))                       {                    this.StateChanged(this, new EventArgs());                }    // run the new state class's StateEntry event                this.CurrentState.OnEntry(stateevent);              }        }
The first API between the real world and the State Machines was designed as a multicasting black box

A button is created to trigger processing each event. The stack traces shown below show how the event arrives, is tested, any Action run, and the state change if one occures.

               private void EventButtonOnClick(object sender, RoutedEventArgs routedEventArgs)              {...              case "EnemySuspected":                   this.chevnt = "EnemySuspected";                   // check if 'EnemySuspected' event is valid                   evtst = _monster.MonsterInputReady.EventsReadyFromState(_monster.GetCurrentState());                   if(evtst != null)                   {                   // tell the state machine to run the event 'EnemySuspected'                   retv = _monster.RunMonsterEventEnemySuspected(DateTime.Now.ToString());                   }                   break;     

For this to work, methods are attached at start up to events that come from the state machine.

        public void StartTest()        {        _monster.MonsterEventEnemyClose += this.TestInputEventEnemyClose;          _monster.MonsterEventEnemyFound += this.TestInputEventEnemyFound;        _monster.MonsterEventEnemySuspected += this.TestInputEventEnemySuspected;  //...missing        _monster.MonsterActions.MonsterActionLookAbout += this.TestActionEventLookAbout;          _monster.MonsterActions.MonsterActionChompEnemy += this.TestActionEventChompEnemy;        _monster.MonsterActions.MonsterActionChargeEnemy += this.TestActionEventChargeEnemy;//...        _monster.MonsterInputReady.MovingCheckEventReady += this.CheckForEventInStateMoving;          _monster.MonsterInputReady.ChasingCheckEventReady += this.CheckForEventInStateChasing;        _monster.MonsterInputReady.FleeingCheckEventReady += this.CheckForEventInStateFleeing;  //...        }    

The state machine tests if an event is valid for the state named 'Moving' The test code logs that it's checking

Call Stack

  1. MonsterTestApp.exe!sm_Monster.MainWindow.CheckForEventInStateMoving(object sender, sm_Monster.MonsterTestEventsReadyArgs e)
  2. MonsterTestApp.exe!sm_Monster.MonsterTestEventsReady.RunMovingCheckEventReady(string st)
  3. MonsterTestApp.exe!sm_Monster.MonsterTestEventsReady.EventsReadyFromState(string st)
  4. MonsterTestApp.exe!sm_Monster.MainWindow.EventButtonOnClick(object sender, System.Windows.RoutedEventArgs routedEventArgs)
    public string CheckForEventInStateMoving(object sender, MonsterTestEventsReadyArgs e)    {        string nowstate = this._monster.GetCurrentState();        string runs = " running CheckForEventInStateMoving";        string message = string.Format("{0} In state {1} with id = {2} inst = {3}", runs, nowstate, e.Sm_ID, e.Sm_Instance);        this.Writer(message);        System.Collections.Generic.Dictionary        validevnts = this._monster.MonsterInputReady.ListEventsFromState("Moving");        if (validevnts.ContainsKey(this.chevnt))        {            return this.chevnt;        }            return null;    }  

Called by the state machine when an event is known to be valid for the current state. The test code logs that the event arived

Call Stack

  1. MonsterTestApp.exe!sm_Monster.MainWindow.TestInputEventEnemySuspected(object sender, sm_Monster.MonsterInputEventArgs e)
  2. MonsterTestApp.exe!sm_Monster.Monster.RunMonsterEventEnemySuspected(string st)
  3. MonsterTestApp.exe!sm_Monster.MainWindow.EventButtonOnClick(object sender, System.Windows.RoutedEventArgs routedEventArgs)
        public bool TestInputEventEnemySuspected(object sender, MonsterInputEventArgs e)        {            EventTextBlock.Text = "EnemySuspected";            string nowstate = this._monster.GetCurrentState();            string runs = " running MonsterEventEnemySuspected";            string message = string.Format("{0} In state {1} [{2}] for id = {3} instance = {4}", runs, nowstate, e.Comment, e.Sm_ID, e.Sm_Instance);            this.Writer(message);            return true;        }        

Called by the state machine to perform the the action 'LookAbout'

Call Stack

  1. MonsterTestApp.exe!sm_Monster.MainWindow.TestActionEventLookAbout(object sender, sm_Monster.MonsterActionsEventArgs e)
  2. MonsterTestApp.exe!sm_Monster.MonsterActionsEvents.RunMonsterActionLookAbout(long id, long inst)
  3. MonsterTestApp.exe!sm_Monster.Monster.st_Moving(string evnt)
  4. MonsterTestApp.exe!sm_Monster.Monster.RunEventFromState(string evnt)
  5. MonsterTestApp.exe!sm_Monster.Monster.RunMonsterEventEnemySuspected(string st)
  6. MonsterTestApp.exe!sm_Monster.MainWindow.EventButtonOnClick(object sender, System.Windows.RoutedEventArgs routedEventArgs)
        public bool TestActionEventLookAbout(object sender, MonsterActionsEventArgs e)        {            ActionTextBlock.Text = "LookAbout";            string nowstate = this._monster.GetCurrentState();            string runs = " running Action MonsterEvent_LookAbout";            string message = string.Format("{0} In state {1} with id = {2} inst = {3}", runs, nowstate, e.Sm_ID, e.Sm_Instance);            this.Writer(message);            return true;        }
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2025 Microsoft