void VrmlNodeProto::instantiate() { System::the->debug("%s::%s instantiate\n", d_nodeType->getName(), name()); if (!d_nodes) { VrmlMFNode *protoNodes = d_nodeType->getImplementationNodes(); int nNodes = protoNodes ? protoNodes->size() : 0; int i; d_scope = new VrmlNamespace(); // Clear all flags - encountering a set flag during cloning // indicates a USEd node, which should be referenced rather // than cloned. for (i = 0; i < nNodes; ++i) protoNodes->get(i)->clearFlags(); // Clone nodes // Those squeamish about broken encapsulations shouldn't look... d_nodes = new VrmlMFNode(nNodes, 0); VrmlNode **clone = d_nodes->get(); for (i = 0; i < nNodes; ++i) { clone[i] = protoNodes->get(i)->clone(d_scope)->reference(); clone[i]->parentList.push_back(this); if (clone[i]->getTraversalForce() > 0) { forceTraversal(false, clone[i]->getTraversalForce()); } } // Copy internal (to the PROTO implementation) ROUTEs. for (i = 0; i < nNodes; ++i) protoNodes->get(i)->copyRoutes(d_scope); // Collect eventIns coming from outside the PROTO. // A list of eventIns along with their maps to local // nodes/eventIns is constructed for each instance. VrmlNodeType::FieldList &eventIns = d_nodeType->eventIns(); VrmlNodeType::FieldList::iterator ev; VrmlNodeType::ISMap *ismap; VrmlNodeType::ISMap::const_iterator j; for (ev = eventIns.begin(); ev != eventIns.end(); ++ev) { EventDispatch *ed = new EventDispatch; char *eventName = (*ev)->name; ed->name = new char[strlen(eventName) + 1]; strcpy(ed->name, eventName); ismap = &(*ev)->thisIS; d_eventDispatch.push_front(ed); for (j = ismap->begin(); j != ismap->end(); ++j) { VrmlNodeType::NodeFieldRec *nf = new VrmlNodeType::NodeFieldRec; nf->node = d_scope->findNode((*j)->node->name()); nf->fieldName = new char[strlen((*j)->fieldName) + 1]; strcpy(nf->fieldName, (*j)->fieldName); ed->ismap.push_front(nf); } } // Distribute eventOuts. Each eventOut ROUTE is added // directly to the local nodes that have IS'd the PROTO // eventOut. VrmlNodeType::FieldList &eventOuts = d_nodeType->eventOuts(); for (Route *r = d_routes; r; r = r->next()) for (ev = eventOuts.begin(); ev != eventOuts.end(); ++ev) if (strcmp((*ev)->name, r->fromEventOut()) == 0) { ismap = &(*ev)->thisIS; for (j = ismap->begin(); j != ismap->end(); ++j) { VrmlNode *n = d_scope->findNode((*j)->node->name()); if (n) n->addRoute((*j)->fieldName, r->toNode(), r->toEventIn()); } } // Set IS'd field values in the implementation nodes to // the values specified in the instantiation. list<NameValueRec *>::iterator ifld; for (ifld = d_fields.begin(); ifld != d_fields.end(); ++ifld) { VrmlField *value = (*ifld)->value; #ifdef DEBUG cerr << d_nodeType->getName() << "::" << name() << " setting IS field " << (*ifld)->name; if (value) cerr << " to " << *value << endl; else cerr << " to null\n"; #endif if (!value) continue; if ((ismap = d_nodeType->getFieldISMap((*ifld)->name)) != 0) { for (j = ismap->begin(); j != ismap->end(); ++j) { // cerr << (*j)->node->name() << endl; VrmlNode *n = d_scope->findNode((*j)->node->name()); #ifdef DEBUG cerr << " on " << n->name() << "::" << (*j)->fieldName << endl; #endif if (n) n->setField((*j)->fieldName, *value); } } } } d_instantiated = true; }