SGBindingList _bindings;
std::set<State*> _sourceStates; ///< weak refs to source states
State* _target;
+ bool _excludeTarget;
SGSharedPtr<SGCondition> _condition;
};
}
StateMachine* _p;
+ bool _initialised;
State_ptr _currentState;
StatePtrVec _states;
std::vector<Transition_ptr> _transitions;
assert(aTarget);
d->_name = aName;
d->_target = aTarget;
+ d->_excludeTarget = true;
}
StateMachine::Transition::~Transition()
bool StateMachine::Transition::applicableForState(State* aCurrent) const
{
+ if (d->_excludeTarget && (aCurrent == d->_target)) {
+ return false;
+ }
+
+ if (d->_sourceStates.empty()) {
+ return true;
+ }
return d->_sourceStates.count(aCurrent);
}
d->_bindings.push_back(aBinding);
}
+void StateMachine::Transition::setExcludeTarget(bool aExclude)
+{
+ d->_excludeTarget = aExclude;
+}
+
///////////////////////////////////////////////////////////////////////////
StateMachine::StateMachine() :
d(new StateMachinePrivate(this))
{
d->_root = new SGPropertyNode();
+ d->_listenerLockout = false;
+ d->_initialised = false;
}
StateMachine::~StateMachine()
void StateMachine::init()
{
+ if (d->_initialised) {
+ return;
+ }
+ if (d->_states.empty()) {
+ throw sg_range_exception("StateMachine::init: no states defined");
+ }
d->_currentStateIndex = d->_root->getChild("current-index", 0, true);
d->_currentStateIndex->setIntValue(0);
d->_timeInStateProp->setIntValue(0);
// TODO go to default state if found
- d->computeEligibleTransitions();
-
+ innerChangeState(d->_states[0], NULL);
+ d->_initialised = true;
}
void StateMachine::shutdown()
void StateMachine::innerChangeState(State_ptr aState, Transition_ptr aTrans)
{
- d->_currentState->fireExitBindings();
+ if (d->_currentState) {
+ d->_currentState->fireExitBindings();
+ }
// fire bindings before we change the state, hmmmm
if (aTrans) {
return t;
}
-StateMachine* StateMachine::createFromPlist(SGPropertyNode* desc, SGPropertyNode* root)
+void StateMachine::initFromPlist(SGPropertyNode* desc, SGPropertyNode* root)
{
- StateMachine* sm = new StateMachine;
-
+ std::string path = desc->getStringValue("branch");
+ if (!path.empty()) {
+ d->_root = root->getNode(path, 0, true);
+ assert(d->_root);
+ }
BOOST_FOREACH(SGPropertyNode* stateDesc, desc->getChildren("state")) {
std::string nm = stateDesc->getStringValue("name");
readBindingList(stateDesc, "exit", root, st->d->_entryBindings);
readBindingList(stateDesc, "update", root, st->d->_exitBindings);
- sm->addState(st);
+ addState(st);
} // of states iteration
BOOST_FOREACH(SGPropertyNode* tDesc, desc->getChildren("transition")) {
std::string nm = tDesc->getStringValue("name");
- State_ptr target = sm->findStateByName(tDesc->getStringValue("target"));
+ State_ptr target = findStateByName(tDesc->getStringValue("target"));
SGCondition* cond = sgReadCondition(root, tDesc->getChild("condition"));
Transition_ptr t(new Transition(nm, target));
t->setTriggerCondition(cond);
+ t->setExcludeTarget(tDesc->getBoolValue("exclude-target", true));
BOOST_FOREACH(SGPropertyNode* src, desc->getChildren("source")) {
- State_ptr srcState = sm->findStateByName(src->getStringValue());
+ State_ptr srcState = findStateByName(src->getStringValue());
t->addSourceState(srcState);
}
readBindingList(tDesc, "binding", root, t->d->_bindings);
- sm->addTransition(t);
+ addTransition(t);
} // of states iteration
+ init();
+}
+
+StateMachine* StateMachine::createFromPlist(SGPropertyNode* desc, SGPropertyNode* root)
+{
+ StateMachine* sm = new StateMachine;
+ sm->initFromPlist(desc, root);
return sm;
}