diff --git a/libs/openFrameworks/types/ofParameter.cpp b/libs/openFrameworks/types/ofParameter.cpp index 513e5ef330c..974b42b0c31 100644 --- a/libs/openFrameworks/types/ofParameter.cpp +++ b/libs/openFrameworks/types/ofParameter.cpp @@ -106,50 +106,70 @@ ofParameter& ofParameter::set(const std::string & name){ } void ofParameter::trigger(){ - ofNotifyEvent(obj->changedE,this); - // Notify all parents, if there are any. - if(!obj->parents.empty()) + // If the object is notifying its parents, just set the value without triggering an event. + if(!obj->bInNotify) { - // Erase each invalid parent - obj->parents.erase(std::remove_if(obj->parents.begin(), - obj->parents.end(), - [](const std::weak_ptr & p){ return p.expired(); }), - obj->parents.end()); - - // notify all leftover (valid) parents of this object's changed value. - // this can't happen in the same iterator as above, because a notified listener - // might perform similar cleanups that would corrupt our iterator - // (which appens for example if the listener calls getFirstParent on us) - for(auto & parent: obj->parents){ - auto p = parent.lock(); - if(p){ - p->notifyParameterChanged(*this); + // Mark the object as in its notification loop. + obj->bInNotify = true; + + // Notify any local subscribers. + ofNotifyEvent(obj->changedE, this); + + // Notify all parents, if there are any. + if(!obj->parents.empty()) + { + // Erase each invalid parent + obj->parents.erase(std::remove_if(obj->parents.begin(), + obj->parents.end(), + [this](const std::weak_ptr & p){ return p.expired(); }), + obj->parents.end()); + + // notify all leftover (valid) parents of this object's changed value. + // this can't happen in the same iterator as above, because a notified listener + // might perform similar cleanups that would corrupt our iterator + // (which appens for example if the listener calls getFirstParent on us) + for(auto & parent: obj->parents){ + auto p = parent.lock(); + if(p){ + p->notifyParameterChanged(*this); + } } } + obj->bInNotify = false; } } void ofParameter::trigger(const void * sender){ - ofNotifyEvent(obj->changedE,sender); - // Notify all parents, if there are any. - if(!obj->parents.empty()) + // If the object is notifying its parents, Do not trigger the event. + if(!obj->bInNotify) { - // Erase each invalid parent - obj->parents.erase(std::remove_if(obj->parents.begin(), - obj->parents.end(), - [](const std::weak_ptr & p){ return p.expired(); }), - obj->parents.end()); - - // notify all leftover (valid) parents of this object's changed value. - // this can't happen in the same iterator as above, because a notified listener - // might perform similar cleanups that would corrupt our iterator - // (which appens for example if the listener calls getFirstParent on us) - for(auto & parent: obj->parents){ - auto p = parent.lock(); - if(p){ - p->notifyParameterChanged(*this); + // Mark the object as in its notification loop. + obj->bInNotify = true; + + // Notify any local subscribers. + ofNotifyEvent(obj->changedE, this); + + // Notify all parents, if there are any. + if(!obj->parents.empty()) + { + // Erase each invalid parent + obj->parents.erase(std::remove_if(obj->parents.begin(), + obj->parents.end(), + [this](const std::weak_ptr & p){ return p.expired(); }), + obj->parents.end()); + + // notify all leftover (valid) parents of this object's changed value. + // this can't happen in the same iterator as above, because a notified listener + // might perform similar cleanups that would corrupt our iterator + // (which appens for example if the listener calls getFirstParent on us) + for(auto & parent: obj->parents){ + auto p = parent.lock(); + if(p){ + p->notifyParameterChanged(*this); + } } } + obj->bInNotify = false; } } diff --git a/libs/openFrameworks/types/ofParameter.h b/libs/openFrameworks/types/ofParameter.h index 64044391a01..08a23d45a5c 100644 --- a/libs/openFrameworks/types/ofParameter.h +++ b/libs/openFrameworks/types/ofParameter.h @@ -1054,14 +1054,17 @@ class ofParameter: public ofAbstractParameter{ class Value{ public: Value() - :serializable(false){} + :bInNotify(false) + ,serializable(false){} Value(std::string name) :name(name) + ,bInNotify(false) ,serializable(false){} std::string name; ofEvent changedE; + bool bInNotify; bool serializable; std::vector> parents; };