3 * Copyright (C) 2013 James Turner
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #ifndef SIMGEAR_STATE_MACHINE_H
23 #define SIMGEAR_STATE_MACHINE_H
28 #include <simgear/structure/SGReferenced.hxx>
29 #include <simgear/structure/SGSharedPtr.hxx>
39 class StateMachine : public SGReferenced
43 virtual ~StateMachine();
45 class State : public SGReferenced
50 std::string name() const;
52 void addUpdateBinding(SGBinding* aBinding);
53 void addEntryBinding(SGBinding* aBinding);
54 void addExitBinding(SGBinding* aBinding);
57 friend class StateMachine;
59 State(const std::string& name);
61 void fireExitBindings();
62 void fireEntryBindings();
67 std::auto_ptr<StatePrivate> d;
70 class Transition : public SGReferenced
73 virtual ~Transition();
75 std::string name() const;
78 * Set if the target state should automatically be excluded
79 * from the source state. Defaults to true, can be cleared
80 * to allow a state to re-enter itself
82 void setExcludeTarget(bool aExclude);
86 * The state we end in, after this transition fires
88 State* target() const;
91 * Add a state in which this transition is eligible to fire
93 void addSourceState(State* aSource);
96 * Specify the transition trigger condition. Takes ownership
98 void setTriggerCondition(SGCondition* aCondition);
101 void addBinding(SGBinding* aBinding);
103 friend class StateMachine;
105 Transition(const std::string& aName, State* aTarget);
108 * predicate to determine if this transition can fire given a
111 bool applicableForState(State* aCurrent) const;
114 * test if the transition should fire, based on current state
116 bool evaluate() const;
120 class TransitionPrivate;
121 std::auto_ptr<TransitionPrivate> d;
124 typedef SGSharedPtr<State> State_ptr;
125 typedef SGSharedPtr<Transition> Transition_ptr;
127 void initFromPlist(SGPropertyNode* desc, SGPropertyNode* root);
130 * create a state machine from a property list description
132 static StateMachine* createFromPlist(SGPropertyNode* desc, SGPropertyNode* root);
134 SGPropertyNode* root();
139 void update(double dt);
141 State_ptr state() const;
144 * public API to force a change to a particular state.
145 * @param aOnlyIfDifferent - only make a transition if the new state is
146 * different from the current state. Otherwise, the existing state will
147 * be exited and re-entered.
149 void changeToState(State_ptr aState, bool aOnlyIfDifferent=true);
151 /// wrapper to change state by looking up a name
152 void changeToStateName(const std::string& aName, bool aOnlyIfDifferent=true);
154 State_ptr findStateByName(const std::string& aName) const;
156 State_ptr stateByIndex(unsigned int aIndex) const;
158 int indexOfState(State_ptr aState) const;
160 // programatic creation
161 State_ptr createState(const std::string& aName);
162 Transition_ptr createTransition(const std::string& aName, State_ptr aTarget);
164 void addState(State_ptr aState);
165 void addTransition(Transition_ptr aTrans);
167 void innerChangeState(State_ptr aState, Transition_ptr aTrans);
169 class StateMachinePrivate;
170 std::auto_ptr<StateMachinePrivate> d;
173 typedef SGSharedPtr<StateMachine> StateMachine_ptr;
175 } // of simgear namespace
177 #endif // of SIMGEAR_STATE_MACHINE_H