Esempio 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;
}