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.
This commit is contained in:
@@ -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<bool> ValueList;
|
||||
|
||||
const ValueList& getValueList() const { return _values; }
|
||||
|
||||
protected :
|
||||
|
||||
virtual ~Switch() {}
|
||||
|
||||
/** The current Switch value. */
|
||||
int _value;
|
||||
|
||||
// this is effectively a bit mask.
|
||||
ValueList _values;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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."<<std::endl;
|
||||
osg::notify(osg::WARN)<<" The number of OpenFlight children ("<<rec->getNumChildren()<<") "<<std::endl;
|
||||
osg::notify(osg::WARN)<<" exceeds the number converted to OSG ("<<osgSwitch->getNumChildren()<<")"<<std::endl;
|
||||
}
|
||||
|
||||
for(unsigned int nChild=0; nChild<totalNumChildren; nChild++)
|
||||
{
|
||||
unsigned int nMaskBit = nChild % 32;
|
||||
unsigned int nMaskWord = pSSwitch->nCurrentMask * pSSwitch->nWordsInMask + nChild / 32;
|
||||
|
||||
if (nChild<osgSwitch->getNumChildren())
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<const Switch&>(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<<sw.getValue()<< std::endl;break;
|
||||
case(Switch::MULTIPLE_CHILDREN_ON):
|
||||
{
|
||||
fw.indent()<<"values {"<< std::endl;
|
||||
fw.moveIn();
|
||||
const Switch::ValueList& values = sw.getValueList();
|
||||
for(Switch::ValueList::const_iterator itr=values.begin();
|
||||
itr!=values.end();
|
||||
++itr)
|
||||
{
|
||||
fw.indent()<<*itr<<endl;
|
||||
}
|
||||
fw.moveOut();
|
||||
fw.indent()<<"}"<< std::endl;
|
||||
break;
|
||||
}
|
||||
case(Switch::ALL_CHILDREN_ON): fw.indent()<<"value ALL_CHILDREN_ON"<< std::endl;break;
|
||||
case(Switch::ALL_CHILDREN_OFF): fw.indent()<<"value ALL_CHILDREN_OFF"<< std::endl;break;
|
||||
default: fw.indent()<<"value "<<value<< std::endl;break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user