diff --git a/VisualStudio/osgPlugins/osgSim/dot_osgSim.dsp b/VisualStudio/osgPlugins/osgSim/dot_osgSim.dsp index a9605567a..ccc83efd7 100644 --- a/VisualStudio/osgPlugins/osgSim/dot_osgSim.dsp +++ b/VisualStudio/osgPlugins/osgSim/dot_osgSim.dsp @@ -224,6 +224,14 @@ SOURCE=..\..\..\src\osgPlugins\osgSim\IO_BlinkSequence.cpp # End Source File +# Begin Source File + + + +SOURCE=..\..\..\src\osgPlugins\osgSim\IO_MultiSwitch.cpp + +# End Source File + # End Group # Begin Group "Header Files" diff --git a/VisualStudio/osgSim/osgSim.dsp b/VisualStudio/osgSim/osgSim.dsp index 0adfc8a92..101eebdc4 100644 --- a/VisualStudio/osgSim/osgSim.dsp +++ b/VisualStudio/osgSim/osgSim.dsp @@ -133,6 +133,10 @@ SOURCE=..\..\src\osgSim\SphereSegment.cpp # End Source File # Begin Source File +SOURCE=..\..\src\osgSim\MultiSwitch.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\osgSim\Version.cpp # End Source File # End Group @@ -181,6 +185,10 @@ SOURCE=..\..\include\osgSim\SphereSegment # End Source File # Begin Source File +SOURCE=..\..\include\osgSim\MultiSwitch +# End Source File +# Begin Source File + SOURCE=..\..\include\osgSim\Export # End Source File # Begin Source File diff --git a/include/osgSim/MultiSwitch b/include/osgSim/MultiSwitch new file mode 100644 index 000000000..6c3b108e1 --- /dev/null +++ b/include/osgSim/MultiSwitch @@ -0,0 +1,91 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSG_MULTISWITCH +#define OSG_MULTISWITCH 1 + +#include + +namespace osgSim { + +/** MultiSwitch is a Group node which allows switching between sets of selected children. + MultiSwtich is based on the OpenFlight switch behaviour. +*/ +class SG_EXPORT MultiSwitch : public osg::Group +{ + public : + + + MultiSwitch(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + MultiSwitch(const MultiSwitch&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(osgSim, MultiSwitch); + + virtual void traverse(osg::NodeVisitor& nv); + + void setNewChildDefaultValue(bool value) { _newChildDefaultValue = value; } + + bool getNewChildDefaultValue() const { return _newChildDefaultValue; } + + virtual bool addChild( Node *child ); + + virtual bool insertChild( unsigned int index, Node *child ); + + virtual bool removeChild( Node *child ); + + void setValue(unsigned int switchSet, unsigned int pos,bool value); + + bool getValue(unsigned int switchSet, unsigned int pos) const; + + void setChildValue(const Node* child,unsigned int switchSet, bool value); + + bool getChildValue(const Node* child,unsigned int switchSet) const; + + /** Set all the children off (false), and set the new default child value to off (false).*/ + bool setAllChildrenOff(unsigned int switchSet); + + /** Set all the children on (true), and set the new default child value to on (true).*/ + bool setAllChildrenOn(unsigned int switchSet); + + /** Set a single child to be on, MultiSwitch off all other children.*/ + bool setSingleChildOn(unsigned int switchSet, unsigned int pos); + + /** Set which of the available switch set lists to use.*/ + void setActiveSwitchSet(unsigned int switchSet) { _activeSwitchSet = switchSet; } + + /** Get which of the available switch set lists to use.*/ + unsigned int getActiveSwitchSet(unsigned int switchSet) { return _activeSwitchSet; } + + typedef std::vector ValueList; + typedef std::vector SwitchSetList; + + const SwitchSetList& getSwitchSetList() const { return _values; } + const ValueList& getValueList(unsigned int switchSet) const { return _values[switchSet]; } + + protected : + + virtual ~MultiSwitch() {} + + void expandToEncompassSwitchSet(unsigned int switchSet); + + // this is effectively a list of bit mask. + bool _newChildDefaultValue; + unsigned int _activeSwitchSet; + SwitchSetList _values; +}; + +} + +#endif diff --git a/src/osgPlugins/flt/flt2osg.cpp b/src/osgPlugins/flt/flt2osg.cpp index 481dbf14c..fbb1b7d6a 100644 --- a/src/osgPlugins/flt/flt2osg.cpp +++ b/src/osgPlugins/flt/flt2osg.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -29,15 +28,16 @@ #include #include #include - #include +#include +#include + #include #include #include #include -#include #include "opcodes.h" #include "flt.h" @@ -997,23 +997,22 @@ osg::Group* ConvertFromFLT::visitDOF(osg::Group& osgParent, DofRecord* rec) osg::Group* ConvertFromFLT::visitSwitch(osg::Group& osgParent, SwitchRecord* rec) { SSwitch *pSSwitch = (SSwitch*)rec->getData(); - osg::Switch* osgSwitch = new osg::Switch; + osgSim::MultiSwitch* osgSwitch = new osgSim::MultiSwitch; osgSwitch->setName(pSSwitch->szIdent); visitAncillary(osgParent, *osgSwitch, rec)->addChild( osgSwitch ); - osg::ref_ptr allChildrenGroup = new osg::Group; - visitPrimaryNode(*allChildrenGroup, (PrimNodeRecord*)rec); + visitPrimaryNode(*osgSwitch, (PrimNodeRecord*)rec); unsigned int totalNumChildren = (unsigned int)rec->getNumChildren(); - if (totalNumChildren!=allChildrenGroup->getNumChildren()) + if (totalNumChildren!=osgSwitch->getNumChildren()) { // only convert the children we agree on, // however, there could be a chance that ordering of children might // be different if there a children that hanvn't mapped across... - if (totalNumChildren>allChildrenGroup->getNumChildren()) totalNumChildren=allChildrenGroup->getNumChildren(); + if (totalNumChildren>osgSwitch->getNumChildren()) totalNumChildren=osgSwitch->getNumChildren(); osg::notify(osg::INFO)<<"Warning::OpenFlight loader has come across an incorrectly handled switch."<getNumChildren()<<") "<getNumChildren()<<")"<getNumChildren()<<")"< group = new osg::Group; osgSwitch->addChild( group.get() ); // for each child in the FLT Switch node - for (unsigned itChild=0; itChildnWordsInMask + itChild / 32; - if ( (pSSwitch->aMask[nMaskWord] & (uint32(1) << nMaskBit))!=0 ) - { - // add this child in the group - group->addChild( allChildrenGroup->getChild(itChild) ); - } + osgSwitch->setValue(itMask, itChild, (pSSwitch->aMask[nMaskWord] & (uint32(1) << nMaskBit))!=0 ); } // now the group contain all the childrens that are active in the current mask (itMask) } - osgSwitch->setSingleChildOn(pSSwitch->nCurrentMask); + osgSwitch->setActiveSwitchSet(pSSwitch->nCurrentMask); return osgSwitch; } diff --git a/src/osgPlugins/osgSim/GNUmakefile b/src/osgPlugins/osgSim/GNUmakefile index a93e95e85..c38298467 100644 --- a/src/osgPlugins/osgSim/GNUmakefile +++ b/src/osgPlugins/osgSim/GNUmakefile @@ -6,6 +6,7 @@ CXXFILES =\ IO_LightPointNode.cpp\ IO_LightPoint.cpp\ IO_BlinkSequence.cpp\ + IO_MultiSwitch.cpp\ IO_Sector.cpp LIBS += -losgSim -losgText $(OSG_LIBS) $(OTHER_LIBS) diff --git a/src/osgPlugins/osgSim/IO_MultiSwitch.cpp b/src/osgPlugins/osgSim/IO_MultiSwitch.cpp new file mode 100644 index 000000000..7212716f4 --- /dev/null +++ b/src/osgPlugins/osgSim/IO_MultiSwitch.cpp @@ -0,0 +1,113 @@ +#include "osgSim/MultiSwitch" + +#include "osgDB/Registry" +#include "osgDB/Input" +#include "osgDB/Output" + +using namespace osg; +using namespace osgSim; +using namespace osgDB; + +// forward declare functions to use later. +bool MultiSwitch_readLocalData(Object& obj, Input& fr); +bool MultiSwitch_writeLocalData(const Object& obj, Output& fw); + +// register the read and write functions with the osgDB::Registry. +RegisterDotOsgWrapperProxy g_SwitchProxy +( + new osgSim::MultiSwitch, + "MultiSwitch", + "Object Node MultiSwitch Group", + &MultiSwitch_readLocalData, + &MultiSwitch_writeLocalData +); + +bool MultiSwitch_readLocalData(Object& obj, Input& fr) +{ + bool iteratorAdvanced = false; + + MultiSwitch& sw = static_cast(obj); + + 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!=0); + iteratorAdvanced = true; + fr += 2; + } + } + + if (fr.matchSequence("ValueList %i {")) + { + int entry = fr[0].getNoNestedBrackets(); + + unsigned int switchSet; + fr[1].getUInt(switchSet); + + // move inside the brakets. + fr += 3; + + unsigned int pos=0; + while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) + { + int value; + if (fr[0].getInt(value)) + { + sw.setValue(switchSet, pos,value!=0); + ++pos; + } + ++fr; + } + + ++fr; + + iteratorAdvanced = true; + + } + + return iteratorAdvanced; +} + + +bool MultiSwitch_writeLocalData(const Object& obj, Output& fw) +{ + const MultiSwitch& sw = static_cast(obj); + + + fw.indent()<<"NewChildDefaultValue "< + +#include + +using namespace osgSim; + +MultiSwitch::MultiSwitch(): + _newChildDefaultValue(true), + _activeSwitchSet(0) +{ +} + +MultiSwitch::MultiSwitch(const MultiSwitch& sw,const osg::CopyOp& copyop): + osg::Group(sw,copyop), + _newChildDefaultValue(sw._newChildDefaultValue), + _values(sw._values) +{ +} + +void MultiSwitch::traverse(osg::NodeVisitor& nv) +{ + if (nv.getTraversalMode()==osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) + { + + if (_activeSwitchSet<_values.size()) + { + for(unsigned int pos=0;pos<_children.size();++pos) + { + if (_values[_activeSwitchSet][pos]) _children[pos]->accept(nv); + } + } + } + else + { + Group::traverse(nv); + } +} + +bool MultiSwitch::addChild( Node *child) +{ + unsigned int childPosition = _children.size(); + if (Group::addChild(child)) + { + for(SwitchSetList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + ValueList& values = *itr; + if (_children.size()>_values.size()) + { + values.resize(_children.size(),_newChildDefaultValue); + values[childPosition]=_newChildDefaultValue; + } + } + return true; + } + return false; +} + +bool MultiSwitch::insertChild( unsigned int index, Node *child) +{ + if (Group::insertChild(index,child)) + { + for(SwitchSetList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + ValueList& values = *itr; + if (index>=_values.size()) + { + values.push_back(_newChildDefaultValue); + } + else + { + values.insert(values.begin()+index, _newChildDefaultValue); + } + } + + + return true; + } + return false; +} + +bool MultiSwitch::removeChild( Node *child ) +{ + // find the child's position. + unsigned int pos=getChildIndex(child); + if (pos==_children.size()) return false; + + for(SwitchSetList::iterator itr=_values.begin(); + itr!=_values.end(); + ++itr) + { + ValueList& values = *itr; + values.erase(values.begin()+pos); + } + + return Group::removeChild(child); +} + +void MultiSwitch::setValue(unsigned int switchSet, unsigned int pos,bool value) +{ + expandToEncompassSwitchSet(switchSet); + + ValueList& values = _values[switchSet]; + if (pos>=values.size()) values.resize(pos+1,_newChildDefaultValue); + values[pos]=value; +} + +void MultiSwitch::setChildValue(const Node* child,unsigned int switchSet, bool value) +{ + expandToEncompassSwitchSet(switchSet); + + // find the child's position. + unsigned int pos=getChildIndex(child); + if (pos==_children.size()) return; + + ValueList& values = _values[switchSet]; + values[pos]=value; +} + +bool MultiSwitch::getValue(unsigned int switchSet, unsigned int pos) const +{ + if (switchSet>=_values.size()) return false; + + const ValueList& values = _values[switchSet]; + if (pos>=values.size()) return false; + + return values[pos]; +} + +bool MultiSwitch::getChildValue(const Node* child, unsigned int switchSet) const +{ + if (switchSet>=_values.size()) return false; + + // find the child's position. + unsigned int pos=getChildIndex(child); + if (pos==_children.size()) return false; + + const ValueList& values = _values[switchSet]; + return values[pos]; +} + +void MultiSwitch::expandToEncompassSwitchSet(unsigned int switchSet) +{ + if (switchSet>=_values.size()) + { + // need to expand arrays. + unsigned int originalSize = _values.size(); + _values.resize(switchSet+1); + for(unsigned int i=originalSize;i<=switchSet;++i) + { + ValueList& values = _values[switchSet]; + values.resize(_children.size(),_newChildDefaultValue); + } + } +} + +bool MultiSwitch::setAllChildrenOff(unsigned int switchSet) +{ + _newChildDefaultValue = false; + + expandToEncompassSwitchSet(switchSet); + + ValueList& values = _values[switchSet]; + for(ValueList::iterator itr=values.begin(); + itr!=values.end(); + ++itr) + { + *itr = false; + } + return true; +} + +bool MultiSwitch::setAllChildrenOn(unsigned int switchSet) +{ + _newChildDefaultValue = true; + + expandToEncompassSwitchSet(switchSet); + + ValueList& values = _values[switchSet]; + for(ValueList::iterator itr=values.begin(); + itr!=values.end(); + ++itr) + { + *itr = true; + } + return true; +} + +bool MultiSwitch::setSingleChildOn(unsigned int switchSet, unsigned int pos) +{ + expandToEncompassSwitchSet(switchSet); + + ValueList& values = _values[switchSet]; + for(ValueList::iterator itr=values.begin(); + itr!=values.end(); + ++itr) + { + *itr = false; + } + setValue(switchSet, pos,true); + return true; +}