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<