1 /*
2  * Proto.cpp
3  *
4  * Copyright (C) 1999 Stephen F. White, 2005 J. "MUFTI" Scheurich
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program (see the file "COPYING" for details); if
18  * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19  * Cambridge, MA 02139, USA.
20  */
21 
22 #include <stdio.h>
23 #include "stdafx.h"
24 #include <ctype.h>
25 
26 #ifndef _WIN32
27 # include <unistd.h>
28 # include <fcntl.h>
29 #endif
30 
31 #include "resource.h"
32 #include "Proto.h"
33 #include "Scene.h"
34 #include "EventIn.h"
35 #include "EventOut.h"
36 #include "Field.h"
37 #include "FieldValue.h"
38 #include "ExposedField.h"
39 #include "DynamicFieldsNode.h"
40 #include "NodeTransform.h"
41 #include "NodeGroup.h"
42 #include "NodeScript.h"
43 
44 // code for a resuable constructor
protoInitializer(Scene * scene,const MyString & name)45 void Proto::protoInitializer(Scene *scene, const MyString &name)
46 {
47     metadata.set(
48           addExposedField(SFNODE, "metadata", new SFNode(NULL), METADATA_NODE));
49     setFieldFlags(metadata, FF_X3D_ONLY | FF_HIDDEN);
50 
51     m_scene = scene;
52     m_name = name;
53     m_protoNodes.resize(0);
54     m_eventIns.resize(0);
55     m_eventOuts.resize(0);
56     m_fields.resize(0);
57     m_exposedFields.resize(0);
58     m_urls = NULL;
59     m_isInternUrl = false;
60     m_loaded = false;
61     m_loading = false;
62     m_defined = false;
63     m_dynamicProto = false;
64     m_fromProtoLibrary = false;
65     m_inUse = false;
66     m_writeCDeclarationWritten = false;
67     m_isInScene = false;
68     m_showFieldsInit = false;
69     m_numbers4KidsInit = false;
70     m_unitLength = 1;
71     m_unitAngle = 1;
72     m_hasTimeSensor = false;
73     buildExportNames();
74     finishEvents();
75 }
76 
Proto(Scene * scene,const MyString & name)77 Proto::Proto(Scene *scene, const MyString &name)
78 {
79     protoInitializer(scene, name);
80     finishEvents();
81 }
82 
83 
searchTimeSensor(Node * node,void * data)84 static bool searchTimeSensor(Node *node, void *data)
85 {
86     bool *found = (bool *)data;
87     if (node->getType() == VRML_TIME_SENSOR)
88         *found = true;
89     return true;
90 }
91 
Proto(Scene * scene,Proto * proto,int extensionFlag)92 Proto::Proto(Scene *scene, Proto *proto, int extensionFlag)
93 {
94     bool x3d = false;
95     int flag = 0;
96     const char *extensionName = "";
97     if (extensionFlag & FF_X3D_ONLY) {
98         extensionName = "X3d";
99         flag = FF_X3D_ONLY;
100         x3d = true;
101     } else if (extensionFlag & FF_COVER_ONLY) {
102         extensionName = "Cover";
103         flag = FF_COVER_ONLY;
104     } else if (extensionFlag & FF_KAMBI_ONLY) {
105         extensionName = "Kambi";
106         flag = FF_KAMBI_ONLY;
107     }
108     int len = 128;
109     len += strlen(extensionName) + strlen(proto->getName(x3d));
110     char *protoName = new char[len + 1];
111     int count = 1;
112     // search new PROTO name
113     do {
114         mysnprintf(protoName, len, "%s%s%d", extensionName,
115                    (const char *)proto->getName(x3d), count++);
116     } while (scene->getProto(protoName) != NULL);
117     protoInitializer(scene, protoName);
118     m_loaded = proto->isLoaded();
119     m_protoNodes[0] = proto->create(scene);
120     m_protoNodes[0]->setOutsideProto(this);
121     for (int i = 0; i < m_protoNodes[0]->getProto()->getNumEventIns(); i++) {
122         EventIn *eventIn = m_protoNodes[0]->getProto()->getEventIn(i);
123         if (eventIn->getExposedField() == NULL) {
124             const MyString name = eventIn->getName(x3d);
125             if (avoidElement(eventIn, flag))
126                 continue;
127             addEventIn(eventIn->getType(), name);
128             if (!(eventIn->getFlags() & flag)) {
129                 int dstEventIn = proto->lookupEventIn(name, x3d);
130                 EventIn *isEvent = m_protoNodes[0]->getProto()->getEventIn(i);
131                 isEvent->addIs(m_protoNodes[0], i, EL_EVENT_IN,
132                                this, dstEventIn, EOF_IS);
133             }
134         }
135     }
136     for (int i = 0; i < m_protoNodes[0]->getProto()->getNumEventOuts(); i++) {
137          EventOut *eventOut = m_protoNodes[0]->getProto()->getEventOut(i);
138          if (eventOut->getExposedField() == NULL) {
139              const MyString name = eventOut->getName(x3d);
140              if (avoidElement(eventOut, flag))
141                  continue;
142              addEventOut(eventOut->getType(), name);
143              if (!(eventOut->getFlags() & flag)) {
144                  int dstEventOut = proto->lookupEventOut(name, x3d);
145                  EventOut *isEvent = m_protoNodes[0]->getProto()->getEventOut(i);
146                  isEvent->addIs(m_protoNodes[0], i, EL_EVENT_OUT,
147                                 this, dstEventOut, EIF_IS);
148              }
149          }
150     }
151     for (int i = 0; i < m_protoNodes[0]->getProto()->getNumFields(); i++) {
152          Field *field = m_protoNodes[0]->getProto()->getField(i);
153          const MyString name = field->getName(x3d);
154          if (avoidElement(field, flag))
155              continue;
156          if (field->getExposedField())
157              addExposedField(field->getType(), name, field->getDefault(x3d));
158          else
159              addField(field->getType(), name, field->getDefault(x3d));
160          if (!(field->getFlags() & flag)) {
161               int dstField = proto->lookupField(name, x3d);
162               Field *isField = m_protoNodes[0]->getProto()->getField(i);
163               isField->addIs(m_protoNodes[0], i, field->getType(),
164                              this, dstField);
165          }
166     }
167     for (int i = 0; i < m_protoNodes.size(); i++) {
168         bool hasTimeSensor = false;
169         m_protoNodes[i]->doWithBranch(searchTimeSensor, &hasTimeSensor, false);
170         if (hasTimeSensor)
171             m_hasTimeSensor;
172     }
173 }
174 
~Proto()175 Proto::~Proto()
176 {
177 /*
178     for (long i = 0; i < m_eventIns.size(); i++)
179         delete m_eventIns[i];
180     for (long i = 0; i < m_eventOuts.size(); i++)
181         delete m_eventOuts[i];
182     for (long i = 0; i < m_exposedFields.size(); i++)
183         delete m_exposedFields[i];
184     for (long i = 0; i < m_fields.size(); i++)
185         delete m_fields[i];
186 */
187     for (long i = 0; i < m_protoNodes.size(); i++)
188         if (m_protoNodes[i])
189             m_protoNodes[i]->unref();
190 }
191 
192 void
finishEvents(void)193 Proto::finishEvents(void)
194 {
195     m_eventIns.setNoResize();
196     m_eventOuts.setNoResize();
197     if (!isDynamicFieldsProto())
198         m_fields.setNoResize();
199 
200 }
201 
avoidElement(Element * element,bool x3d)202 bool Proto::avoidElement(Element *element, bool x3d)
203 {
204     return avoidElement(element, x3d ? FF_VRML_ONLY : FF_X3D_ONLY);
205 }
206 
avoidElement(Element * element,int flag)207 bool Proto::avoidElement(Element *element, int flag)
208 {
209     if (element->getFlags() & FF_ALWAYS)
210         return true;
211     if (element->getFlags() & FF_NEVER)
212         return false;
213     if (flag == FF_X3D_ONLY)
214         if (element->getFlags() & FF_COVER_ONLY)
215             return true;
216     if (flag == FF_X3D_ONLY)
217         if (element->getFlags() & FF_KAMBI_ONLY)
218             return true;
219     if (flag == FF_X3D_ONLY)
220         if (element->getFlags() & FF_VRML_ONLY)
221             return true;
222     if (flag == FF_COVER_ONLY)
223         if (element->getFlags() & FF_X3D_ONLY)
224             return true;
225     if (flag == FF_COVER_ONLY)
226         if (element->getFlags() & FF_KAMBI_ONLY)
227             return true;
228     if (flag == FF_KAMBI_ONLY)
229         if (element->getFlags() & FF_X3D_ONLY)
230             return true;
231     if (flag == FF_X3DOM_ONLY)
232         return true;
233     return false;
234 }
235 
236 Node *
create(Scene * scene)237 Proto::create(Scene *scene)
238 {
239     return new NodePROTO(scene, this);
240 }
241 
242 MyString
buildCallbackClass(const char * name)243 Proto::buildCallbackClass(const char *name)
244 {
245     MyString callbackClass = "";
246     callbackClass += TheApp->getCPrefix();
247     callbackClass += getCName(true);
248     callbackClass += name;
249     callbackClass += "Callback";
250     return callbackClass;
251 }
252 
253 MyString
buildCallbackName(const char * name)254 Proto::buildCallbackName(const char *name)
255 {
256     MyString callbackName = "";
257     callbackName += name;
258     callbackName += "Callback";
259     callbackName += getCName(true);
260     return callbackName;
261 }
262 
263 // a dynamic node needs a extra name (DEF name) otherwise it would be ambiguous
264 void
buildExportNames(const char * nodeName)265 Proto::buildExportNames(const char *nodeName)
266 {
267     m_cName = "";
268     if (isalpha(m_name[0]))
269         m_cName += m_name[0];
270     else
271         m_cName += "A";
272     for (int i = 1; i < m_name.length(); i++)
273         if (isalnum(m_name[i]))
274             m_cName += m_name[i];
275         else
276             m_cName += "_";
277     if (nodeName != NULL) {
278         m_cName += "_";
279         m_cName += nodeName;
280      }
281 
282     m_className = "";
283     m_className += TheApp->getCPrefix();
284     m_className += getCName(true);
285 
286     m_renderCallbackClass = buildCallbackClass("Render");
287     m_renderCallbackName = buildCallbackName("render");
288 
289     m_treeRenderCallbackClass = buildCallbackClass("TreeRender");
290     m_treeRenderCallbackName = buildCallbackName("treeRender");
291 
292     m_createNormalsCallbackClass = buildCallbackClass("CreateNormals");
293     m_createNormalsCallbackName = buildCallbackName("createNormals");
294 
295     m_doWithDataCallbackClass = buildCallbackClass("DoWithData");
296     m_doWithDataCallbackName = buildCallbackName("doWithData");
297 
298     m_treeDoWithDataCallbackClass = buildCallbackClass("TreeDoWithData");
299     m_treeDoWithDataCallbackName = buildCallbackName("treeDoWithData");
300 
301     m_processEventCallbackClass = buildCallbackClass("ProcessEvent");
302     m_processEventCallbackName = buildCallbackName("processEvent");
303 }
304 
305 void
removeFromIs(Node * node)306 Proto::removeFromIs(Node *node)
307 {
308     for (long i = 0; i < m_fields.size(); i++)
309         for (int j = 0; j < m_fields[i]->getNumIs(); j++)
310             if (m_fields[i]->getIsNode(j)->hasAncestor(node))
311                 m_fields[i]->removeIs(j);
312     for (long i = 0; i < m_eventIns.size(); i++)
313         for (int j = 0; j < m_eventIns[i]->getNumIs(); j++)
314             if (m_eventIns[i]->getIsNode(j)->hasAncestor(node))
315                 m_eventIns[i]->removeIs(j);;
316     for (long i = 0; i < m_eventOuts.size(); i++)
317         for (int j = 0; j < m_eventOuts[i]->getNumIs(); j++)
318             if (m_eventOuts[i]->getIsNode(j)->hasAncestor(node))
319                 m_eventOuts[i]->removeIs(j);
320     for (long i = 0; i < m_exposedFields.size(); i++)
321         for (int j = 0; j < m_exposedFields[i]->getNumIs(); j++)
322             if (m_exposedFields[i]->getIsNode(j)->hasAncestor(node))
323                 m_exposedFields[i]->removeIs(j);
324 }
325 
326 void
deleteElements(void)327 Proto::deleteElements(void)
328 {
329     for (long i = 0; i < m_fields.size(); i++)
330         if (m_fields[i] && m_fields[i]->getDefault(false)->isDefaultValue())
331             m_nameOfFieldsWithDefaultValue.append(m_fields[i]->getName(false));
332     int restSize = 1;
333     m_fields.resize(restSize);
334     m_eventIns.resize(restSize);
335     m_eventOuts.resize(restSize);
336     m_exposedFields.resize(restSize);
337 }
338 
339 int
addOrUpdateElement(Element * element)340 Proto::addOrUpdateElement(Element *element)
341 {
342     switch( element->getElementType() ) {
343       case EL_FIELD:
344         for (long i = 0; i < m_fields.size(); i++)
345             if (m_fields[i]->getName(false) == element->getName(false)) {
346                 m_fields[i] = (Field *)element;
347                 return i;
348             }
349         break;
350       case EL_EVENT_IN:
351         for (long i = 0; i < m_eventIns.size(); i++)
352             if (m_eventIns[i]->getName(false) == element->getName(false)) {
353                 m_eventIns[i] = (EventIn *)element;
354                 return i;
355             }
356         break;
357       case EL_EVENT_OUT:
358         for (long i = 0; i < m_eventOuts.size(); i++)
359             if (m_eventOuts[i]->getName(false) == element->getName(false)) {
360                 m_eventOuts[i] = (EventOut *)element;
361                 return i;
362             }
363         break;
364       case EL_EXPOSED_FIELD:
365         for (long i = 0; i < m_exposedFields.size(); i++)
366             if (m_exposedFields[i]->getName(false) == element->getName(false)) {
367                 m_exposedFields[i] = (ExposedField *)element;
368                 return i;
369             }
370         break;
371       default:
372         m_scene->errorf("internal error:  unexpected element in Proto");
373         break;
374     }
375     return addElement(element);
376 }
377 
378 int
addElement(Element * element)379 Proto::addElement(Element *element)
380 {
381     bool x3d = m_scene->isX3d();
382     switch( element->getElementType() ) {
383       case EL_FIELD:
384         {
385         Field *field = (Field *) element;
386         if (field->getDefault(false) == NULL) {
387             swDebugf("ignoring element %s\n", (const char*)field->getName(false));
388             return -1;
389         }
390         for (long i = 0; i < m_nameOfFieldsWithDefaultValue.size(); i++)
391             if (field->getName(false) == m_nameOfFieldsWithDefaultValue[i])
392                 field->getDefault(x3d)->setIsDefaultValue();
393         m_fields.append(field);
394         }
395         return m_fields.size() - 1;
396       case EL_EVENT_IN:
397         m_eventIns.append((EventIn *) element);
398         break;
399       case EL_EVENT_OUT:
400         m_eventOuts.append((EventOut *) element);
401         break;
402       case EL_EXPOSED_FIELD:
403         return addExposedField((ExposedField *) element);
404       default:
405         m_scene->errorf("internal error:  unexpected element in Proto");
406         break;
407     }
408     return -1;
409 }
410 
411 int
addField(int fieldType,const MyString & name,FieldValue * defaultValue,FieldValue * min,FieldValue * max)412 Proto::addField(int fieldType, const MyString &name, FieldValue *defaultValue,
413                 FieldValue *min, FieldValue *max)
414 {
415     FieldValue *value = defaultValue;
416     if (value == NULL)
417         value = typeDefaultValue(fieldType);
418     m_fields.append(new Field(fieldType, name, value, NULL, min, max,
419                               ANY_NODE));
420     return m_fields.size() - 1;
421 }
422 
423 int
addField(int fieldType,const MyString & name,FieldValue * defaultValue,int nodeType)424 Proto::addField(int fieldType, const MyString &name, FieldValue *defaultValue,
425                 int nodeType)
426 {
427     m_fields.append(new Field(fieldType, name, defaultValue, NULL,
428                              NULL, NULL, nodeType));
429     return m_fields.size() - 1;
430 }
431 
432 int
addField(int fieldType,const MyString & name,FieldValue * defaultValue,int flags,const char ** strings)433 Proto::addField(int fieldType, const MyString &name, FieldValue *defaultValue,
434                 int flags, const char **strings)
435 {
436     m_fields.append(new Field(fieldType, name, defaultValue, NULL,
437                              NULL, NULL, ANY_NODE, flags, strings));
438     return m_fields.size() - 1;
439 }
440 
441 
442 int
addField(Field * field)443 Proto::addField(Field *field)
444 {
445     m_fields.append(field);
446     return m_fields.size() - 1;
447 }
448 
449 int
addEventIn(int fieldType,const MyString & name)450 Proto::addEventIn(int fieldType, const MyString &name)
451 {
452     m_eventIns.append(new EventIn(fieldType, name));
453     return m_eventIns.size() - 1;
454 }
455 
456 int
addEventIn(int fieldType,const MyString & name,int flags)457 Proto::addEventIn(int fieldType, const MyString &name, int flags)
458 {
459     m_eventIns.append(new EventIn(fieldType, name, flags));
460     return m_eventIns.size() - 1;
461 }
462 
463 int
addEventIn(int fieldType,const MyString & name,int flags,int field)464 Proto::addEventIn(int fieldType, const MyString &name, int flags, int field)
465 {
466     m_eventIns.append(new EventIn(fieldType, name, flags));
467     m_eventIns[m_eventIns.size() - 1]->setField(field);
468     m_fields[field]->setEventIn(m_eventIns.size() - 1);
469     return m_eventIns.size() - 1;
470 }
471 
472 int
addEventOut(int fieldType,const MyString & name)473 Proto::addEventOut(int fieldType, const MyString &name)
474 {
475     m_eventOuts.append(new EventOut(fieldType, name));
476     return m_eventOuts.size() - 1;
477 }
478 
479 int
addEventOut(int fieldType,const MyString & name,int flags)480 Proto::addEventOut(int fieldType, const MyString &name, int flags)
481 {
482     m_eventOuts.append(new EventOut(fieldType, name, flags));
483     return m_eventOuts.size() - 1;
484 }
485 
486 int
addExposedField(int fieldType,const MyString & name,FieldValue * defaultValue,FieldValue * min,FieldValue * max,const MyString & x3dName)487 Proto::addExposedField(int fieldType, const MyString &name,
488                        FieldValue *defaultValue,
489                        FieldValue *min, FieldValue *max,
490                        const MyString &x3dName)
491 {
492     FieldValue *value = defaultValue;
493     if (value == NULL)
494         value = typeDefaultValue(fieldType);
495     return addExposedField(new ExposedField(fieldType, name, value,
496                                             min, max, ANY_NODE, 0,
497                                             NULL, x3dName));
498 }
499 
500 int
addExposedField(int fieldType,const MyString & name,FieldValue * defaultValue,int nodeType,const MyString & x3dName)501 Proto::addExposedField(int fieldType, const MyString &name,
502                        FieldValue *defaultValue, int nodeType,
503                        const MyString &x3dName)
504 {
505     return addExposedField(new ExposedField(fieldType, name,
506                                             defaultValue, NULL, NULL,
507                                             nodeType, 0, NULL, x3dName));
508 }
509 
510 int
addExposedField(int fieldType,const MyString & name,FieldValue * defaultValue,int flags,const char ** strings)511 Proto::addExposedField(int fieldType, const MyString &name,
512                        FieldValue *defaultValue, int flags,
513                        const char **strings)
514 {
515     return addExposedField(new ExposedField(fieldType, name,
516                                             defaultValue, NULL, NULL,
517                                             0, flags, strings));
518 }
519 
520 int
addExposedField(int fieldType,const MyString & name,FieldValue * defaultValue,FieldValue * min,FieldValue * max,int nodeType,int flags,const char ** strings,const MyString & x3dName)521 Proto::addExposedField(int fieldType, const MyString &name,
522                            FieldValue *defaultValue,
523                            FieldValue *min, FieldValue *max,
524                            int nodeType, int flags, const char **strings,
525                            const MyString &x3dName)
526 {
527     return addExposedField(new ExposedField(fieldType, name,
528                                             defaultValue, min, max,
529                                             nodeType, flags, strings, x3dName));
530 }
531 
532 int
addExposedField(ExposedField * exposedField)533 Proto::addExposedField(ExposedField *exposedField)
534 {
535     const MyString &name = exposedField->getName(false);
536     const MyString &x3dName = exposedField->getName(true);
537     int type = exposedField->getType();
538     FieldValue *value = exposedField->getValue();
539     FieldValue *min = exposedField->getMin();
540     FieldValue *max = exposedField->getMax();
541     int flags = exposedField->getFlags();
542     int nodeType = exposedField->getNodeType();
543     const char **strings = exposedField->getStrings();
544 
545     m_exposedFields.append(exposedField);
546 
547     // now add a hidden Field with the same name
548     m_fields.append(new Field(type, name, value, exposedField, min, max,
549                               nodeType, FF_HIDDEN | flags, strings, x3dName));
550 
551     exposedField->setFieldIndex(m_fields.size() - 1);
552     exposedField->setField(m_fields[m_fields.size() - 1]);
553 
554     // now add a hidden EventIn called set_<name>
555     char buf[1024];
556     mysnprintf(buf, 1024, "set_%s", (const char *) name);
557     m_eventIns.append(new EventIn(type, buf, flags, exposedField));
558 
559     exposedField->setEventIn(m_eventIns.size() - 1);
560     m_eventOuts.append(new EventOut(type, name, flags, exposedField));
561 
562     exposedField->setEventOut(m_eventOuts.size() - 1);
563 
564     return m_fields.size() - 1;
565 }
566 
567 void
deleteField(int index)568 Proto::deleteField(int index)
569 {
570     m_fields.remove(index);
571 }
572 
573 void
deleteEventIn(int index)574 Proto::deleteEventIn(int index)
575 {
576     m_eventIns.remove(index);
577 }
578 
579 void
deleteEventOut(int index)580 Proto::deleteEventOut(int index)
581 {
582     m_eventOuts.remove(index);
583 }
584 
585 void
deleteExposedField(int index)586 Proto::deleteExposedField(int index)
587 {
588     ExposedField *exposedField = m_exposedFields[index];
589     for (int i = 0; i < getNumFields(); i++)
590         if (m_fields[i]->getExposedField() == exposedField)
591             m_fields.remove(i);
592     for (int i = 0; i < getNumEventIns(); i++)
593         if (m_eventIns[i]->getExposedField() == exposedField)
594             m_eventIns.remove(i);
595     for (int i = 0; i < getNumEventOuts(); i++)
596         if (m_eventOuts[i]->getExposedField() == exposedField)
597             m_eventOuts.remove(i);
598     m_exposedFields.remove(index);
599 }
600 
601 int
getExposedOfField(Field * field)602 Proto::getExposedOfField(Field *field)
603 {
604     const char *name = field->getName(m_scene->isX3d());
605     int sField = -1;
606     for (int i = 0; i < getNumExposedFields(); i++) {
607         sField++;
608         if (strcmp(name, getExposedField(i)->getName(m_scene->isX3d())) == 0)
609             return sField;
610     }
611     return -1;
612 }
613 
614 int
getFieldOfExposed(ExposedField * field)615 Proto::getFieldOfExposed(ExposedField *field)
616 {
617     const char *name = field->getName(m_scene->isX3d());
618     int sField = -1;
619     for (int i = 0; i < getNumFields(); i++) {
620         sField++;
621         if (strcmp(name, getField(i)->getName(m_scene->isX3d())) == 0)
622             return sField;
623     }
624     return -1;
625 }
626 
627 int
lookupSimpleEventIn(const MyString & name,bool x3d) const628 Proto::lookupSimpleEventIn(const MyString &name, bool x3d) const
629 {
630     for (long i = 0; i < m_eventIns.size(); i++)
631         if (m_eventIns[i]->getName(x3d) == name) return i;
632     if (m_protoNodes.size() > 0)
633         return m_protoNodes[0]->getProto()->lookupSimpleEventIn(name, x3d);
634     return INVALID_INDEX;
635 }
636 
637 int
lookupEventIn(const MyString & name,bool x3d) const638 Proto::lookupEventIn(const MyString &name, bool x3d) const
639 {
640     int index;
641 
642     if ((index = lookupSimpleEventIn(name, x3d)) == INVALID_INDEX)
643     {
644         // simple search failed; look for an exposed Field
645         if ((index = lookupExposedField(name, x3d)) != INVALID_INDEX) {
646             // now look up the corresponding eventIn
647             char buf[1024];
648             mysnprintf(buf, 1024, "set_%s", (const char *) name);
649             index = lookupSimpleEventIn(buf, x3d);
650         }
651     }
652     return index;
653 }
654 
655 int
lookupSimpleEventOut(const MyString & name,bool x3d) const656 Proto::lookupSimpleEventOut(const MyString &name, bool x3d) const
657 {
658     for (long i = 0; i < m_eventOuts.size(); i++)
659         if (m_eventOuts[i]->getName(x3d) == name)
660             return i;
661     if (m_protoNodes.size() > 0)
662         return m_protoNodes[0]->getProto()->lookupSimpleEventOut(name, x3d);
663     return INVALID_INDEX;
664 }
665 
666 int
lookupEventOut(const MyString & name,bool x3d) const667 Proto::lookupEventOut(const MyString &name, bool x3d) const
668 {
669     int index;
670 
671     if ((index = lookupSimpleEventOut(name, x3d)) == INVALID_INDEX)
672     {
673         // simple search failed; look for an exposedField
674         if ((index = lookupExposedField(name, x3d)) != INVALID_INDEX) {
675 
676             // now look up the corresponding eventOut
677             char buf[1024];
678             mysnprintf(buf, 1024, "%s_changed", (const char *) name);
679             index = lookupSimpleEventOut(buf, x3d);
680         }
681     }
682     return index;
683 }
684 
685 int
lookupField(const MyString & name,bool x3d) const686 Proto::lookupField(const MyString &name, bool x3d) const
687 {
688     for (long i = 0; i < m_fields.size(); i++)
689         if (m_fields[i]->getName(x3d) == name)
690             return i;
691     if (m_protoNodes.size() > 0)
692         m_protoNodes[0]->getProto()->lookupField(name, x3d);
693     return INVALID_INDEX;
694 }
695 
696 int
lookupExposedField(const MyString & name,bool x3d) const697 Proto::lookupExposedField(const MyString &name, bool x3d) const
698 {
699     for (long i = 0; i < m_exposedFields.size(); i++) {
700         if (m_exposedFields[i]->getName(x3d) == name)
701             return i;
702     }
703 
704     return INVALID_INDEX;
705 }
706 
707 bool
canWriteElement(Element * element,bool x3d) const708 Proto::canWriteElement(Element *element, bool x3d) const
709 {
710     if (element && element->getFlags() & FF_ALWAYS)
711         return true;
712     if (element && element->getFlags() & FF_NEVER)
713         return false;
714     if (element && x3d) {
715         if (element->getFlags() & FF_COVER_ONLY)
716             return false;
717         if (element->getFlags() & FF_KAMBI_ONLY)
718             return false;
719         if (element->getFlags() & FF_VRML_ONLY)
720             return false;
721     } else
722         if (element && element->getFlags() & FF_X3D_ONLY)
723             return false;
724     return true;
725 }
726 
727 int
writeEvents(int f,int indent,int flags) const728 Proto::writeEvents(int f, int indent, int flags) const
729 {
730     int indent2 = indent;
731     if (isX3dXml(flags))
732         indent2 = indent + TheApp->GetIndent();
733     for (long i = 0; i < m_fields.size(); i++)
734         if (m_fields[i] && canWriteElement(m_fields[i], isX3d(flags)))
735             RET_ONERROR( m_fields[i]->write(f, indent2, flags) )
736     for (long i = 0; i < m_eventIns.size(); i++)
737         if (m_eventIns[i] && canWriteElement(m_eventIns[i], isX3d(flags)))
738             RET_ONERROR(m_eventIns[i]->write(f, indent2, flags) )
739     for (long i = 0; i < m_eventOuts.size(); i++)
740         if (m_eventOuts[i] && canWriteElement(m_eventOuts[i], isX3d(flags)))
741             RET_ONERROR(m_eventOuts[i]->write(f, indent2, flags) )
742     for (long i = 0; i < m_exposedFields.size(); i++)
743         if (m_exposedFields[i] &&
744             canWriteElement(m_exposedFields[i], isX3d(flags)))
745                 RET_ONERROR(m_exposedFields[i]->write(f, indent2, flags) )
746     return(0);
747 }
748 
setIsProtoToBranch(Node * node,void * data)749 static bool setIsProtoToBranch(Node *node, void *data)
750 {
751     Proto *proto = (Proto *)data;
752     node->ref();
753     node->setOutsideProto(proto);
754     return true;
755 }
756 
757 
758 void
define(Node * primaryNode,NodeList * nodes)759 Proto::define(Node *primaryNode, NodeList *nodes)
760 {
761     if (primaryNode == NULL)
762         return;
763     int numProtos = 0;
764     int ichild = primaryNode->getChildrenField();
765     if (ichild > -1) {
766         m_protoNodes[0] = primaryNode;
767     } else if (primaryNode->getType() == VRML_GROUP) {
768         MFNode *children = ((NodeGroup *)primaryNode)->children();
769         for (long i = 0; i < children->getSize(); i++) {
770             m_protoNodes[i] = children->getValue(i);
771             if (m_protoNodes[i] != NULL)
772                 m_protoNodes[i]->doWithBranch(setIsProtoToBranch, this);
773         }
774     } else {
775         m_protoNodes[0] = primaryNode;
776         numProtos++;
777         if (m_protoNodes[0] != NULL)
778             m_protoNodes[0]->doWithBranch(setIsProtoToBranch, this);
779     }
780     for (long i = numProtos; i < numProtos + nodes->size(); i++) {
781         m_protoNodes[i] = nodes->get(i - numProtos);
782         if (m_protoNodes[i] != NULL)
783             m_protoNodes[i]->doWithBranch(setIsProtoToBranch, this);
784     }
785     setIsNodeIndex();
786 }
787 
write(int f,int indent,int flags) const788 int Proto::write(int f, int indent, int flags) const
789 {
790     int indent2 = indent + TheApp->GetIndent();
791     int indent3 = indent2 + TheApp->GetIndent();
792     int indent4 = indent3 + TheApp->GetIndent();
793 
794     bool x3d = isX3d(flags);
795     bool externProto = (m_urls != NULL);
796     const char *appinfo = getAppinfo();
797     const char *documentation = getDocumentation();
798     if (isX3dXml(flags)) {
799         RET_ONERROR( indentf(f, indent2) )
800         RET_ONERROR( mywritestr(f, "<") )
801         if (externProto)
802             RET_ONERROR( mywritestr(f, "Extern") )
803         RET_ONERROR( mywritestr(f, "ProtoDeclare name='") )
804         RET_ONERROR( mywritestr(f, getName(x3d)) )
805         RET_ONERROR( mywritestr(f, "' ") )
806         if (strlen(appinfo) > 0) {
807             RET_ONERROR( mywritestr(f, " appinfo='") )
808             RET_ONERROR( mywritestr(f, appinfo) )
809             RET_ONERROR( mywritestr(f, "'") )
810         }
811         if (strlen(documentation) > 0) {
812             RET_ONERROR( mywritestr(f, " documentation='") )
813             RET_ONERROR( mywritestr(f, documentation) )
814             RET_ONERROR( mywritestr(f, "'") )
815         }
816         if (externProto) {
817             RET_ONERROR( mywritestr(f, " url=") )
818             const char *oldBase = m_scene->getURL();
819             const char *newBase = m_scene->getNewURL();
820             FieldValue *urls = m_urls;
821             if (!TheApp->GetKeepURLs())
822                 urls = rewriteField(m_urls, oldBase, newBase, flags);
823             RET_ONERROR( urls->writeXml(f, indent3) )
824         }
825         RET_ONERROR( mywritestr(f, ">\n") )
826         TheApp->incSelectionLinenumber();
827 
828         RET_ONERROR( indentf(f, indent3) )
829         RET_ONERROR( mywritestr(f, "<ProtoInterface>\n") )
830         TheApp->incSelectionLinenumber();
831 
832         RET_ONERROR( writeEvents(f, indent2,
833                                  flags | (externProto ? WITHOUT_VALUE: 0)) )
834 
835         RET_ONERROR( indentf(f, indent3) )
836         RET_ONERROR( mywritestr(f, "</ProtoInterface>\n") )
837         TheApp->incSelectionLinenumber();
838 
839         if (!externProto) {
840 
841             RET_ONERROR( indentf(f, indent3) )
842             RET_ONERROR( mywritestr(f, "<ProtoBody>\n") )
843             TheApp->incSelectionLinenumber();
844 
845             for (long i = 0; i < m_protoNodes.size(); i++) {
846                 if (::isX3dXml(flags))
847                     RET_ONERROR( m_protoNodes.get(i)->writeXml(f, indent4) )
848                 else
849                     RET_ONERROR( m_protoNodes.get(i)->write(f, indent4) )
850             }
851             RET_ONERROR( mywritestr(f, "\n") )
852             for (long i = 0; i < m_protoNodes.size(); i++)
853                 RET_ONERROR( m_protoNodes.get(i)->writeRoutes(f, indent4) )
854             m_scene->writeRouteStrings(f, indent4, true);
855 
856             RET_ONERROR( indentf(f, indent3) )
857             RET_ONERROR( mywritestr(f, "</ProtoBody>\n") )
858             TheApp->incSelectionLinenumber();
859         }
860         RET_ONERROR( indentf(f, indent2) )
861         RET_ONERROR( mywritestr(f, "</") )
862         if (externProto)
863             RET_ONERROR( mywritestr(f, "Extern") )
864         RET_ONERROR( mywritestr(f, "ProtoDeclare>\n") )
865         RET_ONERROR( mywritestr(f, "\n") )
866         TheApp->incSelectionLinenumber();
867     } else {
868         if (strlen(appinfo) > 0) {
869             RET_ONERROR( mywritestr(f, "# ") )
870             RET_ONERROR( mywritestr(f, getName(x3d)) )
871             RET_ONERROR( mywritestr(f, " appinfo='") )
872             RET_ONERROR( mywritestr(f, appinfo) )
873             RET_ONERROR( mywritestr(f, "'") )
874             RET_ONERROR( mywritestr(f, "\n") )
875             TheApp->incSelectionLinenumber();
876         }
877         if (strlen(documentation) > 0) {
878             RET_ONERROR( mywritestr(f, "# ") )
879             RET_ONERROR( mywritestr(f, getName(x3d)) )
880             RET_ONERROR( mywritestr(f, " documentation='") )
881             RET_ONERROR( mywritestr(f, documentation) )
882             RET_ONERROR( mywritestr(f, "'") )
883             RET_ONERROR( mywritestr(f, "\n") )
884             TheApp->incSelectionLinenumber();
885         }
886         RET_ONERROR( indentf(f, indent) )
887         if (m_urls != NULL)
888             RET_ONERROR( mywritestr(f, "EXTERN") )
889         RET_ONERROR( mywritestr(f, "PROTO ") )
890         RET_ONERROR( mywritestr(f, getName(x3d)) )
891         if (!TheApp->GetkrFormating()) {
892             RET_ONERROR( mywritestr(f, "\n") )
893             TheApp->incSelectionLinenumber();
894             RET_ONERROR( indentf(f, indent2) )
895         } else
896             RET_ONERROR( mywritestr(f, " ") )
897         RET_ONERROR( mywritestr(f, "[\n") )
898         TheApp->incSelectionLinenumber();
899 
900         RET_ONERROR( writeEvents(f, indent2,
901                                  flags | (externProto ? WITHOUT_VALUE : 0)) )
902 
903         if (!TheApp->GetkrFormating()) {
904             TheApp->incSelectionLinenumber();
905             RET_ONERROR( indentf(f, indent2) )
906         } else
907             RET_ONERROR( indentf(f, indent) )
908 
909         RET_ONERROR( mywritestr(f, "]") )
910 
911         RET_ONERROR( indentf(f, indent) )
912         if (m_urls != NULL) {
913             const char *oldBase = m_scene->getURL();
914             const char *newBase = m_scene->getNewURL();
915             FieldValue *urls = m_urls;
916             if (!TheApp->GetKeepURLs())
917                 urls = rewriteField(m_urls, oldBase, newBase, flags);
918             if (((MFString *)urls)->getSize() == 1) {
919                 RET_ONERROR( mywritestr(f, "\n") )
920                 TheApp->incSelectionLinenumber();
921             }
922             RET_ONERROR( urls->write(f, 0) )
923         } else {
924             RET_ONERROR( mywritestr(f, "\n") )
925             TheApp->incSelectionLinenumber();
926             RET_ONERROR( mywritestr(f, "{\n") )
927             TheApp->incSelectionLinenumber();
928             if (TheApp->GetkrFormating())
929                 indent = indent + TheApp->GetIndent();
930 
931             for (long i = 0; i < m_protoNodes.size(); i++) {
932                 RET_ONERROR( indentf(f, indent) )
933                 RET_ONERROR( m_protoNodes.get(i)->write(f, indent) )
934             }
935             for (long i = 0; i < m_protoNodes.size(); i++)
936                 RET_ONERROR( m_protoNodes.get(i)->writeRoutes(f, indent) )
937             m_scene->writeRouteStrings(f, indent, true);
938 
939             if (TheApp->GetkrFormating())
940                 indent = indent - TheApp->GetIndent();
941             RET_ONERROR( indentf(f, indent) )
942             RET_ONERROR( mywritestr(f, "}\n") )
943             TheApp->incSelectionLinenumber();
944         }
945         RET_ONERROR( mywritestr(f, "\n") )
946         TheApp->incSelectionLinenumber();
947 
948     }
949     return(0);
950 }
951 
952 void
compareToIsNodes(Node * node)953 Proto::compareToIsNodes(Node *node)
954 {
955     for (long i = 0; i < m_fields.size(); i++)
956         if (m_fields[i])
957             for (int j = 0; j < m_fields[i]->getNumIs(); j++)
958                 if (m_fields[i]->getIsNode(j) == node)
959                     m_fields[i]->setIsNodeIndex(j, m_nodeIndex);
960     for (long i = 0; i < m_eventIns.size(); i++)
961         if (m_eventIns[i])
962             for (int j = 0; j < m_eventIns[i]->getNumIs(); j++)
963                 if (m_eventIns[i]->getIsNode(j) == node)
964                     m_eventIns[i]->setIsNodeIndex(j,m_nodeIndex);
965     for (long i = 0; i < m_eventOuts.size(); i++)
966         if (m_eventOuts[i])
967             for (int j = 0; j < m_eventOuts[i]->getNumIs(); j++)
968                 if (m_eventOuts[i]->getIsNode(j) == node)
969                     m_eventOuts[i]->setIsNodeIndex(j, m_nodeIndex);
970     for (long i = 0; i < m_exposedFields.size(); i++)
971         if (m_exposedFields[i])
972             for (int j = 0; j < m_exposedFields[i]->getNumIs(); j++)
973                 if (m_exposedFields[i]->getIsNode(j) == node)
974                     m_exposedFields[i]->setIsNodeIndex(j, m_nodeIndex);
975     m_nodeIndex++;
976 }
977 
setIsNodeIndexToBranch(Node * node,void * data)978 static bool setIsNodeIndexToBranch(Node *node, void *data)
979 {
980     ((Proto *)data)->compareToIsNodes(node);
981     return true;
982 }
983 
984 void
setIsNodeIndex(void)985 Proto::setIsNodeIndex(void)
986 {
987     m_nodeIndex = 0;
988     for (int i = 0; i < getNumNodes(); i++)
989         if (m_protoNodes[i] != NULL)
990             m_protoNodes[i]->doWithBranch(setIsNodeIndexToBranch, this);
991 }
992 
993 
994 int
lookupIsEventIn(const char * name,int elementType) const995 Proto::lookupIsEventIn(const char *name, int elementType) const
996 {
997     for (long i = 0; i < m_eventIns.size(); i++)
998         for (int j = 0; j < m_eventIns[i]->getNumIs(); j++)
999             if (strcmp(m_eventIns[i]->getName(true), name) == 0) {
1000                 if ((elementType != -1) &&
1001                     (m_eventIns[i]->getIsElementType(j) != elementType))
1002                     continue;
1003                 return i;
1004             }
1005     return -1;
1006 }
1007 
1008 
1009 int
lookupIsExposedField(const char * name,int elementType) const1010 Proto::lookupIsExposedField(const char *name, int elementType) const
1011 {
1012     bool x3d = m_scene->isX3d();
1013     for (long i = 0; i < m_exposedFields.size(); i++)
1014         for (int j = 0; j < m_exposedFields[i]->getNumIs(); j++) {
1015             if ((elementType != -1) &&
1016                 (m_exposedFields[i]->getIsElementType(j) != elementType))
1017                 continue;
1018             if (strcmp(m_exposedFields[i]->getName(x3d), name) == 0) {
1019                 return i;
1020             }
1021             if (strlen(name) > 4) {
1022                 char *setPart = strdup(name);
1023                 setPart[4] = 0;
1024                 bool flag = false;
1025                 if (strcmp(setPart, "set_") == 0)
1026                     flag = true;
1027                 free(setPart);
1028                 MyString compName(name + 4);
1029                 if (flag && m_exposedFields[i]->getName(x3d) == compName)
1030                     return i;
1031            }
1032         }
1033     return -1;
1034 }
1035 
1036 int
lookupIsField(Node * node,int field) const1037 Proto::lookupIsField(Node *node, int field) const
1038 {
1039     for (long i = 0; i < m_fields.size(); i++) {
1040         if (m_fields[i] == NULL)
1041             continue;
1042         for (int j = 0; j < m_fields[i]->getNumIs(); j++) {
1043             Node *isNode = m_fields[i]->getIsNode(j);
1044             if (isNode && isNode->isEqual(node))
1045                 if (isNode->translateField(m_fields[i]->getIsField(j)) ==
1046                     field)
1047                     return i;
1048         }
1049     }
1050     return -1;
1051 }
1052 
1053 int
lookupIsEventIn(Node * node,int eventIn,int elementType) const1054 Proto::lookupIsEventIn(Node *node, int eventIn, int elementType) const
1055 {
1056     for (long i = 0; i < m_eventIns.size(); i++) {
1057         if (m_eventIns[i] == NULL)
1058             continue;
1059         for (int j = 0; j < m_eventIns[i]->getNumIs(); j++)
1060             if (m_eventIns[i]->getIsNode(j) &&
1061                 m_eventIns[i]->getIsNode(j)->isEqual(node))
1062                 if (m_eventIns[i]->getIsField(j) == eventIn) {
1063                     if ((elementType != -1) &&
1064                         (m_eventIns[i]->getIsElementType(j) != elementType))
1065                         continue;
1066                     return i;
1067                 }
1068     }
1069     return -1;
1070 }
1071 
1072 int
lookupIsEventOut(Node * node,int eventOut,int elementType) const1073 Proto::lookupIsEventOut(Node *node, int eventOut, int elementType) const
1074 {
1075     for (long i = 0; i < m_eventOuts.size(); i++) {
1076         if (m_eventOuts[i] == NULL)
1077             continue;
1078         for (int j = 0; j < m_eventOuts[i]->getNumIs(); j++)
1079             if (m_eventOuts[i]->getIsNode(j) &&
1080                 m_eventOuts[i]->getIsNode(j)->isEqual(node)) {
1081                 if (m_eventOuts[i]->getIsField(j) == eventOut) {
1082                     if ((elementType != -1) &&
1083                         (m_eventOuts[i]->getIsElementType(j) != elementType))
1084                         continue;
1085                     return i;
1086                 }
1087             }
1088     }
1089     return -1;
1090 }
1091 
1092 
1093 int
lookupIsExposedField(Node * node,int exposedField) const1094 Proto::lookupIsExposedField(Node *node, int exposedField) const
1095 {
1096     for (long i = 0; i < m_exposedFields.size(); i++) {
1097         if (m_exposedFields[i] == NULL)
1098             continue;
1099         for (int j = 0; j < m_exposedFields[i]->getNumIs(); j++) {
1100             Node *isNode = m_exposedFields[i]->getIsNode(j);
1101             if (isNode->isEqual(node))
1102                 if (isNode->translateField(m_exposedFields[i]->getIsField(j)) ==
1103                     exposedField)
1104                     return i;
1105         }
1106     }
1107     return -1;
1108 }
1109 
1110 int
getNumIsMSNodes(void) const1111 Proto::getNumIsMSNodes(void) const
1112 {
1113     int ret = 0;
1114     for (long i = 0; i < m_fields.size(); i++) {
1115         if (m_fields[i] == NULL)
1116             continue;
1117         for (int j = 0; j < m_fields[i]->getNumIs(); j++)
1118             if ((m_fields[i]->getType() == MFNODE) ||
1119                 (m_fields[i]->getType() == SFNODE))
1120                 ret++;
1121     }
1122     for (long i = 0; i < m_exposedFields.size(); i++) {
1123         if (m_exposedFields[i] == NULL)
1124             continue;
1125         for (int j = 0; j < m_exposedFields[i]->getNumIs(); j++)
1126             if ((m_exposedFields[i]->getType() == MFNODE) ||
1127                 (m_exposedFields[i]->getType() == SFNODE))
1128                 ret++;
1129     }
1130     return ret;
1131 }
1132 
1133 Node *
getIsMSNode(int numNode) const1134 Proto::getIsMSNode(int numNode) const
1135 {
1136     int count = 0;
1137     for (long i = 0; i < m_fields.size(); i++) {
1138         if (m_fields[i] == NULL)
1139             continue;
1140         for (int j = 0; j < m_fields[i]->getNumIs(); j++) {
1141             if ((m_fields[i]->getType() == MFNODE) ||
1142                 (m_fields[i]->getType() == SFNODE)) {
1143                 if (numNode == count)
1144                     return m_fields[i]->getIsNode(j);
1145                 count++;
1146             }
1147         }
1148     }
1149     for (long i = 0; i < m_exposedFields.size(); i++) {
1150         if (m_exposedFields[i] == NULL)
1151             continue;
1152         for (int j = 0; j < m_exposedFields[i]->getNumIs(); j++) {
1153             if ((m_exposedFields[i]->getType() == MFNODE) ||
1154                 (m_exposedFields[i]->getType() == SFNODE)) {
1155                 if (numNode == count)
1156                     return m_exposedFields[i]->getIsNode(j);
1157                 count++;
1158             }
1159         }
1160     }
1161     return NULL;
1162 }
1163 
1164 int
getIsMSNodeField(int numNode) const1165 Proto::getIsMSNodeField(int numNode) const
1166 {
1167     int count = 0;
1168     for (long i = 0; i < m_fields.size(); i++) {
1169         if (m_fields[i] == NULL)
1170             continue;
1171         for (int j = 0; j < m_fields[i]->getNumIs(); j++) {
1172             if ((m_fields[i]->getType() == MFNODE) ||
1173                 (m_fields[i]->getType() == SFNODE)) {
1174                 if (numNode == count)
1175                     return m_fields[i]->getIsField(j);
1176                 count++;
1177             }
1178         }
1179     }
1180     for (long i = 0; i < m_exposedFields.size(); i++) {
1181         if (m_exposedFields[i] == NULL)
1182             continue;
1183         for (int j = 0; j < m_exposedFields[i]->getNumIs(); j++) {
1184             if ((m_exposedFields[i]->getType() == MFNODE) ||
1185                 (m_exposedFields[i]->getType() == SFNODE)) {
1186                 if (numNode == count)
1187                     return m_exposedFields[i]->getIsField(j);
1188                 count++;
1189             }
1190         }
1191     }
1192     return -1;
1193 }
1194 
1195 void
addURLs(FieldValue * urls)1196 Proto::addURLs(FieldValue *urls)
1197 {
1198     m_isInternUrl = false;
1199     m_urls = urls;
1200     m_defined = true;
1201 }
1202 
1203 void
addURLs(int urlSchema)1204 Proto::addURLs(int urlSchema)
1205 {
1206     m_isInternUrl = true;
1207     if (urlSchema == URL_NULL) {
1208         m_urls = NULL;
1209         return;
1210     }
1211     StringArray *urls = new StringArray();
1212     MyString url1 = "";
1213     url1 += m_name;
1214     url1 += "PROTO.wrl";
1215     urls->append(url1);
1216 
1217     m_defined = true;
1218 
1219     MyString url2 = "";
1220     switch(urlSchema) {
1221       case URL_VRML97_AMENDMENT1:
1222          url2 += "urn:web3d:vrml97:node:";
1223          url2 += m_name;
1224          break;
1225       case URL_X3D:
1226          url2 += "urn:web3d:x3d:node:";
1227          url2 += m_name;
1228          break;
1229       case URL_KAMBI:
1230         url2 += "urn:castle-engine.sourceforge.net:node:";
1231         url2 += m_name;
1232     }
1233     if (strlen(url2) > 0)
1234         urls->append(url2);
1235 
1236     MyString url3 = "";
1237     switch(urlSchema) {
1238       case URL_VRML97_AMENDMENT1:
1239 #ifdef HAVE_VRML97_AMENDMENT1_PROTO_URL
1240          url3 += HAVE_VRML97_AMENDMENT1_PROTO_URL;
1241          url3 += "/";
1242          url3 += m_name;
1243          url3 += "PROTO.wrl";
1244 #endif
1245          break;
1246       case URL_X3D:
1247 #ifdef HAVE_X3D_PROTO_URL
1248          url3 += HAVE_X3D_PROTO_URL;
1249          url3 += "/";
1250          url3 += m_name;
1251          url3 += "PROTO.wrl";
1252 #endif
1253          break;
1254       case URL_SCRIPTED_NODES:
1255 #ifdef HAVE_SCRIPTED_NODES_PROTO_URL
1256          url3 += HAVE_SCRIPTED_NODES_PROTO_URL;
1257          url3 += "/";
1258          url3 += m_name;
1259          url3 += "PROTO.wrl";
1260 #endif
1261          break;
1262       case URL_COVER:
1263 #ifdef HAVE_COVER_NODES_PROTO_URL
1264          url3 += HAVE_COVER_NODES_PROTO_URL;
1265          url3 += "/";
1266          url3 += m_name;
1267          url3 += "PROTO.wrl";
1268 #endif
1269          break;
1270       case URL_EXPORT_CONTAINER:
1271 #ifdef HAVE_EXPORT_CONTAINER_PROTO_URL
1272          url3 += HAVE_EXPORT_CONTAINER_PROTO_URL;
1273          url3 += "/";
1274          url3 += m_name;
1275          url3 += "PROTO.wrl";
1276 #endif
1277          break;
1278     }
1279     if (urlSchema == URL_KAMBI)
1280         url3 += "http://vrmlengine.sourceforge.net/fallback_prototypes.wrl";
1281     if (strlen(url3) > 0)
1282         urls->append(url3);
1283 
1284     MyString url4 = "";
1285     url4 += "http://wdune.ourproject.org/docs/";
1286     switch(urlSchema) {
1287       case URL_VRML97_AMENDMENT1:
1288          url4 += "vrml97Amendment1";
1289          url4 += "/";
1290          url4 += m_name;
1291          url4 += "PROTO.wrl";
1292          break;
1293       case URL_X3D:
1294          url4 += "x3d";
1295          url4 += "/";
1296          url4 += m_name;
1297          url4 += "PROTO.wrl";
1298          break;
1299          break;
1300       case URL_SCRIPTED_NODES:
1301          url4 += "scripted_Nodes";
1302          url4 += "/";
1303          url4 += m_name;
1304          url4 += "PROTO.wrl";
1305          break;
1306       case URL_COVER:
1307          url4 += "coverNodes";
1308          url4 += "/";
1309          url4 += m_name;
1310          url4 += "PROTO.wrl";
1311          break;
1312       case URL_EXPORT_CONTAINER:
1313          url4 += "exportContainers";
1314          url4 += "/";
1315          url4 += m_name;
1316          url4 += "PROTO.wrl";
1317          break;
1318     }
1319     if (strlen(url4) > 0)
1320         urls->append(url4);
1321 
1322     m_urls = new MFString(urls);
1323 
1324 }
1325 
1326 bool
checkIsExtension(Element * element,int flag)1327 Proto::checkIsExtension(Element *element, int flag)
1328 {
1329     bool ret = false;
1330     bool x3d = (flag == FF_X3D_ONLY) ? true : false;
1331     const char* elementName = element->getElementName(false);
1332     if (element->getNumIs() == 1) {
1333         Proto *proto = element->getIsNode(0)->getProto();
1334         const char *isElementName = NULL;
1335         switch (element->getType()) {
1336           case EL_FIELD:
1337             isElementName = proto->getField(element->getIsField(0))->
1338                             getElementName(x3d);
1339             break;
1340           case EL_EVENT_IN:
1341             isElementName = proto->getEventIn(element->getIsField(0))->
1342                             getElementName(x3d);
1343             break;
1344           case EL_EVENT_OUT:
1345             isElementName = proto->getEventOut(element->getIsField(0))->
1346                             getElementName(x3d);
1347             break;
1348           case EL_EXPOSED_FIELD:
1349             isElementName = proto->getExposedField(element->getIsField(0))->
1350                             getElementName(x3d);
1351             break;
1352           default:
1353             return false;
1354         }
1355         if (strcmp(elementName, isElementName) == 0)
1356             ret = true;
1357         else
1358             return false;
1359     } else if (element->getNumIs() == 0) {
1360         Proto *proto = m_protoNodes[0]->getProto();
1361         int field = -1;
1362         switch (element->getType()) {
1363           case EL_FIELD:
1364             field = proto->lookupField(elementName, x3d);
1365             break;
1366           case EL_EVENT_IN:
1367             field = proto->lookupEventIn(elementName, x3d);
1368             break;
1369           case EL_EVENT_OUT:
1370             field = proto->lookupEventOut(elementName, x3d);
1371             break;
1372           case EL_EXPOSED_FIELD:
1373             field = proto->lookupExposedField(elementName, x3d);
1374             break;
1375           default:
1376             return false;
1377         }
1378         if (field == -1)
1379             return false;
1380         if (proto->getField(field)->getFlags() & flag)
1381             ret = true;
1382         else
1383            return false;
1384     } else
1385         return false;
1386     return ret;
1387 }
1388 
1389 bool
isExtensionProto(int flag)1390 Proto::isExtensionProto(int flag)
1391 {
1392     bool ret = false;
1393     bool x3d = (flag == FF_X3D_ONLY) ? true : false;
1394     for (long i = 0; i < m_fields.size(); i++) {
1395         const char* name = m_fields[i]->getName(x3d);
1396         Element *element = m_fields[i];
1397         ExposedField *exposedField = m_fields[i]->getExposedField();
1398         if (exposedField)
1399             element = exposedField;
1400         if ((element->getNumIs() == 1) && (m_protoNodes.size() > 0)) {
1401             Proto *proto = element->getIsNode(0)->getProto();
1402             Field *field = proto->getField(element->getIsField(0));
1403             if (strcmp(name, field->getName(x3d)) == 0)
1404                 ret = true;
1405             else
1406                 return false;
1407         } else if (element->getNumIs() == 0) {
1408             if ((flag == FF_COVER_ONLY) &&
1409                 (m_fields[i]->getFlags() & FF_X3D_ONLY))
1410                 continue;
1411             if ((flag == FF_KAMBI_ONLY) &&
1412                 (m_fields[i]->getFlags() & FF_X3D_ONLY))
1413                 continue;
1414             if (m_protoNodes.size() < 1)
1415                 continue;
1416             if (m_protoNodes[0] == NULL)
1417                 continue;
1418             Proto *proto = m_protoNodes[0]->getProto();
1419             int field = proto->lookupField(name, x3d);
1420             if (field == -1)
1421                 return false;
1422             if (proto->getField(field)->getFlags() & flag)
1423                 ret = true;
1424             else
1425                return false;
1426         } else
1427             return false;
1428     }
1429     for (long i = 0; i < m_eventIns.size(); i++) {
1430         const char* name = m_eventIns[i]->getName(x3d);
1431         if (m_eventIns[i]->getExposedField()) {
1432             // already handled
1433             continue;
1434         }
1435         if (m_eventIns[i]->getNumIs() == 1) {
1436             if ((flag == FF_COVER_ONLY) &&
1437                 (m_eventIns[i]->getFlags() & FF_X3D_ONLY))
1438                 continue;
1439             if ((flag == FF_KAMBI_ONLY) &&
1440                 (m_eventIns[i]->getFlags() & FF_X3D_ONLY))
1441                 continue;
1442             if (m_protoNodes.size() < 1)
1443                 continue;
1444             Proto *proto = m_eventIns[i]->getIsNode(0)->getProto();
1445             EventIn *field = proto->getEventIn(m_eventIns[i]->getIsField(0));
1446             if (strcmp(name, field->getName(x3d)) == 0)
1447                 ret = true;
1448             else
1449                 return false;
1450         } else if (m_eventIns[i]->getNumIs() == 0) {
1451             if (m_protoNodes.size() < 1)
1452                 continue;
1453             Proto *proto = m_protoNodes[0]->getProto();
1454             int field = proto->lookupEventIn(name, x3d);
1455             if (field == -1)
1456                 return false;
1457             if (proto->getEventIn(field)->getFlags() & flag)
1458                 ret = true;
1459             else
1460                return false;
1461         } else
1462             return false;
1463     }
1464     for (long i = 0; i < m_eventOuts.size(); i++) {
1465         const char* name = m_eventOuts[i]->getName(x3d);
1466         if (m_eventOuts[i]->getExposedField()) {
1467             // already handled
1468             continue;
1469         }
1470         if (m_eventOuts[i]->getNumIs() == 1) {
1471             Proto *proto = m_eventOuts[i]->getIsNode(0)->getProto();
1472             EventOut *field = proto->getEventOut(m_eventOuts[i]->getIsField(0));
1473             if (strcmp(name, field->getName(x3d)) == 0)
1474                 ret = true;
1475             else
1476                 return false;
1477         } else if (m_eventOuts[i]->getNumIs() == 0) {
1478             if ((flag == FF_COVER_ONLY) &&
1479                 (m_eventOuts[i]->getFlags() & FF_X3D_ONLY))
1480                 continue;
1481             if ((flag == FF_KAMBI_ONLY) &&
1482                 (m_eventOuts[i]->getFlags() & FF_X3D_ONLY))
1483                 continue;
1484             if (m_protoNodes.size() < 1)
1485                 continue;
1486             Proto *proto = m_protoNodes[0]->getProto();
1487             int field = proto->lookupEventOut(name, x3d);
1488             if (field == -1)
1489                 return false;
1490             if (proto->getEventOut(field)->getFlags() & flag)
1491                 ret = true;
1492             else
1493                return false;
1494         } else
1495             return false;
1496     }
1497     return ret;
1498 }
1499 
1500 bool
isMismatchingProto(void)1501 Proto::isMismatchingProto(void) {
1502    if (isKambiProto() && !(TheApp->getKambiMode()))
1503        return true;
1504    if (isCoverProto() && !(TheApp->getCoverMode()))
1505        return true;
1506    return false;
1507 }
1508 
1509 
1510 void
setFieldFlags(int index,int flags)1511 Proto::setFieldFlags(int index, int flags)
1512 {
1513     Field *field = m_fields[index];
1514     ExposedField *exposedField = field->getExposedField();
1515     if (exposedField) {
1516         exposedField->addFlags(flags);
1517         m_eventIns[exposedField->getEventIn()]->addFlags(flags);
1518         m_eventOuts[exposedField->getEventOut()]->addFlags(flags);
1519     }
1520     field->addFlags(flags);
1521 }
1522 
1523 int
writeCDeclaration(int f,int languageFlag)1524 Proto::writeCDeclaration(int f, int languageFlag)
1525 {
1526     if (m_name[0] == '#')
1527         return 0;
1528     if (m_writeCDeclarationWritten)
1529         return 0;
1530     m_writeCDeclarationWritten = true;
1531     if (languageFlag & C_SOURCE)
1532         RET_ONERROR( mywritestr(f, "struct ") )
1533     else
1534         RET_ONERROR( mywritestr(f, "class ") )
1535     RET_ONERROR( mywritestr(f, getClassName()) )
1536     if (languageFlag & CC_SOURCE) {
1537         RET_ONERROR( mywritestr(f, " : public ") )
1538         RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
1539     }
1540     if (languageFlag & JAVA_SOURCE) {
1541         RET_ONERROR( mywritestr(f, " extends ") )
1542         RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
1543     }
1544     RET_ONERROR( mywritestr(f, " {\n") )
1545     if (languageFlag & CC_SOURCE)
1546          RET_ONERROR( mywritestr(f, "public:\n") )
1547     // data
1548     if (languageFlag & C_SOURCE) {
1549         SFNode node;
1550         RET_ONERROR( mywritestr(f, "    ") )
1551         RET_ONERROR( mywritestr(f, node.getTypeC(languageFlag)) )
1552         RET_ONERROR( mywritestr(f, " m_parent;\n") )
1553         RET_ONERROR( mywritestr(f, "    ") )
1554         RET_ONERROR( mywritestr(f, node.getTypeC(languageFlag)) )
1555         RET_ONERROR( mywritestr(f, " m_protoRoot;\n") )
1556         RET_ONERROR( mywritestr(f, "    int") )
1557         RET_ONERROR( mywritestr(f, " m_type;\n") )
1558         RET_ONERROR( mywritestr(f, "    void") )
1559         RET_ONERROR( mywritestr(f, " *m_data;\n") )
1560     }
1561     for (long i = 0; i < m_eventIns.size(); i++)
1562         RET_ONERROR( writeCDeclarationEventIn(f, i, languageFlag) )
1563     for (long i = 0; i < m_eventOuts.size(); i++)
1564         RET_ONERROR( writeCDeclarationEventOut(f, i, languageFlag) )
1565     for (long i = 0; i < m_fields.size(); i++)
1566         RET_ONERROR( writeCDeclarationField(f, i, languageFlag) )
1567     writeCExtraFields(f, languageFlag);
1568     if (languageFlag & CC_SOURCE) {
1569         // callbacks
1570         RET_ONERROR( mywritestr(f, "\n") )
1571         RET_ONERROR( mywritestr(f, "    int getType() const ") )
1572         RET_ONERROR( mywritef(f, "{ return %d; }\n", getType()) )
1573         RET_ONERROR( mywritestr(f, "\n") )
1574 
1575         if ((getType() == VRML_INDEXED_FACE_SET) ||
1576             (getType() == VRML_INDEXED_LINE_SET) ||
1577             (getType() == X3D_LINE_SET) ||
1578             (getType() == VRML_POINT_SET)) {
1579             RET_ONERROR( mywritestr(f, "    void setGlName(int number)") )
1580             RET_ONERROR( mywritestr(f, "{ glName_number = number; }\n") )
1581             RET_ONERROR( mywritestr(f, "\n") )
1582         }
1583 
1584         RET_ONERROR( mywritestr(f, "    static ") )
1585         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1586         RET_ONERROR( mywritestr(f, "Callback ") )
1587         RET_ONERROR( mywritestr(f, "renderCallback;\n") )
1588 
1589         RET_ONERROR( mywritestr(f, "    static ") )
1590         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1591         RET_ONERROR( mywritestr(f, "Callback ") )
1592         RET_ONERROR( mywritestr(f, "treeRenderCallback;\n") )
1593 
1594         if (getType() == VRML_INDEXED_FACE_SET) {
1595             RET_ONERROR( mywritestr(f, "    static ") )
1596             RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1597             RET_ONERROR( mywritestr(f, "Callback ") )
1598             RET_ONERROR( mywritestr(f, "createNormalsCallback;\n") )
1599         }
1600 
1601         RET_ONERROR( mywritestr(f, "    static ") )
1602         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1603         RET_ONERROR( mywritestr(f, "Callback ") )
1604         RET_ONERROR( mywritestr(f, "doWithDataCallback;\n") )
1605 
1606         RET_ONERROR( mywritestr(f, "    static ") )
1607         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1608         RET_ONERROR( mywritestr(f, "Callback ") )
1609         RET_ONERROR( mywritestr(f, "treeDoWithDataCallback;\n") )
1610 
1611         RET_ONERROR( mywritestr(f, "    static ") )
1612         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1613         RET_ONERROR( mywritestr(f, "ProcessEventCallback ") )
1614         RET_ONERROR( mywritestr(f, "processEventCallback;\n") )
1615 
1616         RET_ONERROR( mywritestr(f, "\n") )
1617     } else if (languageFlag & JAVA_SOURCE) {
1618         // callbacks
1619         if ((getType() != VRML_COMMENT) && !(isMismatchingProto())) {
1620             RET_ONERROR( mywritestr(f, "    int getType() ") )
1621             RET_ONERROR( mywritef(f, "{ return %d; }\n", getType()) )
1622             RET_ONERROR( mywritestr(f, "\n") )
1623 
1624             RET_ONERROR( mywritestr(f, "    static ") )
1625             RET_ONERROR( mywritestr(f, getRenderCallbackClass()) )
1626             RET_ONERROR( mywritestr(f, " ") )
1627             RET_ONERROR( mywritestr(f, getRenderCallbackName()) )
1628             RET_ONERROR( mywritestr(f, ";\n") )
1629 
1630             RET_ONERROR( mywritestr(f, "    static void set") )
1631             RET_ONERROR( mywritestr(f, getRenderCallbackClass()) )
1632             RET_ONERROR( mywritestr(f, "(") )
1633             RET_ONERROR( mywritestr(f, getRenderCallbackClass()) )
1634             RET_ONERROR( mywritestr(f, " node) {\n") )
1635             RET_ONERROR( mywritestr(f, "        ") )
1636             RET_ONERROR( mywritestr(f, getRenderCallbackName()) )
1637             RET_ONERROR( mywritestr(f, " = node;\n") )
1638             RET_ONERROR( mywritestr(f, "    }\n\n") )
1639 
1640             RET_ONERROR( mywritestr(f, "    static ") )
1641             RET_ONERROR( mywritestr(f, getTreeRenderCallbackClass()) )
1642             RET_ONERROR( mywritestr(f, " ") )
1643             RET_ONERROR( mywritestr(f, getTreeRenderCallbackName()) )
1644             RET_ONERROR( mywritestr(f, ";\n") )
1645 
1646             RET_ONERROR( mywritestr(f, "    static void set") )
1647             RET_ONERROR( mywritestr(f, getTreeRenderCallbackClass()) )
1648             RET_ONERROR( mywritestr(f, "(") )
1649             RET_ONERROR( mywritestr(f, getTreeRenderCallbackClass()) )
1650             RET_ONERROR( mywritestr(f, " node) {\n") )
1651             RET_ONERROR( mywritestr(f, "        ") )
1652             RET_ONERROR( mywritestr(f, getTreeRenderCallbackName()) )
1653             RET_ONERROR( mywritestr(f, " = node;\n") )
1654             RET_ONERROR( mywritestr(f, "    }\n\n") )
1655 
1656             if (getType() == VRML_INDEXED_FACE_SET) {
1657                 RET_ONERROR( mywritestr(f, "    static ") )
1658                 RET_ONERROR( mywritestr(f, getCreateNormalsCallbackClass()) )
1659                 RET_ONERROR( mywritestr(f, " ") )
1660                 RET_ONERROR( mywritestr(f, getCreateNormalsCallbackName()) )
1661                 RET_ONERROR( mywritestr(f, ";\n") )
1662 
1663                 RET_ONERROR( mywritestr(f, "    static void set") )
1664                 RET_ONERROR( mywritestr(f, getCreateNormalsCallbackClass()) )
1665                 RET_ONERROR( mywritestr(f, "(") )
1666                 RET_ONERROR( mywritestr(f, getCreateNormalsCallbackClass()) )
1667                 RET_ONERROR( mywritestr(f, " node) {\n") )
1668                 RET_ONERROR( mywritestr(f, "        ") )
1669                 RET_ONERROR( mywritestr(f, getCreateNormalsCallbackName()) )
1670                 RET_ONERROR( mywritestr(f, " = node;\n") )
1671                 RET_ONERROR( mywritestr(f, "    }\n\n") )
1672             }
1673             if ((getType() == VRML_INDEXED_FACE_SET) ||
1674                 (getType() == VRML_INDEXED_LINE_SET) ||
1675                 (getType() == X3D_LINE_SET) ||
1676                 (getType() == VRML_POINT_SET)) {
1677                 RET_ONERROR( mywritestr(f, "    void setGlName(int number)") )
1678                 RET_ONERROR( mywritestr(f, "{ glName_number = number; }\n") )
1679                 RET_ONERROR( mywritestr(f, "\n") )
1680             }
1681 
1682             RET_ONERROR( mywritestr(f, "    static ") )
1683             RET_ONERROR( mywritestr(f, getDoWithDataCallbackClass()) )
1684             RET_ONERROR( mywritestr(f, " ") )
1685             RET_ONERROR( mywritestr(f, getDoWithDataCallbackName()) )
1686             RET_ONERROR( mywritestr(f, ";\n") )
1687 
1688             RET_ONERROR( mywritestr(f, "    static void set") )
1689             RET_ONERROR( mywritestr(f, getDoWithDataCallbackClass()) )
1690             RET_ONERROR( mywritestr(f, "(") )
1691             RET_ONERROR( mywritestr(f, getDoWithDataCallbackClass()) )
1692             RET_ONERROR( mywritestr(f, " node) {\n") )
1693             RET_ONERROR( mywritestr(f, "        ") )
1694             RET_ONERROR( mywritestr(f, getDoWithDataCallbackName()) )
1695             RET_ONERROR( mywritestr(f, " = node;\n") )
1696             RET_ONERROR( mywritestr(f, "    }\n\n") )
1697 
1698             RET_ONERROR( mywritestr(f, "    static ") )
1699             RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackClass()) )
1700             RET_ONERROR( mywritestr(f, " ") )
1701             RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackName()) )
1702             RET_ONERROR( mywritestr(f, ";\n") )
1703 
1704             RET_ONERROR( mywritestr(f, "    static void set") )
1705             RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackClass()) )
1706             RET_ONERROR( mywritestr(f, "(") )
1707             RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackClass()) )
1708             RET_ONERROR( mywritestr(f, " node) {\n") )
1709             RET_ONERROR( mywritestr(f, "        ") )
1710             RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackName()) )
1711             RET_ONERROR( mywritestr(f, " = node;\n\n") )
1712             RET_ONERROR( mywritestr(f, "    }\n\n") )
1713 
1714             RET_ONERROR( mywritestr(f, "    static ") )
1715             RET_ONERROR( mywritestr(f, getProcessEventCallbackClass()) )
1716             RET_ONERROR( mywritestr(f, " ") )
1717             RET_ONERROR( mywritestr(f, getProcessEventCallbackName()) )
1718             RET_ONERROR( mywritestr(f, ";\n") )
1719 
1720             RET_ONERROR( mywritestr(f, "    static void set") )
1721             RET_ONERROR( mywritestr(f, getProcessEventCallbackClass()) )
1722             RET_ONERROR( mywritestr(f, "(") )
1723             RET_ONERROR( mywritestr(f, getProcessEventCallbackClass()) )
1724             RET_ONERROR( mywritestr(f, " node) {\n") )
1725             RET_ONERROR( mywritestr(f, "        ") )
1726             RET_ONERROR( mywritestr(f, getProcessEventCallbackName()) )
1727             RET_ONERROR( mywritestr(f, " = node;\n") )
1728             RET_ONERROR( mywritestr(f, "    }\n\n") )
1729         }
1730     }
1731 
1732     if (languageFlag & C_SOURCE) {
1733         RET_ONERROR( mywritestr(f, "}") )
1734         RET_ONERROR( mywritestr(f, ";") )
1735         RET_ONERROR( mywritestr(f, "\n\n") )
1736     }
1737 
1738     if (languageFlag & C_SOURCE) {
1739         if (getType() == VRML_INDEXED_FACE_SET) {
1740             RET_ONERROR( mywritef(f, "    void %sSetGlName(",
1741                                   TheApp->getCPrefix()) )
1742             RET_ONERROR( mywritef(f, "struct %sIndexedFaceSet* self, ",
1743                                   TheApp->getCPrefix()) )
1744             RET_ONERROR( mywritestr(f, "int number)\n") );
1745             RET_ONERROR( mywritestr(f, "{\n") )
1746             RET_ONERROR( mywritestr(f, "    self->glName_number = number;\n") )
1747             RET_ONERROR( mywritestr(f, "}\n") )
1748             RET_ONERROR( mywritestr(f, "\n") )
1749         }
1750         if (getType() == VRML_INDEXED_LINE_SET) {
1751             RET_ONERROR( mywritef(f, "    void %sSetGlNameIndexedLineSet(",
1752                                   TheApp->getCPrefix()) )
1753             RET_ONERROR( mywritef(f, "struct %sIndexedFaceSet* self, ",
1754                                   TheApp->getCPrefix()) )
1755             RET_ONERROR( mywritestr(f, "int number)\n") );
1756             RET_ONERROR( mywritestr(f, "{\n") )
1757             RET_ONERROR( mywritestr(f, "    self->glName_number = number;\n") )
1758             RET_ONERROR( mywritestr(f, "}\n") )
1759             RET_ONERROR( mywritestr(f, "\n") )
1760         }
1761         if (getType() == X3D_LINE_SET) {
1762             RET_ONERROR( mywritef(f, "    void %sSetGlNameLineSet(",
1763                                   TheApp->getCPrefix()) )
1764             RET_ONERROR( mywritef(f, "struct %sIndexedFaceSet* self, ",
1765                                   TheApp->getCPrefix()) )
1766             RET_ONERROR( mywritestr(f, "int number)\n") );
1767             RET_ONERROR( mywritestr(f, "{\n") )
1768             RET_ONERROR( mywritestr(f, "    self->glName_number = number;\n") )
1769             RET_ONERROR( mywritestr(f, "}\n") )
1770             RET_ONERROR( mywritestr(f, "\n") )
1771         }
1772         if (getType() == VRML_POINT_SET) {
1773             RET_ONERROR( mywritef(f, "    void %sSetGlNamePointSet(",
1774                                   TheApp->getCPrefix()) )
1775             RET_ONERROR( mywritef(f, "struct %sIndexedFaceSet* self, ",
1776                                   TheApp->getCPrefix()) )
1777             RET_ONERROR( mywritestr(f, "int number)\n") );
1778             RET_ONERROR( mywritestr(f, "{\n") )
1779             RET_ONERROR( mywritestr(f, "    self->glName_number = number;\n") )
1780             RET_ONERROR( mywritestr(f, "}\n") )
1781             RET_ONERROR( mywritestr(f, "\n") )
1782         }
1783     }
1784 
1785     if (languageFlag & (CC_SOURCE | JAVA_SOURCE))
1786         RET_ONERROR( mywritestr(f, "    ") )
1787     if (languageFlag & C_SOURCE)
1788         RET_ONERROR( mywritestr(f, "void ") )
1789     // constructor
1790     RET_ONERROR( mywritestr(f, getClassName()) )
1791     if (languageFlag & C_SOURCE)
1792         RET_ONERROR( mywritestr(f, "Init") )
1793     RET_ONERROR( mywritestr(f, "(") )
1794     if (languageFlag & C_SOURCE) {
1795         RET_ONERROR( mywritestr(f, "struct ") )
1796         RET_ONERROR( mywritestr(f, getClassName()) )
1797         RET_ONERROR( mywritestr(f, "* self") )
1798     }
1799     RET_ONERROR( mywritestr(f, ") {\n") )
1800     if (languageFlag & C_SOURCE) {
1801         RET_ONERROR( mywritestr(f, "    self->m_protoRoot = NULL;\n") )
1802     }
1803     if (languageFlag & (C_SOURCE | CC_SOURCE))
1804         for (long i = 0; i < m_fields.size(); i++)
1805             RET_ONERROR( writeCConstructorField(f, i, languageFlag) )
1806     if (languageFlag & (CC_SOURCE | JAVA_SOURCE))
1807         RET_ONERROR( mywritestr(f, "    ") )
1808     RET_ONERROR( mywritestr(f, "    ") )
1809     if (languageFlag & C_SOURCE)
1810         RET_ONERROR( mywritestr(f, "self->") )
1811     RET_ONERROR( mywritestr(f, "extra_data = ") )
1812     if (languageFlag & JAVA_SOURCE)
1813         RET_ONERROR( mywritestr(f, "null;\n") )
1814     else
1815         RET_ONERROR( mywritestr(f, "NULL;\n") )
1816     if (languageFlag & (CC_SOURCE | JAVA_SOURCE))
1817         RET_ONERROR( mywritestr(f, "    ") )
1818     RET_ONERROR( mywritestr(f, "}\n") )
1819     if (languageFlag & C_SOURCE)
1820         RET_ONERROR( mywritestr(f, "\n") )
1821 
1822     if (languageFlag & C_SOURCE) {
1823         // callback declarations
1824         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1825         RET_ONERROR( mywritestr(f, "Callback ") )
1826         RET_ONERROR( mywritestr(f, getRenderCallbackClass()) )
1827         RET_ONERROR( mywritestr(f, " = NULL;\n") )
1828 
1829         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1830         RET_ONERROR( mywritestr(f, "Callback ") )
1831         RET_ONERROR( mywritestr(f, getTreeRenderCallbackClass()) )
1832         RET_ONERROR( mywritestr(f, " = NULL;\n") )
1833 
1834         if (getType() == VRML_INDEXED_FACE_SET) {
1835             RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1836             RET_ONERROR( mywritestr(f, "Callback ") )
1837             RET_ONERROR( mywritestr(f, getCreateNormalsCallbackClass()) )
1838             RET_ONERROR( mywritestr(f, " = NULL;\n") )
1839         }
1840 
1841         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1842         RET_ONERROR( mywritestr(f, "Callback ") )
1843         RET_ONERROR( mywritestr(f, getDoWithDataCallbackClass()) )
1844         RET_ONERROR( mywritestr(f, " = NULL;\n") )
1845 
1846         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1847         RET_ONERROR( mywritestr(f, "Callback ") )
1848         RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackClass()) )
1849         RET_ONERROR( mywritestr(f, " = NULL;\n\n") )
1850 
1851         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1852         RET_ONERROR( mywritestr(f, "ProcessEventCallback ") )
1853         RET_ONERROR( mywritestr(f, getProcessEventCallbackClass()) )
1854         RET_ONERROR( mywritestr(f, " = NULL;\n\n") )
1855 
1856         bool writeOut = true;
1857         if (getType() == VRML_SCRIPT) {
1858             if (m_scene->getScriptTypeWritten())
1859                 writeOut = false;
1860             m_scene->setScriptTypeWritten();
1861         }
1862         if (writeOut) {
1863             // type
1864             RET_ONERROR( mywritestr(f, "int ") )
1865             RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1866             RET_ONERROR( mywritestr(f, getName(true)) )
1867             RET_ONERROR( mywritestr(f, "Type") )
1868             RET_ONERROR( mywritef(f, " = %d;\n\n", getType()) )
1869         }
1870 
1871         // functions
1872         RET_ONERROR( mywritestr(f, "void ") )
1873         RET_ONERROR( mywritestr(f, getClassName()) )
1874         RET_ONERROR( mywritestr(f, "Render(") )
1875         RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
1876         RET_ONERROR( mywritestr(f, "* self, void *dataptr) {") )
1877         RET_ONERROR( mywritestr(f, "\n") )
1878         RET_ONERROR( mywritestr(f, "    if (") )
1879         RET_ONERROR( mywritestr(f, getRenderCallbackClass()) )
1880         RET_ONERROR( mywritestr(f, ")\n") )
1881         RET_ONERROR( mywritestr(f, "        ") )
1882         RET_ONERROR( mywritestr(f, getRenderCallbackClass()) )
1883         RET_ONERROR( mywritestr(f, "(self, dataptr);\n") )
1884         RET_ONERROR( mywritestr(f, "}\n") )
1885 
1886         RET_ONERROR( mywritestr(f, "void ") )
1887         RET_ONERROR( mywritestr(f, getClassName()) )
1888         RET_ONERROR( mywritestr(f, "TreeRender(") )
1889         RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
1890         RET_ONERROR( mywritestr(f, "* self, void *dataptr)") )
1891         RET_ONERROR( mywritestr(f, " {\n") )
1892         RET_ONERROR( mywritestr(f, "    int i;\n") )
1893         RET_ONERROR( mywritestr(f, "    if (") )
1894         RET_ONERROR( mywritestr(f, "((struct ") )
1895         RET_ONERROR( mywritestr(f, getClassName()) )
1896         RET_ONERROR( mywritestr(f, "*)self)->m_protoRoot != NULL)\n") )
1897         RET_ONERROR( mywritestr(f, "        ") )
1898         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1899         RET_ONERROR( mywritestr(f, "TreeRenderCallback(((struct ") )
1900         RET_ONERROR( mywritestr(f, getClassName()) )
1901         RET_ONERROR( mywritestr(f, "*)self)->m_protoRoot, dataptr);\n") )
1902         RET_ONERROR( mywritestr(f, "    else {\n") )
1903 
1904         for (long i = 0; i < m_fields.size(); i++)
1905             RET_ONERROR( writeCCallTreeField(f, i, "TreeRenderCallback",
1906                                              languageFlag) )
1907 
1908         RET_ONERROR( mywritestr(f, "        ") )
1909         RET_ONERROR( mywritestr(f, getClassName()) )
1910         RET_ONERROR( mywritestr(f, "Render(self, dataptr);\n") )
1911 
1912         RET_ONERROR( mywritestr(f, "    }\n") )
1913         RET_ONERROR( mywritestr(f, "}\n") )
1914 
1915         if (getType() == VRML_INDEXED_FACE_SET) {
1916             RET_ONERROR( mywritestr(f, "void ") )
1917             RET_ONERROR( mywritestr(f, getClassName()) )
1918             RET_ONERROR( mywritestr(f, "CreateNormals(") )
1919             RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
1920             RET_ONERROR( mywritestr(f, "* self, void *dataptr) {") )
1921             RET_ONERROR( mywritestr(f, "\n") )
1922             RET_ONERROR( mywritestr(f, "    if (") )
1923             RET_ONERROR( mywritestr(f, getCreateNormalsCallbackClass()) )
1924             RET_ONERROR( mywritestr(f, ")\n") )
1925             RET_ONERROR( mywritestr(f, "        ") )
1926             RET_ONERROR( mywritestr(f, getCreateNormalsCallbackClass()) )
1927             RET_ONERROR( mywritestr(f, "(self, dataptr);\n") )
1928             RET_ONERROR( mywritestr(f, "}\n") )
1929         }
1930 
1931         // functions
1932         RET_ONERROR( mywritestr(f, "void ") )
1933         RET_ONERROR( mywritestr(f, getClassName()) )
1934         RET_ONERROR( mywritestr(f, "DoWithData(") )
1935         RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
1936         RET_ONERROR( mywritestr(f, "* self, void *dataptr)") )
1937         RET_ONERROR( mywritestr(f, " {\n") )
1938         RET_ONERROR( mywritestr(f, "    if (") )
1939         RET_ONERROR( mywritestr(f, getDoWithDataCallbackClass()) )
1940         RET_ONERROR( mywritestr(f, ")\n") )
1941         RET_ONERROR( mywritestr(f, "        ") )
1942         RET_ONERROR( mywritestr(f, getDoWithDataCallbackClass()) )
1943         RET_ONERROR( mywritestr(f, "(self, dataptr);\n") )
1944         RET_ONERROR( mywritestr(f, "}\n") )
1945 
1946         RET_ONERROR( mywritestr(f, "void ") )
1947         RET_ONERROR( mywritestr(f, getClassName()) )
1948         RET_ONERROR( mywritestr(f, "TreeDoWithData(") )
1949         RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
1950         RET_ONERROR( mywritestr(f, "* self, ") )
1951         RET_ONERROR( mywritestr(f, "void *dataptr)") )
1952         RET_ONERROR( mywritestr(f, " {\n") )
1953         RET_ONERROR( mywritestr(f, "    int i;\n") )
1954 
1955         RET_ONERROR( mywritestr(f, "    if (") )
1956         RET_ONERROR( mywritestr(f, "((struct ") )
1957         RET_ONERROR( mywritestr(f, getClassName()) )
1958         RET_ONERROR( mywritestr(f, "*)self)->m_protoRoot != NULL)\n") )
1959         RET_ONERROR( mywritestr(f, "        ") )
1960         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
1961         RET_ONERROR( mywritestr(f, "TreeDoWithDataCallback(((struct ") )
1962         RET_ONERROR( mywritestr(f, getClassName()) )
1963         RET_ONERROR( mywritestr(f, "*)self)->m_protoRoot, dataptr);\n") )
1964         RET_ONERROR( mywritestr(f, "    else {\n") )
1965 
1966         for (long i = 0; i < m_fields.size(); i++)
1967             RET_ONERROR( writeCCallTreeField(f, i, "TreeDoWithDataCallback", languageFlag) )
1968 
1969         RET_ONERROR( mywritestr(f, "        ") )
1970         RET_ONERROR( mywritestr(f, getClassName()) )
1971         RET_ONERROR( mywritestr(f, "DoWithData(self, dataptr);\n") )
1972 
1973         RET_ONERROR( mywritestr(f, "    }\n") )
1974         RET_ONERROR( mywritestr(f, "}\n") )
1975     }
1976     if (languageFlag & CC_SOURCE) {
1977         // memberfunctions
1978         RET_ONERROR( mywritestr(f, "    virtual void ") )
1979         RET_ONERROR( mywritestr(f, "treeRender(void *dataptr) {\n") )
1980         RET_ONERROR( mywritestr(f, "        int i;\n") )
1981 
1982         RET_ONERROR( mywritestr(f, "        if (") )
1983         RET_ONERROR( mywritestr(f, "treeRenderCallback) {\n") )
1984         RET_ONERROR( mywritestr(f, "            ") )
1985         RET_ONERROR( mywritestr(f, "treeRenderCallback(this, ") )
1986         RET_ONERROR( mywritestr(f, "dataptr);\n") )
1987         RET_ONERROR( mywritestr(f, "            return;\n") )
1988         RET_ONERROR( mywritestr(f, "        }\n") )
1989 
1990         RET_ONERROR( mywritestr(f, "        if (m_protoRoot != NULL)\n") )
1991         RET_ONERROR( mywritestr(f, "            m_protoRoot->") )
1992         RET_ONERROR( mywritestr(f, "treeRender(dataptr);\n") )
1993         RET_ONERROR( mywritestr(f, "        else {\n") )
1994 
1995         for (long i = 0; i < m_fields.size(); i++)
1996             RET_ONERROR( writeCCallTreeField(f, i, "TreeRender", languageFlag,
1997                                              "renderCallback") )
1998 
1999         RET_ONERROR( mywritestr(f, "            render(dataptr);\n") )
2000         RET_ONERROR( mywritestr(f, "        }\n") )
2001 
2002         RET_ONERROR( mywritestr(f, "    }\n") )
2003 
2004         RET_ONERROR( mywritestr(f, "    virtual void render(void *dataptr) {\n") )
2005         RET_ONERROR( mywritestr(f, "        if (") )
2006         RET_ONERROR( mywritestr(f, "renderCallback)\n") )
2007         RET_ONERROR( mywritestr(f, "            ") )
2008         RET_ONERROR( mywritestr(f, "renderCallback(this, dataptr);") )
2009         RET_ONERROR( mywritestr(f, "\n    }\n") )
2010 
2011         if (getType() == VRML_INDEXED_FACE_SET) {
2012             RET_ONERROR( mywritestr(f, "    virtual void createNormals(void *dataptr) {\n") )
2013             RET_ONERROR( mywritestr(f, "        if (") )
2014             RET_ONERROR( mywritestr(f, "createNormalsCallback)\n") )
2015             RET_ONERROR( mywritestr(f, "            ") )
2016             RET_ONERROR( mywritestr(f, "createNormalsCallback(this, dataptr);") )
2017             RET_ONERROR( mywritestr(f, "\n    }\n") )
2018         }
2019 
2020         RET_ONERROR( mywritestr(f, "    virtual void treeDoWithData(void *dataptr)") )
2021         RET_ONERROR( mywritestr(f, " {\n") )
2022         RET_ONERROR( mywritestr(f, "        int i;\n") )
2023 
2024         RET_ONERROR( mywritestr(f, "        if (") )
2025         RET_ONERROR( mywritestr(f, "treeDoWithDataCallback) {\n") )
2026         RET_ONERROR( mywritestr(f, "            ") )
2027         RET_ONERROR( mywritestr(f, "treeDoWithDataCallback(this, ") )
2028         RET_ONERROR( mywritestr(f, "dataptr);\n") )
2029         RET_ONERROR( mywritestr(f, "            return;\n") )
2030         RET_ONERROR( mywritestr(f, "        }\n") )
2031 
2032 
2033         RET_ONERROR( mywritestr(f, "        if (m_protoRoot != NULL)\n") )
2034         RET_ONERROR( mywritestr(f, "            m_protoRoot->") )
2035         RET_ONERROR( mywritestr(f, "treeDoWithData(dataptr);\n") )
2036         RET_ONERROR( mywritestr(f, "        else {\n") )
2037 
2038         for (long i = 0; i < m_fields.size(); i++)
2039             RET_ONERROR( writeCCallTreeField(f, i, "TreeDoWithData",
2040                                              languageFlag,
2041                                              "doWithDataCallback") )
2042 
2043         RET_ONERROR( mywritestr(f, "            doWithData(dataptr);\n") )
2044 
2045         RET_ONERROR( mywritestr(f, "        }\n") )
2046         RET_ONERROR( mywritestr(f, "    }\n") )
2047 
2048         RET_ONERROR( mywritestr(f, "    virtual void doWithData(void *dataptr)") )
2049         RET_ONERROR( mywritestr(f, " {\n") )
2050         RET_ONERROR( mywritestr(f, "        if (") )
2051         RET_ONERROR( mywritestr(f, "doWithDataCallback)\n") )
2052         RET_ONERROR( mywritestr(f, "            ") )
2053         RET_ONERROR( mywritestr(f, "doWithDataCallback(this, dataptr);" ) )
2054         RET_ONERROR( mywritestr(f, "\n") )
2055         RET_ONERROR( mywritestr(f, "    }\n") )
2056 
2057         RET_ONERROR( mywritestr(f, "}") )
2058         RET_ONERROR( mywritestr(f, ";") )
2059         RET_ONERROR( mywritestr(f, "\n\n") )
2060 
2061         // callbacks
2062         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2063         RET_ONERROR( mywritestr(f, "Callback ") )
2064         RET_ONERROR( mywritestr(f, getClassName()) )
2065         RET_ONERROR( mywritestr(f, "::") )
2066         RET_ONERROR( mywritestr(f, "renderCallback = NULL;\n") )
2067 
2068         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2069         RET_ONERROR( mywritestr(f, "Callback ") )
2070         RET_ONERROR( mywritestr(f, getClassName()) )
2071         RET_ONERROR( mywritestr(f, "::") )
2072         RET_ONERROR( mywritestr(f, "treeRenderCallback = NULL;\n") )
2073 
2074         if (getType() == VRML_INDEXED_FACE_SET) {
2075             RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2076             RET_ONERROR( mywritestr(f, "Callback ") )
2077             RET_ONERROR( mywritestr(f, getClassName()) )
2078             RET_ONERROR( mywritestr(f, "::") )
2079             RET_ONERROR( mywritestr(f, "createNormalsCallback = NULL;\n") )
2080         }
2081 
2082         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2083         RET_ONERROR( mywritestr(f, "Callback ") )
2084         RET_ONERROR( mywritestr(f, getClassName()) )
2085         RET_ONERROR( mywritestr(f, "::") )
2086         RET_ONERROR( mywritestr(f, "doWithDataCallback = NULL;\n") )
2087 
2088         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2089         RET_ONERROR( mywritestr(f, "Callback ") )
2090         RET_ONERROR( mywritestr(f, getClassName()) )
2091         RET_ONERROR( mywritestr(f, "::") )
2092         RET_ONERROR( mywritestr(f, "treeDoWithDataCallback = NULL;\n") )
2093 
2094         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2095         RET_ONERROR( mywritestr(f, "ProcessEventCallback ") )
2096         RET_ONERROR( mywritestr(f, getClassName()) )
2097         RET_ONERROR( mywritestr(f, "::") )
2098         RET_ONERROR( mywritestr(f, "processEventCallback") )
2099         RET_ONERROR( mywritestr(f, " = NULL;\n\n") )
2100 
2101         bool writeOut = true;
2102         if (getType() == VRML_SCRIPT) {
2103             if (m_scene->getScriptTypeWritten())
2104                 writeOut = false;
2105             m_scene->setScriptTypeWritten();
2106         }
2107         if (writeOut) {
2108             // type
2109             RET_ONERROR( mywritestr(f, "int ") )
2110             RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2111             RET_ONERROR( mywritestr(f, getName(true)) )
2112             RET_ONERROR( mywritestr(f, "Type") )
2113             RET_ONERROR( mywritef(f, " = %d;\n\n", getType()) )
2114         }
2115     }
2116     if (languageFlag & JAVA_SOURCE) {
2117         // memberfunctions
2118         RET_ONERROR( mywritestr(f, "    void treeRender(") )
2119         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2120         RET_ONERROR( mywritestr(f, "Node dataptr, Object object) {\n") )
2121         RET_ONERROR( mywritestr(f, "        if (") )
2122         RET_ONERROR( mywritestr(f, getClassName()) )
2123         RET_ONERROR( mywritestr(f, ".") )
2124         RET_ONERROR( mywritestr(f, getTreeRenderCallbackName()) )
2125         RET_ONERROR( mywritestr(f, " != null) {\n") )
2126         RET_ONERROR( mywritestr(f, "            ") )
2127         RET_ONERROR( mywritestr(f, getClassName()) )
2128         RET_ONERROR( mywritestr(f, ".") )
2129         RET_ONERROR( mywritestr(f, getTreeRenderCallbackName()) )
2130         RET_ONERROR( mywritestr(f, ".treeRender(this, object);\n") )
2131         RET_ONERROR( mywritestr(f, "            return;\n") )
2132         RET_ONERROR( mywritestr(f, "        }\n") )
2133         for (long i = 0; i < m_fields.size(); i++)
2134             RET_ONERROR( writeCCallTreeField(f, i, "TreeRender", languageFlag,
2135                                              "renderCallback", true) )
2136         RET_ONERROR( mywritestr(f, "        if (m_protoRoot != null)\n") )
2137         RET_ONERROR( mywritestr(f, "            m_protoRoot.") )
2138         RET_ONERROR( mywritestr(f, "treeRender(dataptr, object);\n") )
2139         RET_ONERROR( mywritestr(f, "        if (") )
2140         RET_ONERROR( mywritestr(f, getClassName()) )
2141         RET_ONERROR( mywritestr(f, ".") )
2142         RET_ONERROR( mywritestr(f, getRenderCallbackName()) )
2143         RET_ONERROR( mywritestr(f, " != null)\n") )
2144         RET_ONERROR( mywritestr(f, "            ") )
2145         RET_ONERROR( mywritestr(f, getClassName()) )
2146         RET_ONERROR( mywritestr(f, ".") )
2147         RET_ONERROR( mywritestr(f, getRenderCallbackName()) )
2148         RET_ONERROR( mywritestr(f, ".render(this, object);\n") )
2149         RET_ONERROR( mywritestr(f, "    }\n") )
2150 
2151         RET_ONERROR( mywritestr(f, "    void treeDoWithData(") )
2152         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2153         RET_ONERROR( mywritestr(f, "Node dataptr) {\n") )
2154         RET_ONERROR( mywritestr(f, "        if (") )
2155         RET_ONERROR( mywritestr(f, getClassName()) )
2156         RET_ONERROR( mywritestr(f, ".") )
2157         RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackName()) )
2158         RET_ONERROR( mywritestr(f, " != null) {\n") )
2159         RET_ONERROR( mywritestr(f, "            ") )
2160         RET_ONERROR( mywritestr(f, getClassName()) )
2161         RET_ONERROR( mywritestr(f, ".") )
2162         RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackName()) )
2163         RET_ONERROR( mywritestr(f, ".treeDoWithData(this);\n") )
2164         RET_ONERROR( mywritestr(f, "            return;\n") )
2165         RET_ONERROR( mywritestr(f, "        }\n") )
2166         for (long i = 0; i < m_fields.size(); i++)
2167             RET_ONERROR( writeCCallTreeField(f, i, "TreeDoWithData",
2168                                              languageFlag,
2169                                              "treeDoWithDataCallback") )
2170         RET_ONERROR( mywritestr(f, "        if (m_protoRoot != null)\n") )
2171         RET_ONERROR( mywritestr(f, "            m_protoRoot.") )
2172         RET_ONERROR( mywritestr(f, "treeDoWithData(dataptr);\n") )
2173         RET_ONERROR( mywritestr(f, "        if (") )
2174         RET_ONERROR( mywritestr(f, getClassName()) )
2175         RET_ONERROR( mywritestr(f, ".") )
2176         RET_ONERROR( mywritestr(f, getDoWithDataCallbackName()) )
2177         RET_ONERROR( mywritestr(f, " != null)\n") )
2178         RET_ONERROR( mywritestr(f, "            ") )
2179         RET_ONERROR( mywritestr(f, getClassName()) )
2180         RET_ONERROR( mywritestr(f, ".") )
2181         RET_ONERROR( mywritestr(f, getDoWithDataCallbackName()) )
2182         RET_ONERROR( mywritestr(f, ".doWithData(this);\n") )
2183         RET_ONERROR( mywritestr(f, "    }\n") )
2184 
2185         if (getType() == VRML_INDEXED_FACE_SET) {
2186             RET_ONERROR( mywritestr(f, "    void createNormals(Object dataptr) {\n") )
2187             RET_ONERROR( mywritestr(f, "        if (") )
2188             RET_ONERROR( mywritestr(f, getClassName()) )
2189             RET_ONERROR( mywritestr(f, ".") )
2190             RET_ONERROR( mywritestr(f, getCreateNormalsCallbackName()) )
2191             RET_ONERROR( mywritestr(f, " != null) {\n") )
2192             RET_ONERROR( mywritestr(f, "            ") )
2193             RET_ONERROR( mywritestr(f, getClassName()) )
2194             RET_ONERROR( mywritestr(f, ".") )
2195             RET_ONERROR( mywritestr(f, getCreateNormalsCallbackName()) )
2196             RET_ONERROR( mywritestr(f, ".createNormals(this, dataptr);\n") )
2197             RET_ONERROR( mywritestr(f, "            return;\n") )
2198             RET_ONERROR( mywritestr(f, "        }\n") )
2199             RET_ONERROR( mywritestr(f, "        if (") )
2200             RET_ONERROR( mywritestr(f, getClassName()) )
2201             RET_ONERROR( mywritestr(f, ".") )
2202             RET_ONERROR( mywritestr(f, getCreateNormalsCallbackName()) )
2203             RET_ONERROR( mywritestr(f, " != null)\n") )
2204             RET_ONERROR( mywritestr(f, "            ") )
2205             RET_ONERROR( mywritestr(f, getClassName()) )
2206             RET_ONERROR( mywritestr(f, ".") )
2207             RET_ONERROR( mywritestr(f, getCreateNormalsCallbackName()) )
2208             RET_ONERROR( mywritestr(f, ".createNormals(this, dataptr);\n") )
2209             RET_ONERROR( mywritestr(f, "    }\n") )
2210         }
2211         RET_ONERROR( mywritestr(f, "}\n") )
2212     }
2213 
2214     RET_ONERROR( mywritestr(f, "\n\n") )
2215 
2216     if (languageFlag & JAVA_SOURCE) {
2217         // "callbacks"
2218         RET_ONERROR( mywritestr(f, "class ") )
2219         RET_ONERROR( mywritestr(f, getRenderCallbackClass()) )
2220         RET_ONERROR( mywritestr(f, " extends ") )
2221         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2222         RET_ONERROR( mywritestr(f, "RenderCallback {}\n") )
2223 
2224         RET_ONERROR( mywritestr(f, "class ") )
2225         RET_ONERROR( mywritestr(f, getTreeRenderCallbackClass()) )
2226         RET_ONERROR( mywritestr(f, " extends ") )
2227         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2228         RET_ONERROR( mywritestr(f, "TreeRenderCallback {}\n") )
2229 
2230         RET_ONERROR( mywritestr(f, "class ") )
2231         RET_ONERROR( mywritestr(f, getDoWithDataCallbackClass()) )
2232         RET_ONERROR( mywritestr(f, " extends ") )
2233         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2234         RET_ONERROR( mywritestr(f, "DoWithDataCallback {};\n") )
2235 
2236         RET_ONERROR( mywritestr(f, "class ") )
2237         RET_ONERROR( mywritestr(f, getTreeDoWithDataCallbackClass()) )
2238         RET_ONERROR( mywritestr(f, " extends ") )
2239         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2240         RET_ONERROR( mywritestr(f, "TreeDoWithDataCallback {};\n") )
2241 
2242         if (getType() == VRML_INDEXED_FACE_SET) {
2243             RET_ONERROR( mywritestr(f, "class ") )
2244             RET_ONERROR( mywritestr(f, getCreateNormalsCallbackClass()) )
2245             RET_ONERROR( mywritestr(f, " extends ") )
2246             RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2247             RET_ONERROR( mywritestr(f, "CreateNormalsCallback {}\n") )
2248         }
2249 
2250          RET_ONERROR( mywritestr(f, "class ") )
2251          RET_ONERROR( mywritestr(f, getProcessEventCallbackClass()) )
2252          RET_ONERROR( mywritestr(f, " extends ") )
2253          RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2254          RET_ONERROR( mywritestr(f, "ProcessEventCallback {};\n") )
2255 
2256          RET_ONERROR( mywritestr(f, "\n") )
2257 
2258         bool writeOut = true;
2259         if (getType() == VRML_SCRIPT) {
2260             if (m_scene->getScriptTypeWritten())
2261                 writeOut = false;
2262             m_scene->setScriptTypeWritten();
2263         }
2264         if (writeOut) {
2265              // type
2266              RET_ONERROR( mywritestr(f, "class ") )
2267              RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2268              RET_ONERROR( mywritestr(f, getName(true)) )
2269              RET_ONERROR( mywritestr(f, "Type") )
2270              RET_ONERROR( mywritef(f, " {\n    static final int type = %d;\n}\n\n",
2271                                    getType()) )
2272         }
2273     }
2274     return 0;
2275 }
2276 
2277 int
writeCDeclarationEventIn(int f,int i,int languageFlag)2278 Proto::writeCDeclarationEventIn(int f, int i, int languageFlag)
2279 {
2280     bool x3d = true;
2281 
2282     EventIn *eventIn = getEventIn(i);
2283     if (eventIn->getFlags() & (FF_VRML_ONLY | FF_NEVER | FF_X3DOM_ONLY))
2284         return 0;
2285     if (eventIn->getExposedField() != NULL)
2286         return 0;
2287     const char *name = eventIn->getName(x3d);
2288     RET_ONERROR( mywritestr(f, "    ") )
2289     RET_ONERROR( mywritestr(f, getTypeC(eventIn->getType(), languageFlag)) )
2290     if (isArrayInC(eventIn->getType())) {
2291         if (languageFlag & JAVA_SOURCE) {
2292             if ((eventIn->getType() != SFNODE) &&
2293                 (eventIn->getType() != MFNODE))
2294                 RET_ONERROR( mywritestr(f, "[]") )
2295         } else
2296             RET_ONERROR( mywritestr(f, "*") )
2297     }
2298     RET_ONERROR( mywritestr(f, " ") )
2299     RET_ONERROR( mywritestr(f, name) )
2300     RET_ONERROR( mywritestr(f, ";\n") )
2301     if (isArrayInC(eventIn->getType()) && (languageFlag &
2302                                            (C_SOURCE | CC_SOURCE))) {
2303         RET_ONERROR( mywritestr(f, "    int ") )
2304         RET_ONERROR( mywritestr(f, name) )
2305         RET_ONERROR( mywritestr(f, "_length") )
2306         RET_ONERROR( mywritestr(f, ";\n") )
2307     }
2308     return(0);
2309 }
2310 
2311 int
writeCDeclarationEventOut(int f,int i,int languageFlag)2312 Proto::writeCDeclarationEventOut(int f, int i, int languageFlag)
2313 {
2314     bool x3d = true;
2315 
2316     EventOut *eventOut = getEventOut(i);
2317     if (eventOut->getFlags() & (FF_VRML_ONLY | FF_NEVER | FF_X3DOM_ONLY))
2318         return 0;
2319     if (eventOut->getExposedField() != NULL)
2320         return 0;
2321     const char *name = eventOut->getName(x3d);
2322     RET_ONERROR( mywritestr(f, "    ") )
2323     RET_ONERROR( mywritestr(f, getTypeC(eventOut->getType(), languageFlag)) )
2324     if (isArrayInC(eventOut->getType())) {
2325         if (languageFlag & JAVA_SOURCE) {
2326             if ((eventOut->getType() != SFNODE) &&
2327                 (eventOut->getType() != MFNODE))
2328                 RET_ONERROR( mywritestr(f, "[]") )
2329         } else
2330             RET_ONERROR( mywritestr(f, "*") )
2331     }
2332     RET_ONERROR( mywritestr(f, " ") )
2333     RET_ONERROR( mywritestr(f, name) )
2334     RET_ONERROR( mywritestr(f, ";\n") )
2335     if (isArrayInC(eventOut->getType()) && (languageFlag &
2336                                             (C_SOURCE | CC_SOURCE))) {
2337         RET_ONERROR( mywritestr(f, "    int ") )
2338         RET_ONERROR( mywritestr(f, name) )
2339         RET_ONERROR( mywritestr(f, "_length") )
2340         RET_ONERROR( mywritestr(f, ";\n") )
2341     }
2342     return(0);
2343 }
2344 
2345 int
writeCDeclarationField(int f,int i,int languageFlag)2346 Proto::writeCDeclarationField(int f, int i, int languageFlag)
2347 {
2348     bool x3d = true;
2349 
2350     Field *field = getField(i);
2351     if (field->getFlags() & (FF_VRML_ONLY | FF_NEVER | FF_X3DOM_ONLY))
2352         return 0;
2353     const char *name = field->getName(x3d);
2354     RET_ONERROR( mywritestr(f, "    ") )
2355     RET_ONERROR( mywritestr(f, getTypeC(field->getType(), languageFlag)) )
2356     if (isArrayInC(field->getType())) {
2357         if (languageFlag & JAVA_SOURCE) {
2358             if ((field->getType() != SFNODE) && (field->getType() != MFNODE))
2359                 RET_ONERROR( mywritestr(f, "[]") )
2360         } else
2361             RET_ONERROR( mywritestr(f, "*") )
2362     }
2363     RET_ONERROR( mywritestr(f, " ") )
2364     RET_ONERROR( mywritestr(f, name) )
2365     RET_ONERROR( mywritestr(f, ";\n") )
2366     if (isArrayInC(field->getType()) && (languageFlag &
2367                                          (C_SOURCE | CC_SOURCE))) {
2368         RET_ONERROR( mywritestr(f, "    int ") )
2369         RET_ONERROR( mywritestr(f, name) )
2370         RET_ONERROR( mywritestr(f, "_length") )
2371         RET_ONERROR( mywritestr(f, ";\n") )
2372     }
2373     return(0);
2374 }
2375 
2376 int
writeCConstructorField(int f,int i,int languageFlag)2377 Proto::writeCConstructorField(int f, int i, int languageFlag)
2378 {
2379     bool x3d = true;
2380 
2381     Field *field = getField(i);
2382     if (field->getFlags() & (FF_VRML_ONLY | FF_NEVER | FF_X3DOM_ONLY))
2383         return 0;
2384     FieldValue *value = field->getDefault(x3d);
2385     const char *name = field->getName(x3d);
2386     if (languageFlag & (CC_SOURCE | JAVA_SOURCE))
2387         RET_ONERROR( mywritestr(f, "    ") )
2388     RET_ONERROR( mywritestr(f, "    ") )
2389     if (languageFlag & C_SOURCE)
2390         RET_ONERROR( mywritestr(f, "self->") )
2391     RET_ONERROR( mywritestr(f, name) )
2392     RET_ONERROR( mywritestr(f, " = ") )
2393     RET_ONERROR( mywritestr(f, value->getDefaultC(languageFlag)) )
2394     RET_ONERROR( mywritestr(f, ";\n") )
2395     if (value->isArrayInC() && (languageFlag & (C_SOURCE | CC_SOURCE))) {
2396         if (languageFlag & (CC_SOURCE | JAVA_SOURCE))
2397             RET_ONERROR( mywritestr(f, "    ") )
2398         RET_ONERROR( mywritestr(f, "    ") )
2399         if (languageFlag & C_SOURCE)
2400             RET_ONERROR( mywritestr(f, "self->") )
2401         RET_ONERROR( mywritestr(f, name) )
2402         RET_ONERROR( mywritestr(f, "_length") )
2403         RET_ONERROR( mywritestr(f, " = 0;\n") )
2404     }
2405     return(0);
2406 }
2407 
2408 int
writeCCallTreeField(int f,int i,const char * treeFunctionName,int languageFlag,const char * functionName,bool useObject)2409 Proto::writeCCallTreeField(int f, int i, const char *treeFunctionName,
2410                            int languageFlag, const char *functionName,
2411                            bool useObject)
2412 {
2413     bool x3d = true;
2414 
2415     Field *field = getField(i);
2416     if ((field->getType() != SFNODE) && (field->getType() != MFNODE))
2417         return 0;
2418     if (field->getFlags() & (FF_VRML_ONLY | FF_NEVER | FF_X3DOM_ONLY))
2419         return 0;
2420     FieldValue *value = field->getDefault(x3d);
2421     const char *name = field->getName(x3d);
2422     MyString fieldName = "";
2423     fieldName += name;
2424     if (value->isArrayInC()) {
2425         if (languageFlag & CC_SOURCE)
2426             RET_ONERROR( mywritestr(f, "    ") )
2427         RET_ONERROR( mywritestr(f, "    ") )
2428         RET_ONERROR( mywritestr(f, "    ") )
2429         RET_ONERROR( mywritestr(f, "if (") )
2430         if (languageFlag & JAVA_SOURCE)
2431             RET_ONERROR( mywritestr(f, "(") )
2432         if (languageFlag & C_SOURCE) {
2433             RET_ONERROR( mywritestr(f, "((struct ") )
2434             RET_ONERROR( mywritestr(f, getClassName()) )
2435             RET_ONERROR( mywritestr(f, "*)self)->") )
2436         }
2437         RET_ONERROR( mywritestr(f, fieldName) )
2438         if (languageFlag & JAVA_SOURCE)
2439             RET_ONERROR( mywritestr(f, " != null") )
2440         if (languageFlag & JAVA_SOURCE) {
2441             if (functionName != NULL) {
2442                 RET_ONERROR( mywritestr(f, ") && (") )
2443                 RET_ONERROR( mywritestr(f, getClassName()) )
2444                 RET_ONERROR( mywritestr(f, ".") )
2445                 RET_ONERROR( mywritestr(f, functionName) )
2446                 RET_ONERROR( mywritestr(f, getName(true)) )
2447                 RET_ONERROR( mywritestr(f, " == null)") )
2448            }
2449         }
2450         RET_ONERROR( mywritestr(f, ")\n") )
2451         if (languageFlag & CC_SOURCE)
2452             RET_ONERROR( mywritestr(f, "    ") )
2453         RET_ONERROR( mywritestr(f, "    ") )
2454         RET_ONERROR( mywritestr(f, "        ") )
2455         RET_ONERROR( mywritestr(f, "for (") )
2456         if (languageFlag & JAVA_SOURCE)
2457             RET_ONERROR( mywritestr(f, "int ") )
2458         RET_ONERROR( mywritestr(f, "i = 0; i < ") )
2459         if (languageFlag & C_SOURCE) {
2460             RET_ONERROR( mywritestr(f, "((struct ") )
2461             RET_ONERROR( mywritestr(f, getClassName()) )
2462             RET_ONERROR( mywritestr(f, "*)self)->") )
2463         }
2464         RET_ONERROR( mywritestr(f, name) )
2465         if (languageFlag & JAVA_SOURCE)
2466             RET_ONERROR( mywritestr(f, ".") )
2467         else
2468             RET_ONERROR( mywritestr(f, "_") )
2469         RET_ONERROR( mywritestr(f, "length; i++)\n") )
2470     }
2471     if (value->isArrayInC())
2472         fieldName += "[i]";
2473     if (value->isArrayInC())
2474         RET_ONERROR( mywritestr(f, "        ") )
2475     if (languageFlag & CC_SOURCE)
2476         RET_ONERROR( mywritestr(f, "    ") )
2477     RET_ONERROR( mywritestr(f, "    ") )
2478     RET_ONERROR( mywritestr(f, "    ") )
2479     RET_ONERROR( mywritestr(f, "if (") )
2480     if (languageFlag & C_SOURCE) {
2481         RET_ONERROR( mywritestr(f, "((struct ") )
2482         RET_ONERROR( mywritestr(f, getClassName()) )
2483         RET_ONERROR( mywritestr(f, "*)self)->") )
2484     }
2485     RET_ONERROR( mywritestr(f, fieldName) )
2486     if (languageFlag & JAVA_SOURCE)
2487         RET_ONERROR( mywritestr(f, " != null") )
2488     RET_ONERROR( mywritestr(f, ")\n") )
2489     if (value->isArrayInC())
2490         RET_ONERROR( mywritestr(f, "        ") )
2491     RET_ONERROR( mywritestr(f, "    ") )
2492     if (languageFlag & CC_SOURCE)
2493         RET_ONERROR( mywritestr(f, "    ") )
2494     RET_ONERROR( mywritestr(f, "    ") )
2495     RET_ONERROR( mywritestr(f, "    ") )
2496     if (languageFlag & C_SOURCE) {
2497         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2498         RET_ONERROR( mywritestr(f, treeFunctionName) )
2499         RET_ONERROR( mywritestr(f, "(((struct ") )
2500         RET_ONERROR( mywritestr(f, getClassName()) )
2501         RET_ONERROR( mywritestr(f, "*)self)->") )
2502         RET_ONERROR( mywritestr(f, fieldName) )
2503         RET_ONERROR( mywritestr(f, ", dataptr);\n") )
2504     } else if (languageFlag & CC_SOURCE) {
2505         RET_ONERROR( mywritestr(f, fieldName) )
2506         RET_ONERROR( mywritestr(f, "->") )
2507         MyString lowFirst = "";
2508         lowFirst += tolower(treeFunctionName[0]);
2509         RET_ONERROR( mywritestr(f, lowFirst) )
2510         RET_ONERROR( mywritestr(f, treeFunctionName + 1) )
2511         RET_ONERROR( mywritestr(f, "(dataptr);\n") )
2512     } else if (languageFlag & JAVA_SOURCE) {
2513         RET_ONERROR( mywritestr(f, fieldName) )
2514         RET_ONERROR( mywritestr(f, ".") )
2515         MyString lowFirst = "";
2516         lowFirst += tolower(treeFunctionName[0]);
2517         RET_ONERROR( mywritestr(f, lowFirst) )
2518         RET_ONERROR( mywritestr(f, treeFunctionName + 1) )
2519         RET_ONERROR( mywritestr(f, "(dataptr") )
2520         if (useObject)
2521             RET_ONERROR( mywritestr(f, ", object") )
2522         RET_ONERROR( mywritestr(f, ");\n") )
2523     }
2524     return(0);
2525 }
2526 
2527 Element *
getElement(int elementType,int index) const2528 Proto::getElement(int elementType, int index) const
2529 {
2530      if (elementType == EL_EVENT_IN)
2531          return getEventIn(index);
2532      if (elementType == EL_EVENT_OUT)
2533          return getEventOut(index);
2534      if (elementType == EL_EXPOSED_FIELD)
2535          return getExposedField(index);
2536      return getField(index);
2537 }
2538 
2539 bool
showFields(bool x3d)2540 Proto::showFields(bool x3d)
2541 {
2542     if (m_showFieldsInit == false) {
2543         m_showFieldsInit = true;
2544         int xfNodes = 0;
2545         for (int i = 0; i < getNumFields(); i++)
2546             if ((getField(i)->getType() == SFNODE) ||
2547                 (getField(i)->getType() == MFNODE))
2548                 if (i != metadata_Field())
2549                     if (m_scene->isValidElement(getField(i), x3d))
2550                         xfNodes++;
2551         m_showFields = false;
2552         if (xfNodes > 1)
2553             m_showFields = true;
2554     }
2555     return m_showFields;
2556 }
2557 
2558 
2559 int
writeCExtraFields(int f,int languageFlag)2560 Proto::writeCExtraFields(int f, int languageFlag)
2561 {
2562     if ((languageFlag & C_SOURCE) | (languageFlag & CC_SOURCE)) {
2563             RET_ONERROR( mywritestr(f, "    void* extra_data;\n") )
2564     } else if ((languageFlag & JAVA_SOURCE)) {
2565             RET_ONERROR( mywritestr(f, "    Object extra_data;\n") )
2566     }
2567     if ((getType() == VRML_INDEXED_FACE_SET) ||
2568         (getType() == VRML_INDEXED_LINE_SET) ||
2569         (getType() == X3D_LINE_SET) ||
2570         (getType() == VRML_POINT_SET)) {
2571         RET_ONERROR( mywritestr(f, "    int glName_number;\n") )
2572     }
2573     if (getType() == VRML_TRANSFORM) {
2574         RET_ONERROR( mywritestr(f, "    int num_route_source;\n") )
2575         if ((languageFlag & C_SOURCE) | (languageFlag & CC_SOURCE)) {
2576             RET_ONERROR( mywritef(f, "    %sNode **route_sources;\n",
2577                                      TheApp->getCPrefix()) )
2578         } else if ((languageFlag & JAVA_SOURCE)) {
2579             RET_ONERROR( mywritef(f, "    %sNode route_sources[];\n",
2580                                      TheApp->getCPrefix()) )
2581         }
2582     }
2583     return 0;
2584 }
2585 
2586 // collect array of dynamic field's, eventIn's and eventOut's
2587 void
buildInterfaceData(bool protoFlag)2588 Proto::buildInterfaceData(bool protoFlag)
2589 {
2590     bool x3d = m_scene->isX3d();
2591     m_interface.resize(0);
2592     Proto* proto = this;
2593     if (proto == NULL)
2594         return;
2595     int fieldFlags = FF_STATIC;
2596     for (int i = 0; i < proto->getNumFields(); i++)
2597         if (!(proto->getField(i)->getFlags() & fieldFlags))
2598             if (proto->getField(i)->getExposedField() == NULL)
2599                 m_interface.append(new InterfaceData(EL_FIELD, i));
2600     // exposedFields are always FF_HIDDEN
2601     if (protoFlag)
2602         for (int i = 1; i < proto->getNumExposedFields(); i++)
2603             if (!(proto->getExposedField(i)->getFlags() & fieldFlags))
2604                 m_interface.append(new InterfaceData(EL_EXPOSED_FIELD, i));
2605     fieldFlags = 0;
2606     if (!protoFlag)
2607         fieldFlags = FF_HIDDEN;
2608 //        fieldFlags = FF_HIDDEN | FF_STATIC;
2609     for (int i = 0; i < proto->getNumEventOuts(); i++) {
2610         // ignore Exposedfields (eg. "url")
2611         bool isExposedField = false;
2612         for (long j = 0; j < proto->m_exposedFields.size(); j++) {
2613             MyString exposedName = "";
2614             exposedName += mystrdup(proto->getExposedField(j)->getName(x3d));
2615             exposedName += "_changed";
2616             if (strcmp(proto->getEventOut(i)->getName(x3d), exposedName) == 0)
2617                isExposedField = true;
2618         }
2619         if (isExposedField)
2620             continue;
2621         if (!(proto->getEventOut(i)->getFlags() & fieldFlags))
2622             m_interface.append(new InterfaceData(EL_EVENT_OUT, i));
2623     }
2624     for (int i = 0; i < proto->getNumEventIns(); i++) {
2625         // ignore Exposedfields (eg. "url")
2626         bool isExposedField = false;
2627         for (long j = 0; j < proto->m_exposedFields.size(); j++) {
2628             MyString exposedName = "";
2629             exposedName += "set_";
2630             exposedName += proto->getExposedField(j)->getName(x3d);
2631             if (strcmp(proto->getEventIn(i)->getName(x3d), exposedName) == 0)
2632                isExposedField = true;
2633         }
2634         if (isExposedField)
2635             continue;
2636         if (!(proto->getEventIn(i)->getFlags() & fieldFlags))
2637             m_interface.append(new InterfaceData(EL_EVENT_IN, i));
2638     }
2639 }
2640 
2641 bool
matchNodeClass(int childType) const2642 Proto::matchNodeClass(int childType) const
2643 {
2644     return ::matchNodeClass(getNodeClass(), childType);
2645 }
2646 
2647 class FiledesAndIndent {
2648 public:
2649     int filedes;
2650     int indent;
2651 };
2652 
writeRoutesPerNode(Node * node,void * data)2653 static bool writeRoutesPerNode(Node *node, void *data)
2654 {
2655     FiledesAndIndent *fid = (FiledesAndIndent *)data;
2656     node->setFlag(NODE_FLAG_TOUCHED);
2657     indentf(fid->filedes, fid->indent);
2658     node->writeRoutes(fid->filedes, 0);
2659     return true;
2660 }
2661 
2662 int
write(int filedes,int indent,bool avoidUse)2663 NodePROTO::write(int filedes, int indent, bool avoidUse)
2664 {
2665     return Node::write(filedes, indent);
2666 }
2667 
2668 int
writeXml(int filedes,int indent,int containerField,bool avoidUse)2669 NodePROTO::writeXml(int filedes, int indent, int containerField, bool avoidUse)
2670 {
2671 #if HAVE_NO_PROTOS_X3DOM
2672     bool x3d = m_scene->isX3d();
2673 
2674     if ((m_scene->getWriteFlags() & X3DOM) && (getProto()->getNumNodes() > 0)) {
2675         RET_ONERROR( getProto()->getNode(0)->writeXml(filedes, indent,
2676                                                       containerField, true) )
2677         // write rest of PROTO hidden in a Switch
2678         RET_ONERROR( indentf(filedes, indent) )
2679         RET_ONERROR( mywritestr(filedes, "<Switch whichChoice='"))
2680         RET_ONERROR( mywritef(filedes, "%d'>\n", getProto()->getNumNodes()))
2681         for (int k = 1; k < getProto()->getNumNodes(); k++)
2682             RET_ONERROR( getProto()->getNode(k)->writeXml(filedes,
2683                              TheApp->GetIndent() + indent, containerField, true)
2684                        )
2685         RET_ONERROR( indentf(filedes, indent) )
2686         RET_ONERROR( mywritestr(filedes, "</Switch>\n") )
2687         Node *node = this;
2688         Proto *fromProto = node->getProto();
2689         for (int j = 0; j < fromProto->getNumEventOuts(); j++)
2690             for (int n = 0; n < fromProto->getEventOut(j)->getNumIs(); n++)
2691                 if (fromProto->getEventOut(j)->getIsElementType(n) ==
2692                     EL_EVENT_OUT) {
2693                     const char *srcName =
2694                         fromProto->getEventOut(j)->getIsNode(n)->getName();
2695                     int field = fromProto->getEventOut(j)->getIsField(n);
2696                     EventOut *srcEvent = fromProto->getEventOut(j)->
2697                                              getIsNode(n)->
2698                                              getProto()->getEventOut(field);
2699 
2700                     SocketList::Iterator *i = NULL;
2701 
2702                     for (i = node->getOutput(j).first(); i != NULL;
2703                          i = i->next()) {
2704                          Node *dstNode = i->item().getNode();
2705                          int dstEventOut = i->item().getField();
2706                          EventOut *dstEvent =
2707                              dstNode->getProto()->getEventOut(dstEventOut);
2708                         indentf(filedes, 3 * TheApp->GetIndent());
2709                         RET_ONERROR( mywritef(filedes,
2710                             "<ROUTE fromNode='%s' fromField='%s' ",
2711                             srcName, (const char *)srcEvent->getName(true)) )
2712                         RET_ONERROR( mywritef(filedes,
2713                             "toNode='%s' toField='%s'></ROUTE>\n",
2714                             (const char *)dstNode->getName(),
2715                             (const char *)dstEvent->getName(true)) )
2716                     }
2717                 }
2718 /*
2719         for (int j = 0; j < fromProto->getNumEventIns(); j++)
2720             for (int n = 0; n < fromProto->getEventIn(j)->getNumIs(); n++)
2721                 if (fromProto->getEventOut(j)->getIsElementType(n) ==
2722                     EL_EVENT_IN) {
2723                     const char *srcName =
2724                         fromProto->getEventIn(j)->getIsNode(n)->getName();
2725                     int field = fromProto->getEventIn(j)->getIsField(n);
2726                     EventIn *srcEvent = fromProto->getEventIn(j)->
2727                                             getIsNode(n)->
2728                                             getProto()->getEventIn(field);
2729 
2730                     SocketList::Iterator *i = NULL;
2731 
2732                     for (i = node->getInput(j).first(); i != NULL;
2733                          i = i->next()) {
2734                          Node *dstNode = i->item().getNode();
2735                          int dstEventOut = i->item().getField();
2736                          EventOut *dstEvent =
2737                              dstNode->getProto()->getEventOut(dstEventOut);
2738                         indentf(filedes, 3 * TheApp->GetIndent());
2739                         RET_ONERROR( mywritef(filedes,
2740                             "<ROUTE fromNode='%s' fromField='%s' ",
2741                             srcName, (const char *)srcEvent->getName(true)) )
2742                         RET_ONERROR( mywritef(filedes,
2743                             "toNode='%s' toField='%s'></ROUTE>\n",
2744                             (const char *)dstNode->getName(),
2745                             (const char *)dstEvent->getName(true)) )
2746                     }
2747                 }
2748 */
2749 
2750         for (int i = 0; i < m_numEventIns; i++) {
2751             SocketList::Iterator *j;
2752             for (j = m_inputs[i].first(); j != NULL; j = j->next()) {
2753                 Node *src = j->item().getNode();
2754                 int field = j->item().getField();
2755                 if ((m_scene->getWriteFlags() & X3DOM) &&
2756                     (j->item().getNode()->getType() == VRML_SCRIPT)) {
2757                     NodeScript *script = (NodeScript *)j->item().getNode();
2758                     bool flag = false;
2759                     for (int i = 0; i < script->url()->getSize(); i++)
2760                         if (isX3domscript(script->url()->getValue(i)))
2761                             flag = true;
2762                     if (flag)
2763                         continue;
2764 
2765                 }
2766                 if (m_scene->isPureVRML() &&
2767                     (matchNodeClass(PARAMETRIC_GEOMETRY_NODE) ||
2768                      src->matchNodeClass(PARAMETRIC_GEOMETRY_NODE)))
2769                     continue;
2770                 MyString eventInName = getProto()->getEventIn(i)->getName(x3d);
2771                 EventIn *ev = NULL;
2772                 int ev1 = getProto()->lookupIsEventIn(eventInName);
2773                 Node *dst = NULL;
2774                 if (ev1 == -1) {
2775                     int ev2 = getProto()->lookupIsExposedField(eventInName);
2776                     if (ev2 > -1) {
2777                         dst = getProto()->getExposedField(ev2)->getIsNode(ev2);
2778                         int ev3 = getProto()->getExposedField(ev2)->getIsField(ev2);
2779                         if (dst)
2780                             ev = dst->getProto()->getEventIn(ev3);
2781                     }
2782                 } else
2783                     ev = getProto()->getEventIn(ev1);
2784 
2785                 if (ev == NULL || dst == NULL)
2786                     continue;
2787                 MyString routeString = m_scene->createRouteString(
2788                       src->getName(),
2789                       src->getProto()->getEventOut(field)->getName(x3d),
2790                       dst->getName(),
2791                       ev->getName(x3d));
2792                       m_scene->addRouteString(routeString);
2793             }
2794         }
2795 
2796         FiledesAndIndent fid;
2797         fid.filedes = filedes;
2798         fid.indent = indent;
2799         for (int i = 0; i < getProto()->getNumNodes(); i++)
2800             getProto()->getNode(i)->doWithBranch(writeRoutesPerNode, &fid);
2801         return 0;
2802     }
2803 #endif
2804     return Node::writeXml(filedes, indent);
2805 }
2806 
appendToIndexedNodes(Node * node)2807 void NodePROTO::appendToIndexedNodes(Node *node)
2808 {
2809     if (node != NULL)
2810         m_indexedNodes.append(node);
2811 }
2812 
2813 static MyArray<RouteInfo> routeInfo;
2814 
fixEventOuts(Node * node,void * data)2815 static bool fixEventOuts(Node *node, void *data)
2816 {
2817     Node *compareNode = (Node *)data;
2818     if (compareNode == NULL)
2819         return true;
2820     if (node == NULL)
2821         return true;
2822     if ((node != compareNode) &&
2823         compareNode->getId() == node->getId()) {
2824         Proto *proto = node->getProto();
2825         for (int j = 0; j < proto->getNumEventIns(); j++) {
2826             EventIn *evIn = proto->getEventIn(j);
2827             int eventIn = j;
2828             SocketList::Iterator *i;
2829             int counter = 0;
2830             int listLength = node->getInput(j).size();
2831             static Node *sNode = NULL;
2832             static int sField = -1;
2833             for (i = node->getInput(j).first(); i != NULL;i = i->next()) {
2834                 // list increases in loop
2835                 if (counter++ > listLength)
2836                     break;
2837                 RouteSocket s = i->item();
2838                 if ((s.getNode() != sNode) || (sField != s.getField())) {
2839                     node->getScene()->addRoute(s.getNode(), s.getField(),
2840                                                compareNode, j);
2841                     routeInfo.append(RouteInfo(s.getNode(), s.getField(),
2842                                                compareNode, j));
2843                 }
2844             }
2845         }
2846     }
2847     return true;
2848 }
2849 
buildSetNodePROTO(Node * node,void * data)2850 static bool buildSetNodePROTO(Node *node, void *data)
2851 {
2852     NodePROTO *self = (NodePROTO *)data;
2853     if (self == NULL)
2854         return true;
2855     node->setNodePROTO(self);
2856     return true;
2857 }
2858 
buildNodeIndexInBranch(Node * node,void * data)2859 static bool buildNodeIndexInBranch(Node *node, void *data)
2860 {
2861     NodePROTO *self = (NodePROTO *)data;
2862     if (self == NULL)
2863         return true;
2864 
2865     for (int i = 0; i < self->getProto()->getNumNodes(); i++)
2866         self->getProto()->getNode(i)->doWithBranch(fixEventOuts, node, false);
2867 
2868 //    if (TheApp->isCExporting())
2869 //        node->setVariableName(node->getScene()->generateVariableName(node));
2870 
2871     self->appendToIndexedNodes(node);
2872     node->ref();
2873     node->setNodePROTO(self);
2874     return true;
2875 }
2876 
getIds(Node * node,void * data)2877 static bool getIds(Node *node, void *data)
2878 {
2879     MyArray<long> *ids = (MyArray<long> *)data;
2880     if (node)
2881         (*ids).append(node->getId());
2882     return true;
2883 }
2884 
2885 static int idCounter = 0;
2886 
setIds(Node * node,void * data)2887 static bool setIds(Node *node, void *data)
2888 {
2889     MyArray<long> *ids = (MyArray<long> *)data;
2890     if (node) {
2891         node->setId((*ids)[idCounter++]);
2892     }
2893     return true;
2894 }
2895 
getNames(Node * node,void * data)2896 static bool getNames(Node *node, void *data)
2897 {
2898     MyArray<const char *> *names = (MyArray<const char *> *)data;
2899     if (node)
2900         (*names).append(node->getVariableName());
2901     return true;
2902 }
2903 
2904 static int nameCounter = 0;
2905 
setNames(Node * node,void * data)2906 static bool setNames(Node *node, void *data)
2907 {
2908     MyArray<const char *> *names = (MyArray<const char *> *)data;
2909     if (node) {
2910         node->setVariableName((*names)[nameCounter++]);
2911     }
2912     return true;
2913 }
2914 
2915 void
createPROTO(bool bcopy)2916 NodePROTO::createPROTO(bool bcopy)
2917 {
2918     bool x3d = m_scene->isX3d();
2919 
2920     m_isHumanoid = false;
2921     if (bcopy) {
2922         m_nodes.resize(0);
2923         #pragma parallel for
2924         for (int i = 0; i < m_proto->getNumNodes(); i++) {
2925             if (m_proto->getNode(i)) {
2926                 long id = m_proto->getNode(i)->getId();
2927                 idCounter = 0;
2928                 MyArray<long> ids;
2929                 m_proto->getNode(i)->doWithBranch(getIds, &ids, false);
2930 
2931                 const char *name = m_proto->getNode(i)->getVariableName();
2932                 nameCounter = 0;
2933                 MyArray<const char *> names;
2934                 m_proto->getNode(i)->doWithBranch(getNames, &names, false);
2935 
2936                 m_proto->getNode(i)->doWithBranch(buildSetNodePROTO, this,
2937                                                   false);
2938                 m_nodes[i] = m_proto->getNode(i)->copy();
2939                 m_nodes[i]->setId(id);
2940                 m_nodes[i]->doWithBranch(setIds, &ids, false);
2941                 m_nodes[i]->setVariableName(name);
2942                 m_nodes[i]->doWithBranch(setNames, &names, false);
2943                 m_proto->getNode(i)->copyOutputsTo(m_nodes[i]);
2944                 m_proto->getNode(i)->copyInputsTo(m_nodes[i]);
2945                 m_proto->getNode(i)->copyChildrenTo(m_nodes[i], true);
2946             }
2947         }
2948         #pragma parallel for
2949         for (int i = 0; i < routeInfo.size(); i++)
2950             m_scene->deleteRoute(routeInfo[i].src, routeInfo[i].eventOut,
2951                                  routeInfo[i].dest, routeInfo[i].eventIn);
2952         routeInfo.resize(0);
2953         m_indexedNodes.resize(0);
2954         #pragma parallel for
2955         for (int i = 0; i < m_proto->getNumNodes(); i++)
2956             m_nodes[i]->doWithBranch(buildNodeIndexInBranch, this, false);
2957         #pragma parallel for
2958         for (long i = 0; i < m_indexedNodes.size(); i++)
2959             if (m_indexedNodes[i])
2960                m_indexedNodes[i]->setScene(m_scene);
2961     }
2962     #pragma parallel for
2963     for (int i = 0; i < m_proto->getNumExposedFields(); i++) {
2964         ExposedField *field = m_proto->getExposedField(i);
2965         if (field && field->getFlags() & FF_IS)
2966             for (int j = 0; j < field->getNumIs(); j++) {
2967                 Node *isNode = field->getIsNode(j);
2968                 FieldValue *value = field->getValue()->copy();
2969                 if (value && isNode) {
2970                     int isField = field->getIsField(j);
2971                     if (isField < 0)
2972                         continue;
2973                     isNode->setField(isField, value);
2974                 }
2975             }
2976     }
2977     #pragma parallel for
2978     for (int i = 0; i < m_proto->getNumFields(); i++) {
2979         Field *field = m_proto->getField(i);
2980         if (field && field->getFlags() & FF_IS)
2981             for (int j = 0; j < field->getNumIs(); j++) {
2982                 Node *isNode = field->getIsNode(j);
2983                 FieldValue *value = field->getDefault(x3d)->copy();
2984                 if (value && isNode) {
2985                     int isField = field->getIsField(j);
2986                     isNode->setField(isField, value);
2987                 }
2988             }
2989     }
2990     m_jointRotationField = -1;
2991     bool maybeJoint = false;
2992     if (strcmp(m_proto->getName(x3d), "Joint") == 0)
2993         if (m_nodes.size() > 0)
2994             if (m_nodes[0] != NULL)
2995                 if (m_nodes[0]->getType() == VRML_TRANSFORM)
2996                     maybeJoint = true;
2997     if (strcmp(m_proto->getName(x3d), "Humanoid") == 0)
2998         if (m_nodes.size() > 0)
2999             if (m_nodes[0] != NULL)
3000                 if (m_nodes[0]->getType() == VRML_TRANSFORM)
3001                     m_isHumanoid = true;
3002     #pragma parallel for
3003     for (int i = 0; i < m_proto->getNumFields(); i++) {
3004         Field *field = m_proto->getField(i);
3005         if (field && field->getFlags() & FF_IS)
3006             for (int j = 0; j < field->getNumIs(); j++) {
3007                 Node *isNode = field->getIsNode(j);
3008                 FieldValue *value = field->getDefault(x3d);
3009                 if (value && isNode) {
3010                     value = value->copy();
3011                     int isField = field->getIsField(j);
3012                     isNode->setField(isField, value);
3013                 }
3014             }
3015         // search for Joint.rotation field for H-Anim handle
3016         if (maybeJoint)
3017             if (strcmp(field->getName(false), "rotation") == 0)
3018                 if (field && field->getType() == SFROTATION) {
3019                     m_jointRotationField = i;
3020                     m_scene->setHasJoints();
3021                 }
3022     }
3023 }
3024 
NodePROTO(Scene * scene,Proto * proto)3025 NodePROTO::NodePROTO(Scene *scene, Proto *proto)
3026   : DynamicFieldsNode(scene, proto)
3027 {
3028     createPROTO();
3029     handleIs();
3030 }
3031 
3032 bool
isEXTERNPROTO(void)3033 NodePROTO::isEXTERNPROTO(void)
3034 {
3035     if (isPROTO())
3036         if (m_proto->isExternProto())
3037             return true;
3038     return false;
3039 }
3040 
updateNode(Node * node,void * data)3041 static bool updateNode(Node *node, void *data)
3042 {
3043     node->update();
3044     return true;
3045 }
3046 
3047 
3048 void
update()3049 NodePROTO::update()
3050 {
3051     for (int i = 0; i < m_proto->getNumNodes(); i++) {
3052         if (m_proto->getNode(i) != NULL)
3053             m_proto->getNode(i)->doWithBranch(updateNode, NULL, true, false,
3054                                               false, false);
3055     }
3056     Node::update();
3057 }
3058 
reInitNode(Node * node,void * data)3059 static bool reInitNode(Node *node, void *data)
3060 {
3061     node->reInit();
3062     return true;
3063 }
3064 
3065 
3066 void
reInit(void)3067 NodePROTO::reInit(void)
3068 {
3069     bool x3d = m_scene->isX3d();
3070     for (int i = 0; i < m_proto->getNumNodes(); i++) {
3071         if (m_proto->getNode(i) != NULL)
3072             m_proto->getNode(i)->doWithBranch(reInitNode, NULL);
3073     }
3074     this->updateDynamicFields();
3075     for (int i = 0; i < m_numFields; i++) {
3076          FieldValue *fieldValue = getField(i);
3077          if (fieldValue == NULL)
3078              continue;
3079          if (fieldValue->isDefaultValue())
3080              fieldValue = m_proto->getField(i)->getDefault(x3d);
3081          fieldValue = fieldValue->copy();
3082          setField(i, fieldValue);
3083     }
3084     Node::reInit();
3085 }
3086 
3087 Node *
getIsNode(int nodeIndex)3088 NodePROTO::getIsNode(int nodeIndex)
3089 {
3090     if (nodeIndex >=(int)m_indexedNodes.size()) {
3091         if (isLoaded() && !getProto()->isLoading())
3092             swDebugf("Bug: Internal parse error: nodeIndex >= %s",
3093                      "m_indexedNodes.size()\n");
3094         return NULL;
3095     }
3096     return m_indexedNodes[nodeIndex];
3097 }
3098 
3099 
3100 void
preDraw()3101 NodePROTO::preDraw()
3102 {
3103     m_scene->pushUnitAngle();
3104     m_scene->setUnitAngle(getProto()->getUnitAngle());
3105     double unitLength = getProto()->getUnitLength();
3106     if (unitLength > 0)
3107         glScaled(1 / unitLength, 1 / unitLength, 1 / unitLength);
3108 
3109     if (m_indexedNodes.size() > 0)
3110         if (m_indexedNodes[0] != NULL)
3111             m_indexedNodes[0]->preDraw();
3112     for (long i = 1; i < m_indexedNodes.size(); i++) {
3113         if (m_indexedNodes[i]->getType() == VRML_TIME_SENSOR)
3114             m_indexedNodes[i]->preDraw();
3115     }
3116 
3117     if (unitLength > 0)
3118         glScaled(unitLength, unitLength, unitLength);
3119     m_scene->popUnitAngle();
3120 }
3121 
3122 void
draw()3123 NodePROTO::draw()
3124 {
3125     m_scene->pushUnitAngle();
3126     m_scene->setUnitAngle(getProto()->getUnitAngle());
3127     double unitLength = getProto()->getUnitLength();
3128     if (unitLength > 0)
3129         glScaled(1 / unitLength, 1 / unitLength, 1 / unitLength);
3130 
3131     if (m_indexedNodes.size() > 0)
3132         if (m_indexedNodes[0] != NULL)
3133             m_indexedNodes[0]->draw();
3134 
3135     if (unitLength > 0)
3136         glScaled(unitLength, unitLength, unitLength);
3137     m_scene->popUnitAngle();
3138 }
3139 
3140 void
draw(int pass)3141 NodePROTO::draw(int pass)
3142 {
3143     m_scene->pushUnitAngle();
3144     m_scene->setUnitAngle(getProto()->getUnitAngle());
3145     double unitLength = getProto()->getUnitLength();
3146     if (unitLength > 0)
3147         glScaled(1 / unitLength, 1 / unitLength, 1 / unitLength);
3148 
3149     if (m_indexedNodes.size() > 0)
3150         if (m_indexedNodes[0] != NULL)
3151             m_indexedNodes[0]->draw(pass);
3152 
3153     if (unitLength > 0)
3154         glScaled(unitLength, unitLength, unitLength);
3155     m_scene->popUnitAngle();
3156 }
3157 
3158 int
getType() const3159 NodePROTO::getType() const
3160 {
3161     if (m_scene)
3162         return m_scene->getProtoType(getProto());
3163     else if (m_indexedNodes.size() > 0)
3164         if (m_indexedNodes[0] != NULL)
3165             return m_indexedNodes[0]->getType();
3166     return -1;
3167 }
3168 
3169 int
getNodeClass() const3170 NodePROTO::getNodeClass() const
3171 {
3172     if (m_indexedNodes.size() > 0)
3173         if (m_indexedNodes[0] != NULL)
3174             return m_indexedNodes[0]->getNodeClass() | PROTO_NODE;
3175     return Node::getNodeClass() | PROTO_NODE;
3176 }
3177 
3178 FieldValue *
getField(int index) const3179 NodePROTO::getField(int index) const
3180 {
3181     return Node::getField(index);
3182 }
3183 
3184 void
setField(int index,FieldValue * value,int cf)3185 NodePROTO::setField(int index, FieldValue *value, int cf)
3186 {
3187     value->removeIsDefaultValue();
3188     Node::setField(index, value, cf);
3189 }
3190 
3191 void
receiveProtoEvent(int eventOut,double timestamp,FieldValue * value)3192 NodePROTO::receiveProtoEvent(int eventOut, double timestamp, FieldValue *value)
3193 {
3194     for (int j = 0; j < m_proto->getNumEventOuts(); j++) {
3195         SocketList::Iterator *i;
3196         for (i = m_outputs[j].first();
3197              i != NULL; i = i->next()) {
3198             RouteSocket s = i->item();
3199             s.getNode()->receiveEvent(s.getField(), swGetCurrentTime(),value);
3200         }
3201     }
3202 }
3203 
3204 void
sendEvent(int eventOut,double timestamp,FieldValue * value)3205 NodePROTO::sendEvent(int eventOut, double timestamp, FieldValue *value)
3206 {
3207     Node::sendEvent(eventOut, timestamp, value);
3208 }
3209 
3210 void
receiveEvent(int eventIn,double timestamp,FieldValue * value)3211 NodePROTO::receiveEvent(int eventIn, double timestamp, FieldValue *value)
3212 {
3213     // handle IS
3214     EventIn *evIn = m_proto->getEventIn(eventIn);
3215     if ((m_isEventIns.size() > 0) && (m_isEventIns[eventIn] != NULL))
3216         evIn = m_isEventIns[eventIn];
3217     if (evIn && (evIn->getFlags() & FF_IS)) {
3218         if (getType() != VRML_SCRIPT) {
3219             for (int i = 0; i < evIn->getNumIs(); i++) {
3220                 Node *isNode = evIn->getIsNode(i);
3221                 isNode->receiveEvent(evIn->getIsField(i), timestamp, value);
3222             }
3223         }
3224     }
3225     NodeData::receiveEvent(eventIn, timestamp, value);
3226 }
3227 
3228 void
drawHandles(void)3229 NodePROTO::drawHandles(void)
3230 {
3231     if (m_nodes.size() > 0)
3232         if (m_nodes[0] != NULL) {
3233             if (isJoint())
3234                 ((NodeTransform *)m_nodes[0])->drawRotationHandles(0.1f);
3235             else
3236                 m_nodes[0]->drawHandles();
3237         }
3238 }
3239 
3240 void
transform()3241 NodePROTO::transform()
3242 {
3243     if (m_nodes.size() > 0)
3244         if (m_nodes[0] != NULL)
3245             m_nodes[0]->transform();
3246 }
3247 
3248 int
countPolygons(void)3249 NodePROTO::countPolygons(void)
3250 {
3251     if (m_nodes.size() > 0)
3252         if (m_nodes[0] != NULL)
3253             return m_nodes[0]->countPolygons();
3254     return 0;
3255 }
3256 
3257 int
countPrimitives(void)3258 NodePROTO::countPrimitives(void)
3259 {
3260     if (m_nodes.size() > 0)
3261         if (m_nodes[0] != NULL)
3262             return m_nodes[0]->countPrimitives();
3263     return 0;
3264 }
3265 
3266 int
countPolygons1Sided(void)3267 NodePROTO::countPolygons1Sided(void)
3268 {
3269     if (m_nodes.size() > 0)
3270         if (m_nodes[0] != NULL)
3271             return m_nodes[0]->countPolygons1Sided();
3272     return 0;
3273 }
3274 
3275 int
countPolygons2Sided(void)3276 NodePROTO::countPolygons2Sided(void)
3277 {
3278     if (m_nodes.size() > 0)
3279         if (m_nodes[0] != NULL)
3280             return m_nodes[0]->countPolygons2Sided();
3281     return 0;
3282 }
3283 
3284 
3285 Vec3f
getHandle(int handle,int * constraint,int * field)3286 NodePROTO::getHandle(int handle, int *constraint, int *field)
3287 {
3288     if (isJoint())
3289         if (m_nodes.size() > 0)
3290             if (m_nodes[0] != NULL)
3291                 return m_nodes[0]->getHandle(handle, constraint, field);
3292     *field = getProto()->metadata_Field();
3293     return Vec3f(0.0f, 0.0f, 0.0f);
3294 }
3295 
3296 void
setHandle(int handle,const Vec3f & v)3297 NodePROTO::setHandle(int handle, const Vec3f &v)
3298 {
3299     if (isJoint())
3300         if (m_nodes.size() > 0)
3301             if (m_nodes[0] != NULL) {
3302                 NodeTransform *transform = (NodeTransform *)m_nodes[0];
3303                 transform->setHandle(handle, v);
3304                 m_scene->setField(this, m_jointRotationField,
3305                                 new SFRotation(transform->rotation()->getQuat()));
3306             }
3307 }
3308 
getProfileInBranch(Node * node,void * data)3309 static bool getProfileInBranch(Node *node, void *data)
3310 {
3311     int *profile = (int *)data;
3312 
3313     if (node != NULL)
3314         if (node->getProfile() > *profile)
3315             *profile = node->getProfile();
3316     if (*profile == PROFILE_FULL)
3317         return false;
3318     return true;
3319 }
3320 
3321 int
getProfile(void) const3322 NodePROTO::getProfile(void) const
3323 {
3324     int profile = PROFILE_IMMERSIVE;
3325     for (long i = 0; i < m_nodes.size(); i++)
3326          if (profile != PROFILE_FULL)
3327              m_nodes[i]->doWithBranch(getProfileInBranch, &profile);
3328     return profile;
3329 }
3330 
3331 void
getComponentsInBranch(DoWithNodeCallback callback,void * data)3332 NodePROTO::getComponentsInBranch(DoWithNodeCallback callback, void *data)
3333 {
3334     for (long i = 0; i < m_nodes.size(); i++)
3335         m_nodes[i]->doWithBranch(callback, data);
3336 }
3337 
3338 bool
canWriteAc3d()3339 NodePROTO::canWriteAc3d()
3340 {
3341    if (m_nodes.size() > 0)
3342        return m_nodes.canWriteAc3d();
3343    return false;
3344 }
3345 
3346 int
writeAc3d(int filedes,int indent)3347 NodePROTO::writeAc3d(int filedes, int indent)
3348 {
3349    if (m_nodes.size() > 0)
3350        return m_nodes.writeAc3d(filedes, indent);
3351    return 0;
3352 }
3353 
3354 void
handleAc3dMaterial(ac3dMaterialCallback callback,Scene * scene)3355 NodePROTO::handleAc3dMaterial(ac3dMaterialCallback callback, Scene* scene)
3356 {
3357    for (long i = 0; i < m_nodes.size(); i++)
3358        m_nodes.get(i)->handleAc3dMaterial(callback, scene);
3359 }
3360 
3361 int
writeRib(int filedes,int indent)3362 NodePROTO::writeRib(int filedes, int indent)
3363 {
3364    if (m_nodes.size() > 0)
3365        return m_nodes.writeRib(filedes, indent);
3366    return 0;
3367 }
3368 
3369 bool
canWriteCattGeo()3370 NodePROTO::canWriteCattGeo()
3371 {
3372    if (m_nodes.size() > 0)
3373        return m_nodes.canWriteCattGeo();
3374    return false;
3375 }
3376 
3377 int
writeCattGeo(int filedes,int indent)3378 NodePROTO::writeCattGeo(int filedes, int indent)
3379 {
3380    if (m_nodes.size() > 0)
3381        return m_nodes.writeCattGeo(this, filedes, indent);
3382    return 0;
3383 }
3384 
3385 Node *
getProtoRoot(void)3386 NodePROTO::getProtoRoot(void)
3387 {
3388     if (m_indexedNodes.size() <= 0)
3389         return NULL;
3390     return m_indexedNodes[0];
3391 }
3392 
getMaskedNodeClass(int nodeClass)3393 int getMaskedNodeClass(int nodeClass)
3394 {
3395     const unsigned int mask = ~(
3396                                 NOT_SELF_NODE |
3397                                 TEXTURE_NODE |
3398                                 TEXTURE_COORDINATE_NODE |
3399                                 TEXTURE_TRANSFORM_NODE |
3400                                 GEOMETRY_NODE |
3401                                 COLOR_NODE |
3402                                 CHILD_NODE |
3403                                 GROUPING_NODE |
3404                                 URL_NODE |
3405                                 PROTO_NODE
3406                                );
3407 
3408     return nodeClass & mask;
3409 }
3410 
matchNodeClass(int nodeType,int childType,bool repeat)3411 bool matchNodeClass(int nodeType, int childType, bool repeat)
3412 {
3413     int typelist[] = {
3414         NOT_SELF_NODE,
3415         TEXTURE_NODE,
3416         TEXTURE_COORDINATE_NODE,
3417         TEXTURE_TRANSFORM_NODE,
3418         GEOMETRY_NODE,
3419         COLOR_NODE,
3420         CHILD_NODE,
3421         GROUPING_NODE,
3422         URL_NODE,
3423         PROTO_NODE
3424     };
3425     for (unsigned int i = 0; i < (sizeof(typelist) / sizeof(int)); i++)
3426         if ((nodeType & typelist[i]) &&
3427             (childType & typelist[i]))
3428             return true;
3429 
3430     if (getMaskedNodeClass(nodeType) == childType)
3431         return true;
3432 
3433     switch (getMaskedNodeClass(nodeType)) {
3434       // combined types
3435       case AUDIO_CLIP_OR_MOVIE_TEXTURE_NODE:
3436         switch (getMaskedNodeClass(childType)) {
3437           case AUDIO_CLIP_NODE:
3438             return true;
3439           case MOVIE_TEXTURE_NODE:
3440             return true;
3441         }
3442         break;
3443       case BODY_COLLIDABLE_OR_BODY_COLLISION_SPACE_NODE:
3444         switch (getMaskedNodeClass(childType)) {
3445           case BODY_COLLIDABLE_NODE:
3446             return true;
3447           case BODY_COLLISION_SPACE_NODE:
3448             return true;
3449         }
3450         break;
3451       case TEXTURE_OR_TEXTURE_3D_NODE:
3452         switch (getMaskedNodeClass(childType)) {
3453           case TEXTURE_NODE:
3454             return true;
3455           case TEXTURE_3D_NODE:
3456             return true;
3457         }
3458         break;
3459       case NURBS_TEXTURE_COORDINATE_OR_TEXTURE_COORDINATE_NODE:
3460         switch (getMaskedNodeClass(childType)) {
3461           case NURBS_TEXTURE_COORDINATE_NODE:
3462             return true;
3463           case TEXTURE_COORDINATE_NODE:
3464             return true;
3465         }
3466         break;
3467       case SHAPE_OR_LOD_NODE:
3468         switch (getMaskedNodeClass(childType)) {
3469           case SHAPE_NODE:
3470             return true;
3471           case LOD_NODE:
3472             return true;
3473         }
3474         break;
3475       case SHAPE_OR_INLINE_NODE:
3476         switch (getMaskedNodeClass(childType)) {
3477           case SHAPE_NODE:
3478             return true;
3479           case INLINE_NODE:
3480             return true;
3481         }
3482         break;
3483       case SPOTLIGHT_OR_DIRECTIONALLIGHT_OR_VIEWPOINT_NODE:
3484         switch (getMaskedNodeClass(childType)) {
3485           case VRML_SPOT_LIGHT:
3486             return true;
3487           case VRML_DIRECTIONAL_LIGHT:
3488             return true;
3489           case VIEWPOINT_NODE:
3490             return true;
3491           case VIEWPOINT_GROUP_NODE:
3492             return true;
3493         }
3494         break;
3495       case VIEWPOINT_OR_VIEWPOINT_GROUP_NODE:
3496         switch (getMaskedNodeClass(childType)) {
3497           case VIEWPOINT_NODE:
3498             return true;
3499           case VIEWPOINT_GROUP_NODE:
3500             return true;
3501         }
3502         break;
3503       case NURBS_CURVE_2D_OR_CONTOUR_POLYLINE_2D_NODE:
3504         switch (getMaskedNodeClass(childType)) {
3505           case VRML_NURBS_CURVE_2D:
3506             return true;
3507           case X3D_CONTOUR_POLYLINE_2D:
3508             return true;
3509         }
3510         break;
3511       case VOLUME_RENDER_STYLE_NODE:
3512         switch (getMaskedNodeClass(childType)) {
3513           case COMPOSABLE_VOLUME_RENDER_STYLE_NODE:
3514             return true;
3515           case VOLUME_RENDER_STYLE_NODE:
3516             return true;
3517         }
3518         break;
3519       case GENERATED_TEXTURE_COORDINATE_NODE:
3520         switch (getMaskedNodeClass(childType)) {
3521           case X3D_TEXTURE_COORDINATE_GENERATOR:
3522             return true;
3523           case KAMBI_MULTI_GENERATED_TEXTURE_COORDINATE:
3524             return true;
3525           case KAMBI_PROJECTED_TEXTURE_COORDINATE:
3526             return true;
3527         }
3528         break;
3529     }
3530     if (repeat)
3531         return matchNodeClass(childType, nodeType, false);
3532     return false;
3533 }
3534 
3535 bool
hasNumbers4kids(void)3536 Proto::hasNumbers4kids(void)
3537 {
3538     if (m_numbers4KidsInit == false) {
3539         m_numbers4KidsInit = true;
3540         m_numbers4Kids = false;
3541         for (long i = 0; i < m_fields.size(); i++)
3542            if (m_fields[i]->getFlags() & FF_4KIDS) {
3543                m_numbers4Kids = true;
3544                break;
3545            }
3546     }
3547     return m_numbers4Kids;
3548 }
3549 
3550 void
removeNode(int i)3551 Proto::removeNode(int i)
3552 {
3553     m_protoNodes[i]->unref();
3554     removeFromIs(m_protoNodes[i]);
3555     m_protoNodes.remove(i);
3556 }
3557 
3558 void
convert2X3d(void)3559 Proto::convert2X3d(void)
3560 {
3561     for (long i = 0; i < m_protoNodes.size(); i++)
3562         m_protoNodes[i]->convert2X3d();
3563 }
3564 
3565 void
convert2Vrml(void)3566 Proto::convert2Vrml(void)
3567 {
3568     for (long i = 0; i < m_protoNodes.size(); i++)
3569         m_protoNodes[i]->convert2X3d();
3570 }
3571 
3572