X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fstructure%2FStateMachine.cxx;h=b9e540c8aa79ee8303f1e8700a5f96bc597c5b46;hb=02ac1a43c12c821c92a2e416d0ec343dbe5784e7;hp=76a00b291910a1de973cd0b85bd5529f522e9c6d;hpb=22ea8ebe258da45df9fc2b77904c2dcf79cd0f57;p=simgear.git diff --git a/simgear/structure/StateMachine.cxx b/simgear/structure/StateMachine.cxx index 76a00b29..b9e540c8 100644 --- a/simgear/structure/StateMachine.cxx +++ b/simgear/structure/StateMachine.cxx @@ -25,6 +25,7 @@ #include "StateMachine.hxx" +#include #include #include #include @@ -70,6 +71,7 @@ public: SGBindingList _bindings; std::set _sourceStates; ///< weak refs to source states State* _target; + bool _excludeTarget; SGSharedPtr _condition; }; @@ -91,6 +93,7 @@ public: } StateMachine* _p; + bool _initialised; State_ptr _currentState; StatePtrVec _states; std::vector _transitions; @@ -174,6 +177,7 @@ StateMachine::Transition::Transition(const std::string& aName, State* aTarget) : assert(aTarget); d->_name = aName; d->_target = aTarget; + d->_excludeTarget = true; } StateMachine::Transition::~Transition() @@ -196,6 +200,13 @@ void StateMachine::Transition::addSourceState(State* aSource) 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); } @@ -224,12 +235,19 @@ void StateMachine::Transition::addBinding(SGBinding* aBinding) 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() @@ -239,7 +257,13 @@ 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); @@ -254,8 +278,8 @@ void StateMachine::init() d->_timeInStateProp->setIntValue(0); // TODO go to default state if found - d->computeEligibleTransitions(); - + innerChangeState(d->_states[0], NULL); + d->_initialised = true; } void StateMachine::shutdown() @@ -267,7 +291,9 @@ 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) { @@ -401,10 +427,13 @@ StateMachine::createTransition(const std::string& aName, State_ptr aTarget) 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"); @@ -414,28 +443,36 @@ StateMachine* StateMachine::createFromPlist(SGPropertyNode* desc, SGPropertyNode 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; }