From 4a3cc5c1821f549d6c4c95c62b5aa4b08c599b70 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 4 Oct 2002 14:50:33 +0000 Subject: [PATCH] Implemented OpenFlight style switches so that each child of a switch can now be individually turned on or off. Moved the OpenFlight code across to use the new scheme, removing the old hack of using node masks to achieve the same end result. --- include/osg/Switch | 53 ++++++++---- src/Demos/sgv/sgv.cpp | 4 +- src/osg/Sequence.cpp | 4 +- src/osg/Switch.cpp | 146 ++++++++++++++++++++++++++++++--- src/osgPlugins/flt/flt2osg.cpp | 40 ++++++++- src/osgPlugins/osg/Switch.cpp | 50 +++++++++-- 6 files changed, 258 insertions(+), 39 deletions(-) diff --git a/include/osg/Switch b/include/osg/Switch index 6ed85a70f..a958c5b40 100644 --- a/include/osg/Switch +++ b/include/osg/Switch @@ -18,16 +18,6 @@ class SG_EXPORT Switch : public Group { public : - /** - * Special mode values for the Switch. Use these if you want to - * turn on/off all child nodes. - */ - enum SwitchType { - /** Turn on all children. */ - ALL_CHILDREN_ON=-1, - /** Turn off all children. */ - ALL_CHILDREN_OFF=-2 - }; Switch(); @@ -38,6 +28,31 @@ class SG_EXPORT Switch : public Group virtual void traverse(NodeVisitor& nv); + virtual bool addChild( Node *child ); + + virtual bool removeChild( Node *child ); + + 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; + + /** + * Special values for the Switch. Use these if you want to + * turn on/off all child nodes. + */ + enum Values { + /** All children turned on. */ + ALL_CHILDREN_ON=-1, + /** All children off. */ + ALL_CHILDREN_OFF=-2, + /** Multiple children turned on.*/ + MULTIPLE_CHILDREN_ON=-3 + }; + /** * Selects the active child Node or enables a special * SwitchType mode. @@ -45,18 +60,20 @@ class SG_EXPORT Switch : public Group * (first child == number 0) or SwitchType. Invalid values * will be ignored. */ - inline void setValue(int value) { _value = value; } - /** - * Returns the number of the active child Node or the SwitchType. - */ - inline int getValue() const { return _value; } + void setValue(int value); + + int getValue() const; + + typedef std::vector ValueList; + + const ValueList& getValueList() const { return _values; } protected : virtual ~Switch() {} - - /** The current Switch value. */ - int _value; + + // this is effectively a bit mask. + ValueList _values; }; } diff --git a/src/Demos/sgv/sgv.cpp b/src/Demos/sgv/sgv.cpp index f50c952b3..31586b26b 100644 --- a/src/Demos/sgv/sgv.cpp +++ b/src/Demos/sgv/sgv.cpp @@ -140,8 +140,8 @@ int main( int argc, char **argv ) osgUtil::RenderStage* renderstage = viewer.getViewportSceneView(0)->getRenderStage(); if (renderstage) { -// renderstage->setSortLocalCallback(new MySortCallback); - renderstage->setSortMode(osgUtil::RenderBin::SORT_FRONT_TO_BACK); + renderstage->setSortLocalCallback(new MySortCallback); +// renderstage->setSortMode(osgUtil::RenderBin::SORT_FRONT_TO_BACK); } diff --git a/src/osg/Sequence.cpp b/src/osg/Sequence.cpp index a49f4ee56..0fcba850e 100644 --- a/src/osg/Sequence.cpp +++ b/src/osg/Sequence.cpp @@ -113,7 +113,9 @@ void Sequence::traverse(NodeVisitor& nv) int end = (_end < 0 ? nch + _end : _end); int sw = getValue(); - if (sw == ALL_CHILDREN_OFF || sw == ALL_CHILDREN_ON) { + if (sw == ALL_CHILDREN_OFF || + sw == ALL_CHILDREN_ON || + sw == MULTIPLE_CHILDREN_ON ) { sw = begin; _step = (begin < end ? 1 : -1); } diff --git a/src/osg/Switch.cpp b/src/osg/Switch.cpp index 1fa76af35..de82500f6 100644 --- a/src/osg/Switch.cpp +++ b/src/osg/Switch.cpp @@ -10,12 +10,11 @@ using namespace osg; */ Switch::Switch() { - _value = ALL_CHILDREN_OFF; } Switch::Switch(const Switch& sw,const CopyOp& copyop): Group(sw,copyop), - _value(sw._value) + _values(sw._values) { } @@ -24,23 +23,148 @@ void Switch::traverse(NodeVisitor& nv) switch(nv.getTraversalMode()) { case(NodeVisitor::TRAVERSE_ALL_CHILDREN): + { std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv)); break; + } case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN): - switch(_value) + { + for(unsigned int pos=0;pos<_children.size();++pos) { - case(ALL_CHILDREN_ON): - std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv)); - break; - case(ALL_CHILDREN_OFF): - return; - default: - if (_value>=0 && (unsigned int)_value<_children.size()) _children[_value]->accept(nv); - break; + if (_values[pos]) _children[pos]->accept(nv); } break; + } default: break; } } +bool Switch::addChild( Node *child ) +{ + if (Group::addChild(child)) + { + if (_children.size()>_values.size()) _values.resize(_children.size(),false); + return true; + } + return false; +} + +bool Switch::removeChild( Node *child ) +{ + // find the child's position. + unsigned int pos=0; + for (;pos<_children.size();++pos) + { + if (_children[pos]==child) break; + } + if (pos==_children.size()) return false; + + _values.erase(_values.begin()+pos); + + return Group::removeChild(child); + +} + +void Switch::setValue(unsigned int pos,bool value) +{ + if (pos>=_values.size()) _values.resize(pos+1,false); + _values[pos]=value; +} + +void Switch::setValue(const Node* child,bool value) +{ + // find the child's position. + unsigned int pos=0; + for (;pos<_children.size();++pos) + { + if (_children[pos]==child) break; + } + if (pos==_children.size()) return; + + _values[pos]=value; +} + +bool Switch::getValue(unsigned int pos) const +{ + if (pos>=_values.size()) return false; + return _values[pos]; +} + +bool Switch::getValue(const Node* child) const +{ + // find the child's position. + unsigned int pos=0; + for (;pos<_children.size();++pos) + { + if (_children[pos]==child) break; + } + if (pos==_children.size()) return false; + + return _values[pos]; +} + +void Switch::setValue(int value) +{ + switch(value) + { + case(MULTIPLE_CHILDREN_ON): + // do nothing... + break; + case(ALL_CHILDREN_OFF): + { + for(ValueList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + *itr = false; + } + break; + } + case(ALL_CHILDREN_ON): + { + for(ValueList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + *itr = true; + } + break; + } + default: + { + for(ValueList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + *itr = false; + } + setValue(value,true); + break; + } + } +} + +int Switch::getValue() const +{ + if (_values.empty()) return ALL_CHILDREN_OFF; + + unsigned int noChildrenSwitchedOn=0; + int firstChildSelected=ALL_CHILDREN_OFF; + for(unsigned int i=0; i<_values.size();++i) + { + if (_values[i]) + { + ++noChildrenSwitchedOn; + if (firstChildSelected==ALL_CHILDREN_OFF) firstChildSelected=i; + } + } + + if (noChildrenSwitchedOn>1) + { + if (noChildrenSwitchedOn==_values.size()) return ALL_CHILDREN_ON; + else return MULTIPLE_CHILDREN_ON; + } + return firstChildSelected; + +} diff --git a/src/osgPlugins/flt/flt2osg.cpp b/src/osgPlugins/flt/flt2osg.cpp index 0afd8ad29..7d5d4edcf 100644 --- a/src/osgPlugins/flt/flt2osg.cpp +++ b/src/osgPlugins/flt/flt2osg.cpp @@ -605,6 +605,9 @@ osg::Group* ConvertFromFLT::visitGroup(osg::Group& osgParent, GroupRecord* rec) { osg::Sequence* animSeq = new osg::Sequence; + visitAncillary(osgParent, *animSeq, rec)->addChild( animSeq ); + visitPrimaryNode(*animSeq, rec); + if ( forwardAnim ) animSeq->setInterval(osg::Sequence::LOOP, 0, -1); else @@ -612,8 +615,6 @@ osg::Group* ConvertFromFLT::visitGroup(osg::Group& osgParent, GroupRecord* rec) animSeq->setName(rec->getData()->szIdent); - visitAncillary(osgParent, *animSeq, rec)->addChild( animSeq ); - visitPrimaryNode(*animSeq, rec); return animSeq; } @@ -883,6 +884,40 @@ osg::Group* ConvertFromFLT::visitDOF(osg::Group& osgParent, DofRecord* rec) osg::Group* ConvertFromFLT::visitSwitch(osg::Group& osgParent, SwitchRecord* rec) { +#if 1 + SSwitch *pSSwitch = (SSwitch*)rec->getData(); + osg::Switch* osgSwitch = new osg::Switch; + + osgSwitch->setName(pSSwitch->szIdent); + visitAncillary(osgParent, *osgSwitch, rec)->addChild( osgSwitch ); + visitPrimaryNode(*osgSwitch, (PrimNodeRecord*)rec); + + + unsigned int totalNumChildren = (unsigned int)rec->getNumChildren(); + if (totalNumChildren!=osgSwitch->getNumChildren()) + { + // only convert the children we agree on. + if (totalNumChildren>osgSwitch->getNumChildren()) totalNumChildren=osgSwitch->getNumChildren(); + + osg::notify(osg::WARN)<<"Warning::OpenFlight loader has come across an incorrectly handled switch."<getNumChildren()<<") "<getNumChildren()<<")"<nCurrentMask * pSSwitch->nWordsInMask + nChild / 32; + + if (nChildgetNumChildren()) + { + osgSwitch->setValue(nChild,(pSSwitch->aMask[nMaskWord] & (uint32(1) << nMaskBit))); + } + } + + return osgSwitch; +#else + // Old style osg::Switch couldn't handle the OpenFlight bit mask so had to resort to a group with masked out children. SSwitch *pSSwitch = (SSwitch*)rec->getData(); osg::Group* group = new osg::Group; @@ -915,6 +950,7 @@ osg::Group* ConvertFromFLT::visitSwitch(osg::Group& osgParent, SwitchRecord* rec } return group; +#endif } diff --git a/src/osgPlugins/osg/Switch.cpp b/src/osgPlugins/osg/Switch.cpp index fd5558181..20b41aa52 100644 --- a/src/osgPlugins/osg/Switch.cpp +++ b/src/osgPlugins/osg/Switch.cpp @@ -51,6 +51,31 @@ bool Switch_readLocalData(Object& obj, Input& fr) } } + if (fr.matchSequence("values {")) + { + int entry = fr[0].getNoNestedBrackets(); + + // move inside the brakets. + fr += 2; + + unsigned int pos=0; + while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) + { + int value; + if (fr[0].getInt(value)) + { + sw.setValue(pos,value); + ++pos; + } + ++fr; + } + + ++fr; + + iteratorAdvanced = true; + + } + return iteratorAdvanced; } @@ -59,12 +84,27 @@ bool Switch_writeLocalData(const Object& obj, Output& fw) { const Switch& sw = static_cast(obj); - fw.indent() << "value "; - switch(sw.getValue()) + int value=sw.getValue(); + switch(value) { - case(Switch::ALL_CHILDREN_ON): fw<<"ALL_CHILDREN_ON"<< std::endl;break; - case(Switch::ALL_CHILDREN_OFF): fw<<"ALL_CHILDREN_OFF"<< std::endl;break; - default: fw<