/*! Action method for SoWriteAction. Writes out a node object, and any connected nodes, engines etc, if necessary. */ void SoNode::write(SoWriteAction * action) { SoOutput * out = action->getOutput(); SoNode * node = this; SoProtoInstance * proto = SoProtoInstance::findProtoInstance(this); if (proto) { node = proto; } if (out->getStage() == SoOutput::COUNT_REFS) { node->addWriteReference(out, FALSE); } else if (out->getStage() == SoOutput::WRITE) { if (node->writeHeader(out, FALSE, FALSE)) return; // check for special case where we actually have to write out an // SoEngineOutput "field". An engine output might be connected via // an IS reference in a PROTO, and we then need to write back this // IS reference when exporting the VRML file. SoProto * proto = out->getCurrentProto(); if (proto && node->isOfType(SoNodeEngine::getClassTypeId())) { SoEngineOutputList l; const int num = ((SoNodeEngine*)node)->getOutputs(l); for (int i = 0; i < num; i++) { SbName name; if (((SoNodeEngine*)node)->getOutputName(l[i], name)) { SbName pname = proto->findISReference(node, name); if (pname.getLength()) { out->indent(); out->write(name.getString()); out->write(" IS "); out->write(pname.getString()); out->write("\n"); } } } } node->getFieldData()->write(out, node); node->writeFooter(out); } else assert(0 && "unknown stage"); }
void SoSwitch::write(SoWriteAction *action) // //////////////////////////////////////////////////////////////////////// { SoOutput *out = action->getOutput(); // When writing out a switch that is in a path, we always want to // write out ALL children of the switch. If we did the default // thing of writing out just those children that affect the nodes // in the path, we could screw up. Consider a switch that has two // child separators and whichChild set to 1. If a path goes // through the switch to the second child, the first child, being // a separator, does not affect the path. But if we don't write // out the separator, the whichChild will reference a // nonexistent child. So we always write out all children. // NOTE: SoChildList::traverse() checks the current path code and // skips children off the path that do not affect the // state. Because of this we have to avoid calling it. Instead, we // do its work here. // This code is stolen and modified from SoGroup::write() and // SoChildList::traverse() int lastChild = getNumChildren() - 1; SoAction::PathCode pc = action->getCurPathCode(); // In write-reference counting phase if (out->getStage() == SoOutput::COUNT_REFS) { // Increment our write reference count addWriteReference(out); // If this is the first reference (i.e., we don't now have // multiple references), also count all appropriate children if (! hasMultipleWriteRefs()) { for (int i = 0; i <= lastChild; i++) { action->pushCurPath(i); action->traverse(getChild(i)); action->popCurPath(pc); } } } // In writing phase, we have to do some more work else if (! writeHeader(out, TRUE, FALSE)) { // Write fields const SoFieldData *fieldData = getFieldData(); fieldData->write(out, this); // We KNOW that all children should be written, so don't // bother calling shouldWrite() // If writing binary format, write out number of children // that are going to be written if (out->isBinary()) out->write(getNumChildren()); for (int i = 0; i <= lastChild; i++) { action->pushCurPath(i); action->traverse(getChild(i)); action->popCurPath(pc); } // Write post-children stuff writeFooter(out); } }