Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
//
// 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();
}