From 109f6f22fe48613ef71370b2f010ef1de3940a3b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sat, 7 Dec 2002 21:18:12 +0000 Subject: [PATCH] Updated the Switch, Sequence and Group classes so that they all used a similar style removeChild() mechansim. Made the old style osg::Switch::setValue() method deprecated. --- include/osg/Geode | 34 +----- include/osg/Geometry | 12 +- include/osg/Group | 31 +----- include/osg/Sequence | 8 +- include/osg/Switch | 18 ++- src/osg/Geode.cpp | 40 +++++-- src/osg/Group.cpp | 80 +++++++------ src/osg/Sequence.cpp | 148 ++++++++++++++----------- src/osg/Switch.cpp | 63 ++++++++--- src/osgPlugins/geo/ReaderWriterGEO.cpp | 16 ++- src/osgPlugins/osg/Switch.cpp | 68 +++++++----- 11 files changed, 292 insertions(+), 226 deletions(-) diff --git a/include/osg/Geode b/include/osg/Geode index 76ec55a67..986c87455 100644 --- a/include/osg/Geode +++ b/include/osg/Geode @@ -36,9 +36,11 @@ class SG_EXPORT Geode : public Node /** Remove Drawable from Geode. * Equivalent to setDrawabke(getDrawableIndex(orignChild),node), * see docs for setNode for futher details on implementation.*/ - virtual bool removeDrawable( Drawable *drawable ); + /** Remove drawable(s) from the specified position in Geode's drawable list.*/ + virtual bool removeDrawable(unsigned int i,unsigned int numDrawablesToRemove=1); + /** Replace specified Drawable with another Drawable. * Equivalent to setDrawable(getDrawableIndex(orignChild),node), * see docs for setDrawable for futher details on implementation.*/ @@ -77,36 +79,6 @@ class SG_EXPORT Geode : public Node return false; } - /** return the iterator position for specified Drawable. - * return _drawables.end() if gset not is contained in Geode. - */ - inline DrawableList::iterator findDrawable(const Drawable* gset) - { - - for (DrawableList::iterator itr=_drawables.begin(); - itr!=_drawables.end(); - ++itr) - { - if (itr->get()==gset) return itr; - } - return _drawables.end(); - } - - /** return the const_iterator position for specified Drawable. - * return _drawables.end() if gset not is contained in Geode. - */ - inline DrawableList::const_iterator findDrawable(const Drawable* gset) const - { - - for (DrawableList::const_iterator itr=_drawables.begin(); - itr!=_drawables.end(); - ++itr) - { - if (itr->get()==gset) return itr; - } - return _drawables.end(); - } - /** Get the index number of drawable, return a value between * 0 and _drawables.size()-1 if found, if not found then * return _drawables.size().*/ diff --git a/include/osg/Geometry b/include/osg/Geometry index c3702cc2b..fc4eb6643 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -128,16 +128,16 @@ class SG_EXPORT Geometry : public Drawable PrimitiveSet* getPrimitiveSet(unsigned int pos) { return _primitives[pos].get(); } const PrimitiveSet* getPrimitiveSet(unsigned int pos) const { return _primitives[pos].get(); } - /** Add a primtive set to the geometry.*/ + /** Add a primitive set to the geometry.*/ bool addPrimitiveSet(PrimitiveSet* primitiveset); - /** Set a primtive set to the specified position in geometry's primtive set list.*/ + /** Set a primitive set to the specified position in geometry's primitive set list.*/ bool setPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset); - /** Insert a primtive set to the specified position in geometry's primtive set list.*/ + /** Insert a primitive set to the specified position in geometry's primitive set list.*/ bool insertPrimitiveSet(unsigned int i,PrimitiveSet* primitiveset); - /** Remove primtive set(s) from the specified position in geometry's primtive set list.*/ + /** Remove primitive set(s) from the specified position in geometry's primitive set list.*/ bool removePrimitiveSet(unsigned int i,unsigned int numElementsToRemove=1); /** Get the index number of a primitive set, return a value between @@ -148,7 +148,7 @@ class SG_EXPORT Geometry : public Drawable /** return true if OpenGL fast paths will be used with drawing this Geometry. * Fast paths use vertex arrays, and glDrawArrays/glDrawElements. Slow paths - * use glBegin()/glVertex.../glEnd(). Use of per primtive bindings or per vertex indexed + * use glBegin()/glVertex.../glEnd(). Use of per primitive bindings or per vertex indexed * arrays will drop the rendering path off the fast path.*/ bool areFastPathsUsed() const; @@ -178,7 +178,7 @@ class SG_EXPORT Geometry : public Drawable /** return true, osg::Geometry does support accept(PrimitiveFunctor&) .*/ virtual bool supports(PrimitiveFunctor&) const { return true; } - /** accept a PrimtiveFunctor and call its methods to tell it about the interal primtives that this Drawable has.*/ + /** accept a PrimitiveFunctor and call its methods to tell it about the interal primitives that this Drawable has.*/ virtual void accept(PrimitiveFunctor& pf) const; protected: diff --git a/include/osg/Group b/include/osg/Group index dc6f76403..564b584d7 100644 --- a/include/osg/Group +++ b/include/osg/Group @@ -49,6 +49,8 @@ class SG_EXPORT Group : public Node */ virtual bool removeChild( Node *child ); + virtual bool removeChild(unsigned int pos,unsigned int numChildrenToRemove=1); + /** Replace specified Node with another Node. * Equivalent to setChild(getChildIndex(orignChild),node), * see docs for setChild for futher details on implementation.*/ @@ -87,35 +89,6 @@ class SG_EXPORT Group : public Node return false; } - - /** return the iterator position for specified Node. - * return _children.end() if node is not contained in Group. - */ - inline ChildList::iterator findNode( const Node* node ) - { - for (ChildList::iterator itr=_children.begin(); - itr!=_children.end(); - ++itr) - { - if (itr->get()==node) return itr; - } - return _children.end(); - } - - /** return the const_iterator position for specified Node. - * return _children.end() if node is not contained in Group. - */ - inline ChildList::const_iterator findNode( const Node* node ) const - { - for (ChildList::const_iterator itr=_children.begin(); - itr!=_children.end(); - ++itr) - { - if (itr->get()==node) return itr; - } - return _children.end(); - } - /** Get the index number of child, return a value between * 0 and _children.size()-1 if found, if not found then * return _children.size().*/ diff --git a/include/osg/Sequence b/include/osg/Sequence index 96ae8eda7..0e7045d71 100644 --- a/include/osg/Sequence +++ b/include/osg/Sequence @@ -14,7 +14,7 @@ namespace osg { /** Sequence is a Group node which allows automatic, time based switching between children. */ -class SG_EXPORT Sequence : public Switch +class SG_EXPORT Sequence : public Group { public : @@ -26,6 +26,10 @@ public : META_Node(osg, Sequence); virtual void traverse(NodeVisitor& nv); + + + void setValue(int value) { _value = value; } + int getValue() const { return _value; } /** Set time in seconds for child */ void setTime(int frame, float t); @@ -80,6 +84,8 @@ protected : virtual ~Sequence() {} + int _value; + float _last; std::vector _frameTime; diff --git a/include/osg/Switch b/include/osg/Switch index 51292c3da..ddec71321 100644 --- a/include/osg/Switch +++ b/include/osg/Switch @@ -40,12 +40,22 @@ class SG_EXPORT Switch : public Group void setValue(unsigned int pos,bool value); - void setValue(const Node* child,bool value); - bool getValue(unsigned int pos) const; - bool getValue(const Node* child) const; + void setChildValue(const Node* child,bool value); + + bool getChildValue(const Node* child) const; + /** Set all the children off (false), and set the new default child value to off (false).*/ + bool setAllChildrenOff(); + + /** Set all the children on (true), and set the new default child value to on (true).*/ + bool setAllChildrenOn(); + + /** Set a single child to be on, switch off all other children.*/ + bool setSingleChildOn(unsigned int pos); + +#ifdef USE_DEPRECTATED_API /** * Special values for the Switch. Use these if you want to * turn on/off all child nodes. @@ -69,6 +79,8 @@ class SG_EXPORT Switch : public Group void setValue(int value); int getValue() const; + +#endif typedef std::vector ValueList; diff --git a/src/osg/Geode.cpp b/src/osg/Geode.cpp index 94c4c108c..c2e2cee44 100644 --- a/src/osg/Geode.cpp +++ b/src/osg/Geode.cpp @@ -1,6 +1,8 @@ +#include +#include + #include #include -#include #define square(x) ((x)*(x)) @@ -58,19 +60,36 @@ bool Geode::addDrawable( Drawable *drawable ) bool Geode::removeDrawable( Drawable *drawable ) { - DrawableList::iterator itr = findDrawable(drawable); - if (itr!=_drawables.end()) - { - // remove this Geode from the child parent list. - drawable->removeParent(this); + return removeDrawable(getDrawableIndex(drawable)); +} - if (drawable->getAppCallback()) +bool Geode::removeDrawable(unsigned int pos,unsigned int numDrawablesToRemove) +{ + if (pos<_drawables.size() && numDrawablesToRemove>0) + { + unsigned int endOfRemoveRange = pos+numDrawablesToRemove; + if (endOfRemoveRange>_drawables.size()) { - setNumChildrenRequiringAppTraversal(getNumChildrenRequiringAppTraversal()-1); + notify(DEBUG_INFO)<<"Warning: Geode::removeDrawable(i,numDrawablesToRemove) has been passed an excessive number"< automatically handles decrementing drawable's reference count. - _drawables.erase(itr); + unsigned int appCallbackRemoved = 0; + for(unsigned i=pos;iremoveParent(this); + // update the number of app calbacks removed + if (_drawables[i]->getAppCallback()) ++appCallbackRemoved; + } + + _drawables.erase(_drawables.begin()+pos,_drawables.begin()+endOfRemoveRange); + + if (appCallbackRemoved) + { + setNumChildrenRequiringAppTraversal(getNumChildrenRequiringAppTraversal()-appCallbackRemoved); + } dirtyBound(); @@ -79,7 +98,6 @@ bool Geode::removeDrawable( Drawable *drawable ) else return false; } - bool Geode::replaceDrawable( Drawable *origDrawable, Drawable *newDrawable ) { if (newDrawable==NULL || origDrawable==newDrawable) return false; diff --git a/src/osg/Group.cpp b/src/osg/Group.cpp index ed3068ae3..ba408ab49 100644 --- a/src/osg/Group.cpp +++ b/src/osg/Group.cpp @@ -1,9 +1,11 @@ -#include -#include #include #include #include #include +#include + +#include +#include #include @@ -94,48 +96,60 @@ bool Group::addChild( Node *child ) else return false; } - bool Group::removeChild( Node *child ) { - ChildList::iterator itr = findNode(child); - if (itr!=_children.end()) + return removeChild(getChildIndex(child)); +} + +bool Group::removeChild(unsigned int pos,unsigned int numChildrenToRemove) +{ + if (pos<_children.size() && numChildrenToRemove>0) { - // remove this group from the child parent list. - child->removeParent(this); - - // could now require app traversal thanks to the new subgraph, - // so need to check and update if required. - // note, need to do this checking before the erase of the child - // otherwise child will be invalid. - if (child->getNumChildrenRequiringAppTraversal()>0 || - child->getAppCallback()) + unsigned int endOfRemoveRange = pos+numChildrenToRemove; + if (endOfRemoveRange>_children.size()) { - setNumChildrenRequiringAppTraversal( - getNumChildrenRequiringAppTraversal()-1 - ); + notify(DEBUG_INFO)<<"Warning: Group::removeChild(i,numChildrenToRemove) has been passed an excessive number"<getNumChildrenWithCullingDisabled()>0 || - !child->getCullingActive()) + unsigned int appCallbackRemoved = 0; + unsigned int numChildrenWithCullingDisabledRemoved = 0; + unsigned int numChildrenWithOccludersRemoved = 0; + + for(unsigned i=pos;iremoveParent(this); + + if (child->getNumChildrenRequiringAppTraversal()>0 || child->getAppCallback()) ++appCallbackRemoved; + + if (child->getNumChildrenWithCullingDisabled()>0 || !child->getCullingActive()) ++numChildrenWithCullingDisabledRemoved; + + if (child->getNumChildrenWithOccluderNodes()>0 || dynamic_cast(child)) ++numChildrenWithOccludersRemoved; + } - if (child->getNumChildrenWithOccluderNodes()>0 || - dynamic_cast(child)) - { - setNumChildrenWithOccluderNodes( - getNumChildrenWithOccluderNodes()-1 - ); - } + _children.erase(_children.begin()+pos,_children.begin()+endOfRemoveRange); - // note ref_ptr<> automatically handles decrementing child's reference count. - _children.erase(itr); + if (appCallbackRemoved) + { + setNumChildrenRequiringAppTraversal(getNumChildrenRequiringAppTraversal()-appCallbackRemoved); + } + + if (numChildrenWithCullingDisabledRemoved) + { + setNumChildrenWithCullingDisabled(getNumChildrenWithCullingDisabled()-numChildrenWithCullingDisabledRemoved); + } + + if (numChildrenWithOccludersRemoved) + { + setNumChildrenWithOccluderNodes(getNumChildrenWithOccluderNodes()-numChildrenWithOccludersRemoved); + } + dirtyBound(); - - + return true; } else return false; diff --git a/src/osg/Sequence.cpp b/src/osg/Sequence.cpp index 0fcba850e..48a219491 100644 --- a/src/osg/Sequence.cpp +++ b/src/osg/Sequence.cpp @@ -6,7 +6,8 @@ using namespace osg; * Sequence constructor. */ Sequence::Sequence() : - Switch(), + Group(), + _value(-1), _last(-1.0f), _step(1), _loopMode(LOOP), @@ -21,7 +22,8 @@ Sequence::Sequence() : } Sequence::Sequence(const Sequence& seq, const CopyOp& copyop) : - Switch(seq, copyop), + Group(seq, copyop), + _value(seq._value), _last(seq._last), _step(seq._step), _loopMode(seq._loopMode), @@ -82,7 +84,7 @@ void Sequence::setMode(SequenceMode mode) switch (mode) { case START: // restarts sequence in 'traverse' - setValue(ALL_CHILDREN_OFF); + setValue(-1); _mode = mode; break; case STOP: @@ -101,75 +103,89 @@ void Sequence::setMode(SequenceMode mode) void Sequence::traverse(NodeVisitor& nv) { + // if app traversal update the frame count. if (nv.getVisitorType()==NodeVisitor::APP_VISITOR && _mode == START && _nrepsremain) { - double t = nv.getFrameStamp()->getReferenceTime(); - if (_last == -1.0) - _last = t; + const FrameStamp* framestamp = nv.getFrameStamp(); + if (framestamp) + { + + double t = framestamp->getReferenceTime(); + if (_last == -1.0) + _last = t; - // first and last frame of interval - unsigned int nch = getNumChildren(); - int begin = (_begin < 0 ? nch + _begin : _begin); - int end = (_end < 0 ? nch + _end : _end); + // first and last frame of interval + unsigned int nch = getNumChildren(); + int begin = (_begin < 0 ? nch + _begin : _begin); + int end = (_end < 0 ? nch + _end : _end); - int sw = getValue(); - if (sw == ALL_CHILDREN_OFF || - sw == ALL_CHILDREN_ON || - sw == MULTIPLE_CHILDREN_ON ) { - sw = begin; - _step = (begin < end ? 1 : -1); - } - - // default timeout for unset values - if (sw >= (int) _frameTime.size()) { - setTime(sw, 1.0f); - } - - // frame time-out? - float dur = _frameTime[sw] * _speed; - if ((t - _last) > dur) { - - sw += _step; - - // check interval - int ibegin = (begin < end ? begin : end); - int iend = (end > begin ? end : begin); - //cerr << this << " interval " << ibegin << "," << iend << endl; - - if (sw < ibegin || sw > iend) { - // stop at last frame - if (sw < ibegin) - sw = ibegin; - else - sw = iend; - - // repeat counter - if (_nrepsremain > 0) - _nrepsremain--; - - if (_nrepsremain == 0) { - // stop - setMode(STOP); - } - else { - // wrap around - switch (_loopMode) { - case LOOP: - //cerr << this << " loop" << endl; - sw = begin; - break; - case SWING: - //cerr << this << " swing" << endl; - _step = -_step; - break; - } - } + int sw = getValue(); + if (sw<0) + { + sw = begin; + _step = (begin < end ? 1 : -1); } - _last = t; + // default timeout for unset values + if (sw >= (int) _frameTime.size()) + { + setTime(sw, 1.0f); + } + + // frame time-out? + float dur = _frameTime[sw] * _speed; + if ((t - _last) > dur) { + + sw += _step; + + // check interval + int ibegin = (begin < end ? begin : end); + int iend = (end > begin ? end : begin); + //cerr << this << " interval " << ibegin << "," << iend << endl; + + if (sw < ibegin || sw > iend) { + // stop at last frame + if (sw < ibegin) + sw = ibegin; + else + sw = iend; + + // repeat counter + if (_nrepsremain > 0) + _nrepsremain--; + + if (_nrepsremain == 0) { + // stop + setMode(STOP); + } + else { + // wrap around + switch (_loopMode) { + case LOOP: + //cerr << this << " loop" << endl; + sw = begin; + break; + case SWING: + //cerr << this << " swing" << endl; + _step = -_step; + break; + } + } + } + + _last = t; + } + setValue(sw); } - //cerr << this << " child=" << sw << endl; - setValue(sw); } - Switch::traverse(nv); + + // now do the traversal + if (nv.getTraversalMode()==NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) + { + if (getValue()>=0) _children[getValue()]->accept(nv); + } + else + { + Group::traverse(nv); + } } diff --git a/src/osg/Switch.cpp b/src/osg/Switch.cpp index ddc831c1c..332a3d776 100644 --- a/src/osg/Switch.cpp +++ b/src/osg/Switch.cpp @@ -18,23 +18,16 @@ Switch::Switch(const Switch& sw,const CopyOp& copyop): void Switch::traverse(NodeVisitor& nv) { - switch(nv.getTraversalMode()) + if (nv.getTraversalMode()==NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) { - case(NodeVisitor::TRAVERSE_ALL_CHILDREN): + for(unsigned int pos=0;pos<_children.size();++pos) { - std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv)); - break; + if (_values[pos]) _children[pos]->accept(nv); } - case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN): - { - for(unsigned int pos=0;pos<_children.size();++pos) - { - if (_values[pos]) _children[pos]->accept(nv); - } - break; - } - default: - break; + } + else + { + Group::traverse(nv); } } @@ -75,7 +68,7 @@ void Switch::setValue(unsigned int pos,bool value) _values[pos]=value; } -void Switch::setValue(const Node* child,bool value) +void Switch::setChildValue(const Node* child,bool value) { // find the child's position. unsigned int pos=getChildIndex(child); @@ -90,7 +83,7 @@ bool Switch::getValue(unsigned int pos) const return _values[pos]; } -bool Switch::getValue(const Node* child) const +bool Switch::getChildValue(const Node* child) const { // find the child's position. unsigned int pos=getChildIndex(child); @@ -99,6 +92,43 @@ bool Switch::getValue(const Node* child) const return _values[pos]; } +bool Switch::setAllChildrenOff() +{ + _newChildDefaultValue = false; + for(ValueList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + *itr = false; + } + return true; +} + +bool Switch::setAllChildrenOn() +{ + _newChildDefaultValue = true; + for(ValueList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + *itr = true; + } + return true; +} + +bool Switch::setSingleChildOn(unsigned int pos) +{ + for(ValueList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + *itr = false; + } + setValue(pos,true); + return true; +} + +#ifdef USE_DEPRECTATED_API void Switch::setValue(int value) { switch(value) @@ -165,3 +195,4 @@ int Switch::getValue() const return firstChildSelected; } +#endif diff --git a/src/osgPlugins/geo/ReaderWriterGEO.cpp b/src/osgPlugins/geo/ReaderWriterGEO.cpp index 0cc6fe8ef..a1c85fc31 100644 --- a/src/osgPlugins/geo/ReaderWriterGEO.cpp +++ b/src/osgPlugins/geo/ReaderWriterGEO.cpp @@ -1172,14 +1172,22 @@ class ReaderWriterGEO : public ReaderWriter osg::Group *makeSwitch(const georecord *gr) { osg::Switch *sw=new Switch; const geoField *gfd=gr->getField(GEO_DB_SWITCH_CURRENT_MASK); - sw->setValue(osg::Switch::ALL_CHILDREN_OFF); + sw->setAllChildrenOff(); if (gfd) { - int imask; + int imask; // bit surprised this isn't a uint.. Robert Dec 2002. imask=gfd->getInt(); - sw->setValue(imask); + + // will set all 32 bits of the mask into the switch right now, + // should cap to only set the number of children in the switch. + int selector_mask = 0x1; + for(unsigned int i=0;i<32;++i) + { + sw->setValue(i,(imask&selector_mask)); + selector_mask <<= 1; + } osg::notify(osg::WARN) << gr << " imask " << imask << std::endl; } else { - sw->setValue(0); + sw->setSingleChildOn(0); osg::notify(osg::WARN) << gr << " No mask " << std::endl; } gfd=gr->getField(GEO_DB_SWITCH_NAME); diff --git a/src/osgPlugins/osg/Switch.cpp b/src/osgPlugins/osg/Switch.cpp index ad754f24f..cf3d536e1 100644 --- a/src/osgPlugins/osg/Switch.cpp +++ b/src/osgPlugins/osg/Switch.cpp @@ -31,26 +31,50 @@ bool Switch_readLocalData(Object& obj, Input& fr) { if (fr[1].matchWord("ALL_CHILDREN_ON")) { - sw.setValue(Switch::ALL_CHILDREN_ON); + sw.setAllChildrenOn(); iteratorAdvanced = true; fr+=2; } else if (fr[1].matchWord("ALL_CHILDREN_OFF")) { - sw.setValue(Switch::ALL_CHILDREN_OFF); + sw.setAllChildrenOff(); iteratorAdvanced = true; fr+=2; } else if (fr[1].isInt()) { - int value; - fr[1].getInt(value); - sw.setValue(value); + unsigned int value; + fr[1].getUInt(value); + sw.setSingleChildOn(value); iteratorAdvanced = true; fr+=2; } } + if (fr[0].matchWord("NewChildDefaultValue")) + { + if (fr[1].matchWord("TRUE")) + { + sw.setNewChildDefaultValue(true); + iteratorAdvanced = true; + fr += 2; + } + else if (fr[1].matchWord("FALSE")) + { + sw.setNewChildDefaultValue(false); + iteratorAdvanced = true; + fr += 2; + } + else if (fr[1].isInt()) + { + int value; + fr[1].getInt(value); + sw.setNewChildDefaultValue(value); + iteratorAdvanced = true; + fr += 2; + } + } + if (fr.matchSequence("ValueList {")) { int entry = fr[0].getNoNestedBrackets(); @@ -64,7 +88,7 @@ bool Switch_readLocalData(Object& obj, Input& fr) int value; if (fr[0].getInt(value)) { - sw.setValue(value); + sw.setValue(pos,value); ++pos; } ++fr; @@ -84,28 +108,20 @@ bool Switch_writeLocalData(const Object& obj, Output& fw) { const Switch& sw = static_cast(obj); - int value=sw.getValue(); - switch(value) + + fw.indent()<<"NewChildDefaultValue "<