Files
simgear/simgear/structure/StateMachine.hxx
2013-01-25 09:29:31 +01:00

178 lines
4.8 KiB
C++

/* -*-c++-*-
*
* Copyright (C) 2013 James Turner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#ifndef SIMGEAR_STATE_MACHINE_H
#define SIMGEAR_STATE_MACHINE_H
#include <memory>
#include <string>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
// forward decls
class SGPropertyNode;
class SGBinding;
class SGCondition;
namespace simgear
{
class StateMachine : public SGReferenced
{
public:
StateMachine();
virtual ~StateMachine();
class State : public SGReferenced
{
public:
virtual ~State();
std::string name() const;
void addUpdateBinding(SGBinding* aBinding);
void addEntryBinding(SGBinding* aBinding);
void addExitBinding(SGBinding* aBinding);
private:
friend class StateMachine;
State(const std::string& name);
void fireExitBindings();
void fireEntryBindings();
void update();
class StatePrivate;
std::auto_ptr<StatePrivate> d;
};
class Transition : public SGReferenced
{
public:
virtual ~Transition();
std::string name() const;
/**
* Set if the target state should automatically be excluded
* from the source state. Defaults to true, can be cleared
* to allow a state to re-enter itself
*/
void setExcludeTarget(bool aExclude);
/**
* The state we end in, after this transition fires
*/
State* target() const;
/**
* Add a state in which this transition is eligible to fire
*/
void addSourceState(State* aSource);
/**
* Specify the transition trigger condition. Takes ownership
*/
void setTriggerCondition(SGCondition* aCondition);
void addBinding(SGBinding* aBinding);
private:
friend class StateMachine;
Transition(const std::string& aName, State* aTarget);
/**
* predicate to determine if this transition can fire given a
* current state.
*/
bool applicableForState(State* aCurrent) const;
/**
* test if the transition should fire, based on current state
*/
bool evaluate() const;
void fireBindings();
class TransitionPrivate;
std::auto_ptr<TransitionPrivate> d;
};
typedef SGSharedPtr<State> State_ptr;
typedef SGSharedPtr<Transition> Transition_ptr;
void initFromPlist(SGPropertyNode* desc, SGPropertyNode* root);
/**
* create a state machine from a property list description
*/
static StateMachine* createFromPlist(SGPropertyNode* desc, SGPropertyNode* root);
SGPropertyNode* root();
void init();
void shutdown();
void update(double dt);
State_ptr state() const;
/**
* public API to force a change to a particular state.
* @param aOnlyIfDifferent - only make a transition if the new state is
* different from the current state. Otherwise, the existing state will
* be exited and re-entered.
*/
void changeToState(State_ptr aState, bool aOnlyIfDifferent=true);
/// wrapper to change state by looking up a name
void changeToStateName(const std::string& aName, bool aOnlyIfDifferent=true);
State_ptr findStateByName(const std::string& aName) const;
State_ptr stateByIndex(unsigned int aIndex) const;
int indexOfState(State_ptr aState) const;
// programatic creation
State_ptr createState(const std::string& aName);
Transition_ptr createTransition(const std::string& aName, State_ptr aTarget);
private:
void addState(State_ptr aState);
void addTransition(Transition_ptr aTrans);
void innerChangeState(State_ptr aState, Transition_ptr aTrans);
class StateMachinePrivate;
std::auto_ptr<StateMachinePrivate> d;
};
typedef SGSharedPtr<StateMachine> StateMachine_ptr;
} // of simgear namespace
#endif // of SIMGEAR_STATE_MACHINE_H