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; }
// // The update method is where the events are processed. It should be // called after each frame is rendered. // bool VrmlScene::update( double timeStamp ) { if (timeStamp <= 0.0) timeStamp = theSystem->time(); VrmlSFTime now( timeStamp ); d_deltaTime = DEFAULT_DELTA; // Update each of the timers. VrmlNodeList::iterator i, end = d_timers->end(); for (i = d_timers->begin(); i != end; ++i) { VrmlNodeTimeSensor *t = (*i)->toTimeSensor(); if (t) t->update( now ); } // Update each of the clips. end = d_audioClips->end(); for (i = d_audioClips->begin(); i != end; ++i) { VrmlNodeAudioClip *c = (*i)->toAudioClip(); if (c) c->update( now ); } // Update each of the scripts. end = d_scripts->end(); for (i = d_scripts->begin(); i != end; ++i) { VrmlNodeScript *s = (*i)->toScript(); if (s) s->update( now ); } // Update each of the movies. end = d_movies->end(); for (i = d_movies->begin(); i != end; ++i) { VrmlNodeMovieTexture *m = (*i)->toMovieTexture(); if (m) m->update( now ); } // Pass along events to their destinations while (d_firstEvent != d_lastEvent && ! d_pendingUrl && ! d_pendingNodes) { Event *e = &d_eventMem[d_firstEvent]; d_firstEvent = (d_firstEvent+1) % MAXEVENTS; // Ensure that the node is in the scene graph VrmlNode *n = e->toNode; if (this != n->scene()) { theSystem->debug("VrmlScene::update: %s::%s is not in the scene graph yet.\n", n->nodeType()->getName(), n->name()); n->addToScene((VrmlScene*)this, urlDoc()->url() ); } n->eventIn(e->timeStamp, e->toEventIn, e->value); // this needs to change if event values are shared... delete e->value; } if (d_pendingNodes) { replaceWorld( *d_pendingNodes, d_pendingScope ); delete d_pendingNodes; d_pendingNodes = 0; d_pendingScope = 0; } else if (d_pendingUrl) { (void) loadUrl( d_pendingUrl, d_pendingParameters ); delete d_pendingUrl; delete d_pendingParameters; d_pendingUrl = 0; d_pendingParameters = 0; } // Signal a redisplay if necessary return isModified(); }