SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
StateMachine.cpp
Go to the documentation of this file.
1 /**
2  * \file StateMachinge.cpp
3  * \brief State Machine Class Implementation
4  * \authors Michael Göttlicher
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8  */
9 
10 #include "StateMachine.h"
11 #include <sstream>
12 
13 #define LOG_STATEMACHINE_WARN(...) Utils::log("StateMachine", __VA_ARGS__);
14 #define LOG_STATEMACHINE_INFO(...) Utils::log("StateMachine", __VA_ARGS__);
15 #define LOG_STATEMACHINE_DEBUG(...) Utils::log("StateMachine", __VA_ARGS__);
16 
17 namespace sm
18 {
19 //-----------------------------------------------------------------------------
20 StateMachine::StateMachine(unsigned int initialStateId)
21  : _currentStateId(initialStateId)
22 {
23 }
24 //-----------------------------------------------------------------------------
26 {
27  for (auto it : _stateActions)
28  {
29  delete it.second;
30  }
31 };
32 //-----------------------------------------------------------------------------
34 {
35  sm::EventData* data = nullptr;
36  bool stateEntry = false;
37  bool stateWasUpdated = false;
38  // invoke state action for every valid event, but at least once
39  while (!_events.empty())
40  {
41  Event* e = _events.front();
42  _events.pop();
43 
44  unsigned int newState = e->getNewState(_currentStateId);
45  data = e->getEventData();
46 
47  LOG_STATEMACHINE_DEBUG("Event %s received sent by %s",
48  e->name(),
49  e->senderInfo());
50 
51  if (newState != Event::EVENT_IGNORED)
52  {
53  if (_currentStateId != newState)
54  {
55  stateEntry = true;
56  LOG_STATEMACHINE_DEBUG("State change: %s -> %s",
58  getPrintableState(newState).c_str());
59 
60  // inform old state that we will leave it soon
61  auto itStateAction = _stateActions.find(_currentStateId);
62  if (itStateAction != _stateActions.end())
63  {
64  itStateAction->second->invokeStateAction(this,
65  data,
66  false,
67  true);
68  }
69  else
70  {
71  std::stringstream ss;
72  ss << "You forgot to register state "
74  << "!";
75  Utils::exitMsg("StateMachine",
76  ss.str().c_str(),
77  __LINE__,
78  __FILE__);
79  }
80 
81  // update state
82  _currentStateId = newState;
83  }
84  auto itStateAction = _stateActions.find(_currentStateId);
85  if (itStateAction != _stateActions.end())
86  {
87  itStateAction->second->invokeStateAction(this,
88  data,
89  stateEntry,
90  false);
91  }
92  else
93  {
94  std::stringstream ss;
95  ss << "You forgot to register state "
97  << "!";
98  Utils::exitMsg("StateMachine",
99  ss.str().c_str(),
100  __LINE__,
101  __FILE__);
102  }
103  stateWasUpdated = true;
104  }
105  else
106  {
107  LOG_STATEMACHINE_DEBUG("Event %s ignored in state %s",
108  e->name(),
110  }
111 
112  delete e;
113  }
114 
115  if (!stateWasUpdated)
116  _stateActions[_currentStateId]->invokeStateAction(this, data, stateEntry, false);
117 
118  // ATTENTION: data ownership is not transferred to state
119  delete data;
120 
121  return true;
122 }
123 //-----------------------------------------------------------------------------
124 }
#define LOG_STATEMACHINE_DEBUG(...)
std::queue< Event * > _events
Definition: EventHandler.h:18
Event class used in the state machine.
Definition: Event.h:32
EventData * getEventData()
Get event data that was possibly send with this event. If the function returns nullptr,...
Definition: Event.h:72
const char * name() const
Definition: Event.h:77
const char * senderInfo() const
Definition: Event.h:78
unsigned int getNewState(unsigned int currentState)
Check if there is a transition to a new state. The current state is used to lookup the new state.
Definition: Event.h:54
@ EVENT_IGNORED
Definition: Event.h:36
unsigned int _currentStateId
Definition: StateMachine.h:103
virtual ~StateMachine()
virtual std::string getPrintableState(unsigned int state)=0
StateMachine(unsigned int initialStateId)
bool update()
process events and update current state
std::map< unsigned int, sm::StateBase * > _stateActions
Definition: StateMachine.h:105
void exitMsg(const char *tag, const char *msg, const int line, const char *file)
Terminates the application with a message. No leak checking.
Definition: Utils.cpp:1135
Collection of classes for a state machine implementation used in the Erleb-AR app.
Definition: Event.h:25