1 /*
2  * Node.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 <string.h>
24 #include <ctype.h>
25 #include "stdafx.h"
26 
27 #ifndef FLT_MIN
28 # include <float.h>
29 #endif
30 
31 #include "MeshBasedNode.h"
32 #include "Scene.h"
33 #include "Field.h"
34 #include "FieldValue.h"
35 #include "FieldCommand.h"
36 #include "Proto.h"
37 #include "Path.h"
38 #include "SFNode.h"
39 #include "MFNode.h"
40 #include "SFString.h"
41 #include "MFString.h"
42 #include "EventIn.h"
43 #include "EventOut.h"
44 #include "ExposedField.h"
45 #include "URL.h"
46 #include "DuneApp.h"
47 #include "swDebugf.h"
48 #include "MoveCommand.h"
49 #include "NodeScript.h"
50 #include "NodeIndexedFaceSet.h"
51 #include "NodeCurveAnimation.h"
52 #include "NodePositionInterpolator.h"
53 #include "NodeOrientationInterpolator.h"
54 #include "NodeTimeSensor.h"
55 #include "NodeInline.h"
56 #include "NodeComment.h"
57 #include "ScriptEventDialog.h"
58 
59 void
initIdentifier(void)60 NodeData::initIdentifier(void)
61 {
62     static int identifier_source = 0;
63     identifier_source++;
64     m_identifier = identifier_source;
65     m_identifierCopy = -1;
66 }
67 
NodeData(Scene * scene,Proto * proto)68 NodeData::NodeData(Scene *scene, Proto *proto)
69 {
70     m_scene = scene;
71 
72     m_graphX = m_graphY = 0;
73     m_graphWidth = m_graphHeight = 0;
74 
75     m_refs = 0;
76     m_flags = 1<<NODE_FLAG_COLLAPSED;
77     m_proto = proto;
78 
79     bool x3d = scene->isX3d();
80 
81     m_numFields = m_proto->getNumFields();
82     m_fields = new FieldValue *[m_numFields];
83     for (int i = 0; i < m_numFields; i++) {
84         if (m_proto->getField(i)) {
85             m_fields[i] = m_proto->getField(i)->getDefault(x3d);
86             if (m_fields[i]) {
87                 m_fields[i] = m_fields[i]->copy();
88                 m_fields[i]->ref();
89             }
90         }
91     }
92     m_numEventIns = m_proto->getNumEventIns();
93     m_inputs = new SocketList[m_numEventIns];
94     m_numEventOuts = m_proto->getNumEventOuts();
95     m_outputs = new SocketList[m_numEventOuts];
96     m_insideProto = NULL;
97     m_nodePROTO = NULL;
98     m_canDraw = true;
99     handleIs();
100     generateTreeLabel();
101     m_name = "";
102     m_variableName = "";
103     m_isConvertedInCurveAnimaton = false;
104     setCounter4SceneTreeViewToZero();
105     m_written = false;
106     m_x3domId = "";
107     m_x3domOnOutputChange = "";
108     m_x3domOnClick = "";
109     m_writtenCompleteCProcessEvent = true;
110     m_alreadyConverted = false;
111     m_scene->addNode((Node*)this);
112 }
113 
NodeData(const Node & node)114 NodeData::NodeData(const Node &node) {
115     copyData(node);
116     m_written = false;
117     m_identifierCopy = node.m_identifier;
118     m_alreadyConverted = false;
119     m_writtenCompleteCProcessEvent = true;
120 }
121 
122 void
copyData(const NodeData & node)123 NodeData::copyData(const NodeData &node)
124 {
125     m_identifier = node.m_identifier;// all IDs are unique, except IDs of copies
126 
127     m_scene = node.m_scene;
128     m_refs = 0;
129     m_graphX = m_graphY = 0;
130     m_graphWidth = m_graphHeight = 0;
131     m_flags = node.m_flags;
132     m_proto = node.m_proto;
133     m_numFields = m_proto->getNumFields();
134     m_fields = new FieldValue *[m_numFields];
135     if (node.m_name.length() != 0) {
136         if (!m_scene->hasAlreadyName(node.m_name))
137             m_scene->def(node.m_name, (Node *)this);
138         else
139             m_scene->makeSimilarName((Node *)this, node.m_name);
140     }
141     for (int i = 0; i < m_numFields; i++)
142         if (node.m_fields[i]) {
143             m_fields[i] = node.m_fields[i]->copy();
144             m_fields[i]->ref();
145         }
146     m_numEventIns = m_proto->getNumEventIns();
147     m_inputs = new SocketList[m_numEventIns];
148     m_numEventOuts = m_proto->getNumEventOuts();
149     m_outputs = new SocketList[m_numEventOuts];
150     m_insideProto = node.m_insideProto;
151     m_nodePROTO = node.m_nodePROTO;
152     m_canDraw = node.m_canDraw;
153     handleIs();
154     generateTreeLabel();
155     m_isConvertedInCurveAnimaton = node.m_isConvertedInCurveAnimaton;
156     m_variableName = node.m_variableName;
157     for (long i = 0; i < node.m_convertedNodes.size(); i++)
158         m_convertedNodes[i] = node.m_convertedNodes[i];
159     for (long i = 0; i < node.m_isEventIns.size(); i++)
160         m_isEventIns[i] = node.m_isEventIns[i];
161     for (long i = 0; i < node.m_isEventOuts.size(); i++)
162         m_isEventOuts[i] = node.m_isEventOuts[i];
163     for (long i = 0; i < node.m_isFields.size(); i++)
164         m_isFields[i] = node.m_isFields[i];
165     for (long i = 0; i < node.m_isExposedFields.size(); i++)
166         m_isExposedFields[i] = node.m_isExposedFields[i];
167     m_x3domId = m_x3domId && node.m_x3domId ?
168                 strdup(node.m_x3domId) : NULL;
169     m_x3domOnOutputChange = m_x3domOnOutputChange &&
170                             node.m_x3domOnOutputChange ?
171                             strdup(node.m_x3domOnOutputChange) : NULL;
172     m_x3domOnClick = m_x3domOnClick && node.m_x3domOnClick ?
173                      strdup(node.m_x3domOnClick) : NULL;
174     m_writtenCompleteCProcessEvent = true;
175     m_scene->addNode((Node*)this);
176  }
177 
~NodeData()178 NodeData::~NodeData()
179 {
180     unref();
181 }
182 
183 void
delete_this(void)184 NodeData::delete_this(void)
185 {
186     for (int i = 0; i < m_numFields; i++) {
187         m_fields[i]->unref();
188     }
189     m_numFields = 0;
190     delete [] m_fields;
191     delete [] m_inputs;
192     delete [] m_outputs;
193     m_scene->undef(m_name);
194     m_scene->removeNode((Node *)this);
195 }
196 
197 int
translateField(int field) const198 NodeData::translateField(int field) const
199 {
200     return m_proto->translateField(field);
201 }
202 
203 int
repairField(int field) const204 NodeData::repairField(int field) const
205 {
206     return translateField(field);
207 }
208 
209 bool
isMesh(void)210 NodeData::isMesh(void)
211 {
212     return m_proto->isMesh();
213 }
214 
215 
Node(Scene * scene,Proto * proto)216 Node::Node(Scene *scene, Proto *proto) : NodeData(scene,proto)
217 {
218     initIdentifier();
219     m_commentsList = new NodeList;
220     m_geometricParentIndex = -1;
221     m_numberCDataFunctions = 0;
222     m_containerField = -1;
223     m_protoParent = NULL;
224     m_isUse = false;
225     ref();
226 }
227 
Node(const Node & node)228 Node::Node(const Node &node) : NodeData(node)
229 {
230     m_geometricParentIndex = node.getGeometricParentIndex();
231     m_commentsList = new NodeList;
232     ref();
233     m_numberCDataFunctions = node.m_numberCDataFunctions;
234 }
235 
Node(const Node & node,Proto * proto)236 Node::Node(const Node &node, Proto *proto) : NodeData(node)
237 {
238     initIdentifier();
239     m_geometricParentIndex = node.getGeometricParentIndex();
240     m_proto = proto;
241     for (int i = 0; i < proto->getNumEventOuts(); i++)
242         m_outputs[i] = node.m_outputs[i];
243     m_commentsList = new NodeList;
244     ref();
245     m_numberCDataFunctions = 0;
246     m_containerField = -1;
247 }
248 
~Node()249 Node::~Node()
250 {
251     delete m_commentsList;
252 }
253 
254 bool
matchNodeClass(int childType) const255 NodeData::matchNodeClass(int childType) const
256 {
257     return m_proto->matchNodeClass(childType);
258 }
259 
260 void
copyParentList(const Node & node)261 NodeData::copyParentList(const Node &node)
262 {
263     for (long i = 0; i < node.m_parents.size(); i++)
264         m_parents.append(node.m_parents[i]);
265 }
266 
267 int
getType() const268 NodeData::getType() const
269 {
270     if (m_proto && isPROTO() && m_scene)
271         return m_scene->getProtoType(m_proto);
272     if (m_proto)
273         return m_proto->getType();
274     return -1;
275 }
276 
277 int
getNodeClass() const278 NodeData::getNodeClass() const
279 {
280     if (m_proto)
281         return m_proto->getNodeClass();
282     return CHILD_NODE;
283 }
284 
285 int
getMaskedNodeClass(void)286 NodeData::getMaskedNodeClass(void)
287 {
288     if (m_proto)
289         return ::getMaskedNodeClass(getNodeClass());
290     return 0;
291 }
292 
293 bool
hasName(void)294 NodeData::hasName(void)
295 {
296     if (m_name.length() == 0)
297         return false;
298     if (m_name.length() == 0)
299         if (needsDEF())
300             m_scene->generateUniqueNodeName((Node *)this);
301     if (m_name.length() == 0)
302         return false;
303     else
304         return true;
305 }
306 
307 const MyString&
getName(void)308 NodeData::getName(void)
309 {
310     if (needsDEF())
311        if (m_name.length() == 0)
312           m_scene->generateUniqueNodeName((Node *)this);
313     return m_name;
314 }
315 
316 const MyString&
getNameOrNewName(void)317 NodeData::getNameOrNewName(void)
318 {
319     if (m_name.length() == 0)
320         m_scene->generateUniqueNodeName((Node *)this);
321     return m_name;
322 }
323 
324 void
setName(const char * name)325 NodeData::setName(const char *name)
326 {
327     m_scene->undef(m_name);
328     m_name = name;
329     generateTreeLabel();
330 }
331 
332 bool
needsDEF() const333 NodeData::needsDEF() const
334 {
335     if (m_name.length() != 0) return true;
336 
337     if (((Node *)this)->getNumParents() > 1) return true;
338 
339     for (int i = 0; i < m_numEventIns; i++) {
340         if (m_inputs[i].size() > 0) {
341             return true;
342         }
343     }
344 
345     for (int j = 0; j < m_numEventOuts; j++) {
346         if (m_outputs[j].size() > 0) {
347             return true;
348         }
349     }
350 
351     return false;
352 }
353 
354 // C/C++/java keywords not possible as variable names
355 static const char *keyWords[] = {
356     "abstract",
357     "asm",
358     "auto",
359     "bool",
360     "boolean",
361     "break",
362     "byte",
363     "case",
364     "catch",
365     "char",
366     "class",
367     "const",
368     "continue",
369     "default",
370     "delete",
371     "do",
372     "double",
373     "else",
374     "enum",
375     "extends",
376     "extern",
377     "final",
378     "finally",
379     "float",
380     "for",
381     "friend",
382     "goto",
383     "if",
384     "implements",
385     "import",
386     "inline",
387     "instanceof",
388     "int",
389     "interface",
390     "long",
391     "native",
392     "new",
393     "operator",
394     "package",
395     "private",
396     "protected",
397     "public",
398     "register",
399     "return",
400     "short",
401     "signed",
402     "sizeof",
403     "static",
404     "strictfp",
405     "String",
406     "struct",
407     "super",
408     "switch",
409     "synchronized",
410     "template",
411     "this",
412     "throw",
413     "throws",
414     "transient",
415     "try",
416     "typedef",
417     "union",
418     "unsigned",
419     "virtual",
420     "void",
421     "volatile",
422     "while"
423 };
424 
425 const char *
getVariableName(void)426 NodeData::getVariableName(void)
427 {
428     bool hasname = hasName();
429     bool isRoot = false;
430     if (m_variableName.length() == 0) {
431         MyString cName = "";
432         if ((m_name != NULL) && (m_name.length() > 0)) {
433             if (isalpha(m_name[0]))
434                 cName += m_name[0];
435             else
436                 cName += "A";
437             for (int i = 1; i < m_name.length(); i++)
438                 if (isalnum(m_name[i]))
439                     cName += m_name[i];
440                 else
441                     cName += "m_";
442             hasname = true;
443         }
444 
445         if (m_scene != NULL) {
446             if (m_scene->getRoot() == this) {
447                 isRoot = true;
448                 m_variableName = "";
449                 m_variableName += "root";
450             }
451         }
452         if ((!isRoot) && hasname) {
453             m_variableName = "";
454             bool isKeyWord = false;
455             for (unsigned int i = 0;
456                  i < sizeof(keyWords)/sizeof(const char *); i++)
457                 if (strcmp(m_name.getData(), keyWords[i]) == 0) {
458                     isKeyWord = true;
459                     m_variableName += cName;
460                     swDebugf("Warning: Variablename ");
461                     swDebugf("\"%s\"", m_name.getData());
462                     swDebugf(" is a C++/java keyword, ");
463                     swDebugf("\"%s\"", m_variableName.getData());
464                     swDebugf(" used instead\n");
465                 }
466             if (!isKeyWord)
467                 m_variableName += cName;
468         }
469         if (m_variableName.length() == 0)
470             if (m_scene != NULL) {
471                 setVariableName(m_scene->generateUniqueNodeName((Node *)this));
472 //                m_variableName.sub("ColorRGBA", "Color");
473                 m_name = "";
474                 m_name += m_variableName;
475             }
476     }
477 
478     return m_variableName;
479 }
480 
481 void
setVariableName(const char * name)482 NodeData::setVariableName(const char *name)
483 {
484     m_variableName = "";
485     m_variableName += name;
486 }
487 
488 const char *
getClassName(void)489 NodeData::getClassName(void)
490 {
491     if (m_proto)
492         return m_proto->getClassName();
493     return NULL;
494 }
495 
496 
497 FieldValue *
getField(int index) const498 NodeData::getField(int index) const
499 {
500 #ifdef DEBUG
501     assert(index >= 0 && index < m_numFields);
502 #else
503     if ((index < 0) && (index >= m_numFields)) {
504         printf("Internal error in NodeData::getField\n");
505         return NULL;
506     }
507 #endif
508     if (m_scene != NULL)
509         if (((m_scene->getWriteFlags() & (CONVERT2VRML | CONVERT2X3D)) != 0) ||
510              m_scene->isX3d())
511             return m_fields[translateField(index)];
512     return m_fields[index];
513 }
514 
515 void
setField(int fieldIndex,FieldValue * value,int containerField)516 NodeData::setField(int fieldIndex, FieldValue *value, int containerField)
517 {
518     int index = fieldIndex;
519     if (m_scene != NULL)
520         if (((m_scene->getWriteFlags() & (CONVERT2VRML | CONVERT2X3D)) == 0) ||
521              m_scene->isX3d())
522          index = translateField(index);
523     assert(index >= 0 && index < m_numFields);
524     Field *field = m_proto->getField(index);
525     if ((field != NULL) && value && (value->getRefs() != 0))
526         assert(field->getType() == value->getType());
527 
528     // if field is an SFNode or MFNode type, remove old values from
529     // children's parent list
530 
531     bool isNode = false;
532     if (m_fields[index] && m_fields[index]->getType() == SFNODE) {
533         isNode = true;
534         Node *child = ((SFNode *) m_fields[index])->getValue();
535         if (child) child->removeParent();
536     } else if (m_fields[index] && m_fields[index]->getType() == MFNODE) {
537         isNode = true;
538         NodeList *childList = ((MFNode *) m_fields[index])->getValues();
539         if (childList) {
540             for (long i = 0; i < childList->size(); i++) {
541                 Node *child = childList->get(i);
542                 if (child) child->removeParent();
543             }
544         }
545     }
546 
547     if (value && value->getRefs() > -1)
548         value->clamp(field->getMin(), field->getMax());
549 
550     if (m_fields[index] != NULL)
551         m_fields[index]->unref();
552     m_fields[index] = value;
553     if (value)
554         m_fields[index]->ref();
555     if (value && isNode) {
556         if (containerField != -1)
557             m_fields[index]->setContainerField(containerField);
558     }
559 
560     if (value && value->getType() == SFNODE) {
561         Node *child = ((SFNode *) value)->getValue();
562         if (child) child->addParent((Node*)this, index);
563     } else if (value && value->getType() == MFNODE) {
564         NodeList *childList = ((MFNode *) value)->getValues();
565         if (childList) {
566             for (long i = 0; i < childList->size(); i++) {
567                 Node *child = childList->get(i);
568                 if (child) child->addParent((Node*)this, index);
569             }
570         }
571     }
572     // handle IS
573     if (field && (field->getFlags() & FF_IS))
574         for (int i = 0; i < field->getNumIs(); i++) {
575             Node *isNode = getIsNode(field->getIsNodeIndex(i));
576             if (isNode)
577                 isNode->setField(field->getIsField(i), value);
578         }
579     ExposedField *expField = field->getExposedField();
580     if (expField) {
581         if (expField->getFlags() & FF_IS)
582             for (int i = 0; i < expField->getNumIs(); i++) {
583                 Node *isNode = getIsNode(expField->getIsNodeIndex(i));
584                 if (isNode)
585                     isNode->setField(expField->getIsField(i), value);
586             }
587         if (m_scene) {
588             int eventOut = expField->getEventOut();
589             SocketList::Iterator *i;
590             for (i = m_outputs[eventOut].first(); i != NULL; i = i->next()) {
591                 RouteSocket s = i->item();
592                 s.getNode()->receiveEvent(s.getField(), swGetCurrentTime(),
593                                           value);
594             }
595         }
596     }
597     if (m_scene)
598         m_scene->setNotSaved();
599 }
600 
601 FieldValue *
getUntranslatedField(int index) const602 NodeData::getUntranslatedField(int index) const
603 {
604 #ifdef DEBUG
605     assert(index >= 0 && index < m_numFields);
606 #else
607     if ((index < 0) && (index >= m_numFields)) {
608         printf("Internal error in NodeData::getField\n");
609         return NULL;
610     }
611 #endif
612     return m_fields[index];
613 }
614 
615 void
addFieldNodeList(int index,NodeList * childList,int containerField)616 Node::addFieldNodeList(int index, NodeList *childList, int containerField)
617 {
618     assert(index >= 0 && index < m_numFields);
619     if (((MFNode*)m_fields[index])->getSize() == 0)
620         setField(index, new MFNode(childList), containerField);
621     else {
622         for (long i = 0; i < childList->size(); i++) {
623             Node *child = childList->get(i);
624             FieldValue* newField= ((MFNode*)m_fields[index])->addNode(child);
625             ((MFNode*)m_fields[index])->setContainerField(containerField);
626             newField->clamp(m_proto->getField(index)->getMin(),
627                             m_proto->getField(index)->getMax());
628 
629             m_fields[index]->unref();
630             m_fields[index] = newField;
631             m_fields[index]->ref();
632             if (child) {
633                 child->addParent(this, index);
634             }
635         }
636     }
637     ((MFNode*)m_fields[index])->getValues();
638 }
639 
640 int
write(int f,int indent,bool avoidUse)641 Node::write(int f, int indent, bool avoidUse)
642 {
643     bool x3d = m_scene->isX3dv();
644     if (m_proto) {
645         TheApp->checkSelectionLinenumberCounting(m_scene, (Node*) this);
646         if ((!avoidUse) && getFlag(NODE_FLAG_DEFED) && (m_name.length() > 0)) {
647             RET_ONERROR( mywritestr(f, "USE ") )
648             RET_ONERROR( mywritestr(f, (const char *) m_name) )
649             RET_ONERROR( mywritestr(f, "\n") )
650             TheApp->incSelectionLinenumber();
651         } else {
652             if (avoidUse) {
653                  m_scene->generateUniqueNodeName((Node*)this,
654                                                  getProto()->getName(x3d));
655             }
656             if (((Node *)this)->needsDEF()) {
657                 if (!m_name[0])
658                     m_scene->generateUniqueNodeName((Node*)this);
659                 RET_ONERROR( mywritestr(f, "DEF ") )
660                 RET_ONERROR( mywritestr(f, (const char *) m_name) )
661                 RET_ONERROR( mywritestr(f, " ") )
662             }
663             setFlag(NODE_FLAG_DEFED);
664             bool writeProtoName = true;
665             if (m_scene->isPureVRML97())
666                 if ((TheApp->getCoverMode() && (!hasDefault(FF_COVER_ONLY))) ||
667                     (TheApp->getKambiMode() && (!hasDefault(FF_KAMBI_ONLY)))) {
668                     Proto *extension = m_scene->getExtensionProto(m_proto);
669                     if (extension != NULL) {
670                         writeProtoName = false;
671                         RET_ONERROR( mywritestr(f, extension->getName(x3d)) )
672                     }
673                 }
674             if (writeProtoName) {
675                 RET_ONERROR( mywritestr(f,
676                                         (const char *) m_proto->getName(x3d)))
677             }
678 
679             if (!TheApp->GetkrFormating()) {
680                 RET_ONERROR( mywritestr(f, "\n") )
681                 TheApp->incSelectionLinenumber();
682                 RET_ONERROR( indentf(f, indent + TheApp->GetIndent()) )
683             } else
684                 RET_ONERROR( mywritestr(f, " ") )
685 
686             RET_ONERROR( mywritestr(f, "{\n") )
687             TheApp->incSelectionLinenumber();
688             RET_ONERROR( writeFields(f, indent + TheApp->GetIndent()) )
689             if (!TheApp->GetkrFormating())
690                 RET_ONERROR( indentf(f, indent + TheApp->GetIndent()) )
691             else
692                 RET_ONERROR( indentf(f, indent) )
693             RET_ONERROR( mywritestr(f, "}\n") )
694             TheApp->incSelectionLinenumber();
695             if (indent==0) {
696                 RET_ONERROR( mywritestr(f, "\n") )
697                 TheApp->incSelectionLinenumber();
698             }
699             RET_ONERROR( writeRoutes(f, indent) )
700             setFlag(NODE_FLAG_TOUCHED);
701         }
702     }
703     return(0);
704 }
705 
706 int
writeXml(int f,int indent,int containerField,bool avoidUse)707 Node::writeXml(int f, int indent, int containerField, bool avoidUse)
708 {
709     bool x3d = true;
710     if (getType() == VRML_COMMENT) {
711         MFString *value = ((NodeComment *)this)->comment();
712         RET_ONERROR( indentf(f, indent) )
713         RET_ONERROR( mywritestr(f, "<!--") )
714         if (value->getSize() > 1)
715             RET_ONERROR( mywritestr(f, "\n") )
716         TheApp->checkSelectionLinenumberCounting(m_scene, this);
717         for (int i = 0; i < value->getSize(); i++) {
718             if (value->getSize() > 1)
719                 RET_ONERROR( indentf(f, indent + TheApp->GetIndent()) )
720             RET_ONERROR( mywritestr(f, (const char *) value->getValue(i)) )
721             if (value->getSize() > 1)
722                 RET_ONERROR( mywritestr(f, "\n") )
723             TheApp->incSelectionLinenumber();
724         }
725         if (value->getSize() > 1)
726             RET_ONERROR( indentf(f, indent) )
727         RET_ONERROR( mywritestr(f, "-->\n") )
728         return 0;
729     } else if ((getType() == VRML_IMAGE_TEXTURE) &&
730                ((m_scene->getWriteFlags() & X3DOM) != 0)) {
731         NodeImageTexture *texture = (NodeImageTexture *)this;
732         Node *pixelTexture = texture->getPixelTexture();
733         return pixelTexture->writeXml(f, indent, containerField);
734     }
735 
736     if (m_proto) {
737         Proto *protoToWrite = NULL;
738         TheApp->checkSelectionLinenumberCounting(m_scene, (Node*) this);
739         RET_ONERROR( indentf(f, indent) )
740         RET_ONERROR( mywritestr(f, "<") )
741         if (m_scene->isPureVRML97() &&
742             ((TheApp->getCoverMode() && (!hasDefault(FF_COVER_ONLY))) ||
743              (TheApp->getKambiMode() && (!hasDefault(FF_KAMBI_ONLY))))) {
744             protoToWrite = m_scene->getExtensionProto(m_proto);
745         } else if (isPROTO() ||
746                    m_proto->isScriptedProto() ||
747                    m_proto->isScriptedExternProto()) {
748             protoToWrite = m_proto;
749         }
750         bool containerFieldWritten = false;
751         if (protoToWrite == NULL) {
752 #ifdef HAVE_NO_STATIC_GROUP_X3DOM
753             if ((m_scene->getWriteFlags() & X3DOM) &&
754                 strcmp(m_proto->getName(x3d), "StaticGroup") == 0)
755                 RET_ONERROR( mywritestr(f, "Group") )
756             else
757                 RET_ONERROR(mywritestr(f, (const char *) m_proto->getName(x3d)))
758 #else
759             RET_ONERROR( mywritestr(f, (const char *) m_proto->getName(x3d)) )
760 #endif
761 /*
762             if (hasParent()) {
763                 if ((getParent()->showFields()) &&
764                     (getParent()->getType() != VRML_SCRIPT)) {
765                     Node *parent = getParent();
766                     int cField = containerField;
767                     if (cField == -1)
768                         cField = getParentField();
769                     if (cField != getParentField()) {
770                         parent = searchParentField(cField);
771                     }
772                     const char *name = parent->getProto()->getField(
773                                            cField)->getName(x3d);
774                     containerFieldWritten = true;
775                 }
776             }
777 */
778         } else {
779             RET_ONERROR( mywritestr(f, "ProtoInstance name='") )
780             RET_ONERROR( mywritestr(f, protoToWrite->getName(x3d)) )
781             RET_ONERROR( mywritestr(f, "'") )
782         }
783 
784         if ((!avoidUse) && getFlag(NODE_FLAG_DEFED)) {
785             RET_ONERROR( mywritestr(f, " USE='") )
786             RET_ONERROR( mywritestr(f, (const char *) m_name) )
787             RET_ONERROR( mywritestr(f, "'") )
788             if (hasParent() &&
789                 (containerFieldWritten == false)) {
790                 if ((getParent()->showFields()) &&
791                     (getParent()->getType() != VRML_SCRIPT)) {
792                     Node *parent = getParent();
793                     int cField = containerField;
794                     if (cField == -1)
795                         cField = getParentField();
796                     if (cField != getParentField()) {
797                         parent = searchParentField(cField);
798                     }
799                     const char *name = parent->getProto()->getField(
800                                            cField)->getName(x3d);
801 /*
802                     RET_ONERROR( mywritestr(f, " containerField='") )
803                     RET_ONERROR( mywritestr(f, name) )
804                     RET_ONERROR( mywritestr(f, "'") )
805 */
806                 }
807             }
808             RET_ONERROR( mywritestr(f, ">\n") )
809             RET_ONERROR( indentf(f, indent) )
810             RET_ONERROR( mywritestr(f, "</") )
811 #ifdef HAVE_NO_STATIC_GROUP_X3DOM
812             if ((m_scene->getWriteFlags() & X3DOM) &&
813                 strcmp(m_proto->getName(x3d), "StaticGroup") == 0)
814                 RET_ONERROR( mywritestr(f, "Group") )
815             else
816                 RET_ONERROR(mywritestr(f, (const char *) m_proto->getName(x3d)))
817 #else
818             RET_ONERROR( mywritestr(f, (const char *) m_proto->getName(x3d)) )
819 #endif
820             RET_ONERROR( mywritestr(f, ">\n") )
821             TheApp->incSelectionLinenumber();
822         } else {
823             if (avoidUse) {
824                 m_scene->generateUniqueNodeName((Node*)this,
825                                                 getProto()->getName(x3d));
826             }
827             if (((Node *)this)->needsDEF()) {
828                 if (!m_name[0])
829                     m_scene->generateUniqueNodeName((Node*)this);
830                 RET_ONERROR( mywritestr(f, " DEF='") )
831                 RET_ONERROR( mywritestr(f, (const char *) m_name) )
832                 RET_ONERROR( mywritestr(f, "' ") )
833                 setFlag(NODE_FLAG_DEFED);
834                 if (m_scene->getWriteFlags() & X3DOM) {
835                     RET_ONERROR( mywritestr(f, "id='") )
836                     if ((m_x3domId == NULL) || strlen(m_x3domId) == 0)
837                         RET_ONERROR( mywritestr(f, (const char *) m_name) )
838                     else
839                         RET_ONERROR( mywritestr(f,m_x3domId) )
840                     RET_ONERROR( mywritestr(f, "' ") )
841                     if (m_x3domOnOutputChange &&
842                         strlen(m_x3domOnOutputChange) != 0) {
843                         RET_ONERROR( mywritestr(f, "OnOutputChange='") )
844                         RET_ONERROR( mywritestr(f,m_x3domOnOutputChange) )
845                         RET_ONERROR( mywritestr(f, "' ") )
846                     }
847                     if (m_x3domOnClick && strlen(m_x3domOnClick) != 0) {
848                         RET_ONERROR( mywritestr(f, "OnClick='") )
849                         RET_ONERROR( mywritestr(f,m_x3domOnClick) )
850                         RET_ONERROR( mywritestr(f, "' ") )
851                     }
852                 }
853             }
854             RET_ONERROR( mywritestr(f, " ") )
855             RET_ONERROR( writeXmlFields(f, indent, XML_IN_TAG,
856                          containerField, avoidUse) )
857             RET_ONERROR( mywritestr(f, ">\n") )
858             TheApp->incSelectionLinenumber();
859             RET_ONERROR( writeXmlFields(f, indent, XML_NODE,
860                                         containerField, avoidUse) )
861             RET_ONERROR( writeXmlFields(f, indent + TheApp->GetIndent(),
862                                         XML_PROTO_INSTANCE_FIELD,
863                                         containerField, avoidUse) )
864             if (getProto()->getNumNodes() > 0)
865                 RET_ONERROR( writeXmlFields(f, indent + TheApp->GetIndent(),
866                                             XML_IS, containerField, avoidUse) )
867             RET_ONERROR( indentf(f, indent) )
868             RET_ONERROR( mywritestr(f, "</") )
869             if (protoToWrite == NULL) {
870 #ifdef HAVE_NO_STATIC_GROUP_X3DOM
871                 if ((m_scene->getWriteFlags() & X3DOM) &&
872                     strcmp(m_proto->getName(x3d), "StaticGroup") == 0)
873                     RET_ONERROR( mywritestr(f, "Group") )
874                 else
875                     RET_ONERROR( mywritestr(f,
876                         (const char *) m_proto->getName(x3d)) )
877 #else
878                 RET_ONERROR( mywritestr(f, (const char *) m_proto->getName(x3d)))
879 #endif
880             } else
881                 RET_ONERROR( mywritestr(f, "ProtoInstance") )
882             RET_ONERROR( mywritestr(f, ">\n") )
883             TheApp->incSelectionLinenumber();
884             if (!avoidUse) {
885                 RET_ONERROR( writeRoutes(f, indent) )
886                 setFlag(NODE_FLAG_TOUCHED);
887             } else
888                 m_scene->copyRoutesToScene(this);
889         }
890     }
891     return 0;
892 }
893 
894 int
writeProto(int filedes)895 NodeData::writeProto(int filedes)
896 {
897     // used to write the EXTERNPROTO definition of extension nodes
898     return 0;
899 }
900 
901 int
writeProto(int f,const char * urn,const char * directoryName,const char * haveUrl,bool nameInUrl)902 NodeData::writeProto(int f, const char *urn, const char *directoryName,
903                            const char *haveUrl, bool nameInUrl)
904 {
905     if (m_scene->isX3dXml())
906         return m_proto->write(f, 0, X3D_XML);
907     const char* nodeName = m_proto->getName(m_scene->isX3d());
908     RET_ONERROR( mywritef(f, "EXTERNPROTO %s[\n", nodeName) )
909     TheApp->incSelectionLinenumber();
910     RET_ONERROR( writeProtoArguments(f) )
911     RET_ONERROR( mywritestr(f, " ]\n") )
912     TheApp->incSelectionLinenumber();
913     RET_ONERROR( mywritestr(f, "[\n") )
914     TheApp->incSelectionLinenumber();
915     if (strlen(urn) > 0) {
916         RET_ONERROR( mywritef(f, "  \"%s:%s\"\n", urn, nodeName) )
917         TheApp->incSelectionLinenumber();
918     }
919     RET_ONERROR( mywritef(f, "  \"%sPROTO.wrl\"\n", nodeName) )
920     TheApp->incSelectionLinenumber();
921     RET_ONERROR( mywritestr(f, "  \"") )
922     char *dunedocs = getenv("DUNEDOCS");
923     if (dunedocs != NULL) {
924         RET_ONERROR( mywritestr(f, dunedocs) )
925         RET_ONERROR( mywritestr(f, "/") )
926         RET_ONERROR( mywritestr(f, directoryName) )
927         RET_ONERROR( mywritestr(f, "/") )
928     } else if (strlen(haveUrl) > 0) {
929         RET_ONERROR( mywritestr(f, haveUrl) )
930         if (nameInUrl)
931             RET_ONERROR( mywritestr(f, "/") )
932         else
933             RET_ONERROR( mywritestr(f, "\"\n") )
934     }
935     if ((dunedocs != NULL) || (nameInUrl))
936         RET_ONERROR( mywritef(f, "%sPROTO.wrl\"\n", nodeName) )
937     TheApp->incSelectionLinenumber();
938     RET_ONERROR( mywritef(f,
939                           "  \"%s/docs/%s/%sPROTO.wrl\"\n",
940                           "http://wdune.ourproject.org/",
941                           directoryName, nodeName) )
942     TheApp->incSelectionLinenumber();
943     RET_ONERROR( mywritestr(f, "]\n") )
944     TheApp->incSelectionLinenumber();
945     return 0;
946 }
947 
948 int
writeX3dProto(int filedes)949 NodeData::writeX3dProto(int filedes)
950 {
951     return ((Node *)this)->writeProto(filedes,
952                                       "urn:web3d:x3d:node:",
953                                       "x3d"
954 #ifdef HAVE_X3D_PROTO_URL
955                                       , HAVE_X3D_PROTO_URL
956 #endif
957                                       );
958 }
959 
960 int
writeIs(int f,int indent,const char * name,const char * isName)961 NodeData::writeIs(int f, int indent, const char *name, const char* isName)
962 {
963     RET_ONERROR( indentf(f, indent) )
964     RET_ONERROR( mywritestr(f, name) )
965     RET_ONERROR( mywritestr(f, " IS ") )
966     RET_ONERROR( mywritestr(f, isName) )
967     RET_ONERROR( mywritestr(f, "\n") )
968     TheApp->incSelectionLinenumber();
969     return 0;
970 }
971 
972 int
writeXmlIs(int f,int indent,const char * name,const char * isName)973 NodeData::writeXmlIs(int f, int indent, const char *name, const char* isName)
974 {
975     RET_ONERROR( indentf(f, indent) )
976     RET_ONERROR( mywritestr(f, "<connect nodeField='") )
977     RET_ONERROR( mywritestr(f, name) )
978     RET_ONERROR( mywritestr(f, "' protoField='") )
979     RET_ONERROR( mywritestr(f, isName) )
980     RET_ONERROR( mywritestr(f, "' />\n") )
981     TheApp->incSelectionLinenumber();
982     return 0;
983 }
984 
985 
986 int
writeXmlProtoInstanceField(int f,int indent,const char * name,FieldValue * value)987 NodeData::writeXmlProtoInstanceField(int f, int indent, const char *name,
988                                      FieldValue* value)
989 {
990     bool isNode = false;
991     bool needValue = true;
992     if (value->getType() == SFNODE) {
993         if (((SFNode *)value)->getValue() == NULL)
994             needValue = false;
995         else
996             isNode = true;
997     }
998     if (value->getType() == MFNODE) {
999         if (((MFieldValue *)value)->getSFSize() == 0)
1000             needValue = false;
1001         else
1002             isNode = true;
1003     }
1004 
1005     RET_ONERROR( indentf(f, indent) )
1006     RET_ONERROR( mywritestr(f, "<fieldValue name='") )
1007     RET_ONERROR( mywritestr(f, name) )
1008     RET_ONERROR( mywritestr(f, "' ") )
1009     if (isNode)
1010         RET_ONERROR( mywritestr(f, ">\n") )
1011     else if (needValue)
1012         RET_ONERROR( mywritestr(f, "value=") )
1013     RET_ONERROR( value->writeXml(f, indent) )
1014     if (isNode) {
1015         RET_ONERROR( indentf(f, indent) )
1016         RET_ONERROR( mywritestr(f, "</fieldValue>\n") )
1017     } else {
1018         RET_ONERROR( mywritestr(f, "/>\n") )
1019     }
1020     TheApp->incSelectionLinenumber();
1021     return 0;
1022 }
1023 
1024 const char *
searchIsName(int i,int type)1025 NodeData::searchIsName(int i, int type)
1026 {
1027     Element *element = NULL;
1028     switch (type) {
1029       case EL_FIELD:
1030         element = m_proto->getField(i);
1031         break;
1032       case EL_EVENT_IN:
1033         element = m_proto->getEventIn(i);
1034         break;
1035       case EL_EVENT_OUT:
1036         element = m_proto->getEventOut(i);
1037         break;
1038       default:
1039         return NULL;
1040     }
1041     if (m_scene->isInvalidElement(element))
1042         return NULL;
1043     if (!isInsideProto())
1044         return NULL;
1045 
1046     bool x3d = m_scene->isX3d();
1047     const char *isName = NULL;
1048     bool stopLoop = false;
1049     for (int j = 0; j < m_scene->getNumProtoNames(); j++) {
1050         const char *protoName = m_scene->getProtoName(j);
1051         Proto *proto = m_scene->getProto(protoName);
1052         int isElement = -1;
1053         ExposedField *exposedField = NULL;
1054         int field = i;
1055         int myType = type;
1056         switch (type) {
1057           case EL_EVENT_IN:
1058             exposedField = ((EventIn *)element)->getExposedField();
1059             if (exposedField) {
1060                 field = exposedField->getFieldIndex();
1061                 myType = EL_EXPOSED_FIELD;
1062             }
1063             isElement = proto->lookupIsEventIn((Node *)this, field, myType);
1064             if (isElement == -1)
1065                 isElement = proto->lookupIsEventOut((Node *)this, field,
1066                                                     EL_EVENT_IN);
1067             if (isElement != -1) {
1068                 isName = proto->getEventIn(isElement)->getName(x3d);
1069                 stopLoop = true;
1070             }
1071             break;
1072           case EL_EVENT_OUT:
1073             exposedField = ((EventOut *)element)->getExposedField();
1074             if (exposedField) {
1075                 field = exposedField->getFieldIndex();
1076                 myType = EL_EXPOSED_FIELD;
1077             }
1078             isElement = proto->lookupIsEventOut((Node *)this, field, myType);
1079             if (isElement == -1)
1080                 isElement = proto->lookupIsEventOut((Node *)this, field,
1081                                                     EL_EVENT_OUT);
1082             if (isElement != -1) {
1083                 isName = proto->getEventOut(isElement)->getName(x3d);
1084                 stopLoop = true;
1085             }
1086             break;
1087           case EL_FIELD:
1088             isElement = proto->lookupIsExposedField((Node *)this, i);
1089             if (isElement != -1) {
1090                 isName = proto->getExposedField(isElement)->getName(x3d);
1091                 stopLoop = true;
1092             }
1093             if ((isName == NULL) || (isName && strlen(isName) == 0)) {
1094                 isElement = proto->lookupIsField((Node *)this, i);
1095                 if (isElement != -1) {
1096                     isName = proto->getField(isElement)->getName(x3d);
1097                     stopLoop = true;
1098                 }
1099             }
1100         }
1101         if (stopLoop)
1102             break;
1103     }
1104     return isName;
1105 }
1106 
1107 int
writeFields(int f,int indent)1108 NodeData::writeFields(int f, int indent)
1109 {
1110     if (!m_proto) return(0);
1111 
1112     // delay writing of Script.url
1113     int scriptUrlField = -1;
1114     if (getType() == VRML_SCRIPT)
1115         scriptUrlField = ((NodeScript *)this)->url_Field();
1116 
1117     for (int i = 0; i < m_numFields; i++)
1118         if (i != scriptUrlField)
1119             RET_ONERROR( writeField(f, indent, i) )
1120 
1121     for (int i = 0; i < m_numEventIns; i++)
1122         RET_ONERROR( writeEventIn(f, indent, i) )
1123 
1124     for (int i = 0; i < m_numEventOuts; i++)
1125         RET_ONERROR( writeEventOut(f, indent, i) )
1126 
1127     if ((scriptUrlField != -1) && (!isPROTO())) {
1128         RET_ONERROR( mywritestr(f, "\n[\n") )
1129         RET_ONERROR( writeField(f, indent, scriptUrlField) )
1130         RET_ONERROR( mywritestr(f, "\n]\n") )
1131     }
1132 
1133     return(0);
1134 }
1135 
1136 int
writeXmlFields(int f,int indent,int when,int containerField,bool avoidUse)1137 NodeData::writeXmlFields(int f, int indent, int when, int containerField,
1138                          bool avoidUse)
1139 {
1140     if (isDynamicFieldsNode())
1141         TheApp->setDynamicFieldsNode();
1142 
1143     if (!m_proto) return(0);
1144 
1145     if (isPROTO() || (getType() == DUNE_VRML_CUT) ||
1146                      (getType() == DUNE_VRML_SCENE)) {
1147         if (when != XML_PROTO_INSTANCE_FIELD)
1148             return 0;
1149     } else
1150         if (when == XML_PROTO_INSTANCE_FIELD)
1151             return 0;
1152 
1153     bool writeIs = false;
1154     if (when == XML_IS) {
1155         for (int i = 0; i < m_numFields; i++)
1156             if (searchIsName(i, EL_FIELD) != NULL)
1157                 writeIs = true;
1158         for (int i = 0; i < m_numEventIns; i++)
1159             if (searchIsName(i, EL_EVENT_IN) != NULL)
1160                 writeIs = true;
1161         for (int i = 0; i < m_numEventOuts; i++)
1162             if (searchIsName(i, EL_EVENT_OUT) != NULL)
1163                 writeIs = true;
1164     }
1165     if (avoidUse)
1166         writeIs = false;
1167     if (writeIs) {
1168         RET_ONERROR( indentf(f, indent) )
1169         RET_ONERROR( mywritestr(f, "<IS>\n") )
1170         TheApp->incSelectionLinenumber();
1171         indent += TheApp->GetIndent();
1172     }
1173 
1174     bool isScript = false;
1175     int scriptMetadataField = -1;
1176     int scriptUrlField = -1;
1177     if (getType() == VRML_SCRIPT) {
1178         scriptUrlField = ((NodeScript *)this)->url_Field();
1179         scriptMetadataField = getProto()->metadata_Field();
1180         isScript = true;
1181     }
1182     for (int i = 0; i < m_numFields; i++)
1183         if ((i != scriptUrlField) && (i != scriptMetadataField))
1184             RET_ONERROR( writeXmlField(f, indent, i, when, isScript,
1185                                        containerField, avoidUse) )
1186 
1187     if (!avoidUse) {
1188         for (int i = 0; i < m_numEventIns; i++)
1189             RET_ONERROR( writeXmlEventIn(f, indent, i, when) )
1190 
1191          for (int i = 0; i < m_numEventOuts; i++)
1192              RET_ONERROR( writeXmlEventOut(f, indent, i, when) )
1193     }
1194 
1195     if (scriptUrlField != -1)
1196         RET_ONERROR( writeXmlField(f, indent, scriptUrlField, when) )
1197 
1198     if (when == XML_IN_TAG) {
1199         SocketList::Iterator *j;
1200 
1201         for (int i = 0; i < m_numEventOuts; i++)
1202             for (j = m_outputs[i].first(); j != NULL; j = j->next()) {
1203                 Node *dest = j->item().getNode();
1204                 int field = j->item().getField();
1205                 if ((dest->getType() == VRML_SCRIPT) &&
1206                     (hasX3domOnOutputChange() || hasX3domOnclick())) {
1207                     NodeScript *script = (NodeScript *)dest;
1208                     for (int n = 0; n < script->url()->getSize(); n++)
1209                         if (isX3domscript(script->url()->getValue(n))) {
1210                             RET_ONERROR( mywritestr(f, " ") )
1211                             if (hasX3domOnclick())
1212                                 RET_ONERROR( mywritestr(f, "onClick") )
1213                             else
1214                                 RET_ONERROR( mywritestr(f, "onOutputChange") )
1215                             RET_ONERROR( mywritestr(f, "=\'") )
1216                             const char *name = script->getProto()->
1217                                 getEventIn(field)->getName(true);
1218                             RET_ONERROR( mywritestr(f, name) )
1219                             RET_ONERROR( mywritestr(f, "(event)\' ") )
1220                         }
1221                 }
1222             }
1223     }
1224 
1225     if (writeIs) {
1226         indent -= TheApp->GetIndent();
1227         RET_ONERROR( indentf(f, indent) )
1228         RET_ONERROR( mywritestr(f, "</IS>\n") )
1229         TheApp->incSelectionLinenumber();
1230     }
1231 
1232     if (isDynamicFieldsNode())
1233         TheApp->unsetDynamicFieldsNode();
1234 
1235     return 0;
1236 }
1237 
1238 int
writeField(int f,int indent,int i,bool script)1239 NodeData::writeField(int f, int indent, int i, bool script)
1240 {
1241     if (isDynamicFieldsNode())
1242         TheApp->setDynamicFieldsNode();
1243 
1244     if (!m_proto) return(0);
1245     bool x3d = m_scene->isX3d();
1246     const char *oldBase = m_scene->getURL();
1247     const char *newBase = m_scene->getNewURL();
1248     bool tempSave = m_scene->isTempSave();
1249 
1250     Field *field = m_proto->getField(i);
1251     if (m_scene->isInvalidElement(field))
1252         return 0;
1253     FieldValue *value = m_fields[i];
1254     const char *name = field->getName(x3d);
1255     bool hasIsName = false;
1256     const char *isName = searchIsName(i, EL_FIELD);
1257     if (isName)
1258         hasIsName = true;
1259     else {
1260         isName = searchIsName(i, EL_EXPOSED_FIELD);
1261         if (isName)
1262             hasIsName = true;
1263     }
1264     if (hasIsName)
1265         RET_ONERROR( writeIs(f, indent, name, isName) )
1266     else if (value) {
1267         if (script || (value->getRefs() &&
1268                         (!value->equals(field->getDefault(x3d))))) {
1269             RET_ONERROR( indentf(f, indent) )
1270             RET_ONERROR( mywritestr(f , name) )
1271             RET_ONERROR( mywritestr(f ," ") )
1272             if ((field->getFlags() & FF_URL) && (!TheApp->GetKeepURLs())) {
1273                 value = rewriteField(value, oldBase, newBase,
1274                                      m_scene->getWriteFlags());
1275                 RET_ONERROR( mywritef(f, "\n[\n\"") )
1276                 RET_ONERROR( value->writeRaw(f, 0) )
1277                 RET_ONERROR( mywritef(f, "\"\n]\n") )
1278                 if (!tempSave) {
1279                     setField(i, value);
1280                     FieldUpdate* fieldUpdate=new FieldUpdate((Node*)this, i);
1281                     m_scene->UpdateViews(NULL, UPDATE_FIELD,
1282                                          (Hint *) fieldUpdate);
1283                     delete fieldUpdate;
1284                 } else {
1285                     delete value;
1286                 }
1287             } else {
1288                 RET_ONERROR( value->write(f, indent) )
1289             }
1290         }
1291     }
1292     if (isDynamicFieldsNode())
1293         TheApp->unsetDynamicFieldsNode();
1294     return(0);
1295 }
1296 
1297 int
writeXmlField(int f,int indent,int i,int when,bool script,int containerField,bool avoidUse)1298 NodeData::writeXmlField(int f, int indent, int i, int when, bool script,
1299                         int containerField, bool avoidUse)
1300 {
1301     if (!m_proto) return(0);
1302     const char *oldBase = m_scene->getURL();
1303     const char *newBase = m_scene->getNewURL();
1304     bool tempSave = m_scene->isTempSave();
1305     bool x3d = m_scene->isX3d();
1306 
1307     Field *field = m_proto->getField(i);
1308     if (m_scene->isInvalidElement(field))
1309         return 0;
1310     bool isNode = (field->getType() == SFNODE) || (field->getType() == MFNODE);
1311     bool isScript = field->getFlags() & FF_IN_SCRIPT;
1312     bool isScriptUrl = field->getFlags() & FF_SCRIPT_URL;
1313     bool inTag = (when == XML_IN_TAG);
1314     FieldValue *value = m_fields[i];
1315     const char *name = field->getName(x3d);
1316     const char *isName = searchIsName(i, EL_FIELD);
1317     if (when == XML_IS) {
1318         if (isName)
1319             RET_ONERROR( writeXmlIs(f, indent, name, isName) )
1320         else
1321             return 0;
1322     } else if (when == XML_PROTO_INSTANCE_FIELD) {
1323         if (isName)
1324             RET_ONERROR( writeXmlIs(f, indent, name, isName) )
1325         else
1326             RET_ONERROR( writeXmlProtoInstanceField(f, indent, name, value) )
1327     } else if (value) {
1328         int size = 1;
1329         MFString *urls = NULL;
1330         if (isScriptUrl) {
1331             urls = ((NodeScript *)this)->url();
1332             size = urls->getSize();
1333         }
1334         if (inTag && isScript)
1335             return 0;
1336         if (inTag && isScriptUrl) {
1337             int count = 0;
1338             for (int j = 0; j < size; j++)
1339                 if (!isSortOfEcmascript(urls->getValue(j)))
1340                     count++;
1341             if (count == 0)
1342                 return 0;
1343             else if (size > 0) {
1344                 RET_ONERROR( mywritestr(f ,"url='") )
1345                 for (int j = 0; j < size; j++) {
1346                     if (!isSortOfEcmascript(urls->getValue(j))) {
1347                         if (j > 0)
1348                             RET_ONERROR( mywritestr(f, " ") )
1349                         RET_ONERROR( mywritestr(f, "\"") )
1350                         RET_ONERROR( mywritestr(f, rewriteURL(urls->getValue(j),
1351                                                    oldBase, newBase)) )
1352                         RET_ONERROR( mywritestr(f, "\"") )
1353                     }
1354                 }
1355                 RET_ONERROR( mywritestr(f, "'") )
1356             }
1357         } else if (isScriptUrl) {
1358             for (int j = 0; j < size; j++) {
1359                 if (isSortOfEcmascript(urls->getValue(j))) {
1360                     RET_ONERROR( indentf(f, indent + TheApp->GetIndent()) )
1361                     RET_ONERROR( mywritestr(f, "<![CDATA[") )
1362                     RET_ONERROR( mywritestr(f, urls->getValue(j)) )
1363                     RET_ONERROR( indentf(f, indent + TheApp->GetIndent()) )
1364                     RET_ONERROR( mywritestr(f, "\n") )
1365                     TheApp->incSelectionLinenumber();
1366                     RET_ONERROR( indentf(f, indent + TheApp->GetIndent()) )
1367                     RET_ONERROR( mywritestr(f, "]]>\n") )
1368                     TheApp->incSelectionLinenumber();
1369                 }
1370             }
1371         } else if (isScript) {
1372             int flags = m_scene->getWriteFlags();
1373             const char *isName = searchIsName(i, EL_FIELD);
1374             if ((value->isNullNode()) && (!isName))
1375                 flags |= NULL_VALUE;
1376             else if (isNode)
1377                 flags |= WITHOUT_VALUE;
1378             if (isName)
1379                 flags |= WITHOUT_VALUE;
1380             if (isName) {
1381                 return 0;
1382                 RET_ONERROR( indentf(f, indent + TheApp->GetIndent()) )
1383                 RET_ONERROR( mywritef(f,
1384                     "<IS> <connect nodeField=\"%s\" protoField=\"%s\"/> </IS>\n",
1385                     name, isName) )
1386                 TheApp->incSelectionLinenumber();
1387             } else
1388                 RET_ONERROR( field->writeElementPart(f, indent, flags) )
1389             if (isName)
1390                 return 0;
1391             if (flags & NULL_VALUE)
1392                 if (!(flags & WITHOUT_VALUE)) {
1393                     RET_ONERROR( mywritestr(f, " value='NULL'") )
1394                 }
1395             int type = field->getType();
1396             bool nodeField = (type == SFNODE) || (type == MFNODE);
1397             if ((flags & NULL_VALUE) && (!(flags & WITHOUT_VALUE))) {
1398                 RET_ONERROR( mywritestr(f, "></field>\n") )
1399                 TheApp->incSelectionLinenumber();
1400             } else if (nodeField ) {
1401                 RET_ONERROR( mywritestr(f, ">\n") )
1402                 TheApp->incSelectionLinenumber();
1403                 RET_ONERROR( value->writeXml(f, indent + TheApp->GetIndent()) )
1404                 RET_ONERROR( indentf(f, indent + TheApp->GetIndent()) )
1405                 RET_ONERROR( mywritestr(f, "</field>\n") )
1406                 TheApp->incSelectionLinenumber();
1407             } else {
1408                 RET_ONERROR( mywritestr(f, " value=") )
1409                 RET_ONERROR( value->writeXml(f, 0) )
1410                 RET_ONERROR( mywritestr(f, " ></field>\n") )
1411                 TheApp->incSelectionLinenumber();
1412             }
1413         } else if (!inTag && !isNode)
1414             return 0;
1415         else if (inTag && isNode)
1416             return 0;
1417         else if (!value->equals(field->getDefault(x3d))) {
1418             if (inTag) {
1419                 RET_ONERROR( mywritestr(f , name) )
1420                 RET_ONERROR( mywritestr(f ,"=") )
1421             }
1422             if ((field->getFlags() & FF_URL) && (!TheApp->GetKeepURLs())) {
1423                 value = rewriteField(value, oldBase, newBase,
1424                                      m_scene->getWriteFlags());
1425                 RET_ONERROR( value->writeXml(f, indent) )
1426                 if (!tempSave) {
1427                      setField(i, value);
1428                      FieldUpdate* fieldUpdate=new FieldUpdate((Node*)this, i);
1429                      m_scene->UpdateViews(NULL, UPDATE_FIELD,
1430                                           (Hint *) fieldUpdate);
1431                      delete fieldUpdate;
1432                 } else {
1433                     delete value;
1434                 }
1435             } else {
1436                 RET_ONERROR( value->writeXml(f, indent, containerField,
1437                                              avoidUse) )
1438             }
1439             if (inTag) {
1440                 RET_ONERROR( mywritestr(f ," ") )
1441             }
1442         }
1443     }
1444     return(0);
1445 }
1446 
1447 int
writeEventIn(int f,int indent,int i,bool eventName)1448 NodeData::writeEventIn(int f, int indent, int i, bool eventName)
1449 {
1450     if (!m_proto) return(0);
1451 
1452     bool x3d = m_scene->isX3dv();
1453 
1454     EventIn *eventIn = m_proto->getEventIn(i);
1455     const char *name = eventIn->getName(x3d);
1456     const char *isName = searchIsName(i, EL_EVENT_IN);
1457     if (isName)
1458         RET_ONERROR( writeIs(f, indent, name, isName) )
1459     else if (eventName) {
1460         RET_ONERROR( mywritestr(f, name) )
1461         RET_ONERROR( mywritestr(f, "\n") )
1462         TheApp->incSelectionLinenumber();
1463     }
1464     return(0);
1465 }
1466 
1467 int
writeXmlEventIn(int f,int indent,int i,int when,bool eventName)1468 NodeData::writeXmlEventIn(int f, int indent, int i, int when, bool eventName)
1469 {
1470     if (!m_proto) return(0);
1471 
1472     bool x3d = m_scene->isX3dv();
1473 
1474     EventIn *eventIn = m_proto->getEventIn(i);
1475     bool isScript = eventIn->getFlags() & FF_IN_SCRIPT;
1476     bool inTag = (when == XML_IN_TAG);
1477     const char *name = eventIn->getName(x3d);
1478     if (when == XML_IS) {
1479         const char *isName = searchIsName(i, EL_EVENT_IN);
1480         if (isName)
1481             RET_ONERROR( writeXmlIs(f, indent, name, isName) )
1482     } else if (inTag && isScript) {
1483             return 0;
1484     } else if (isScript) {
1485         int flags = m_scene->getWriteFlags();
1486         RET_ONERROR( eventIn->write(f, indent, flags) )
1487         TheApp->incSelectionLinenumber();
1488     } else if (eventName) {
1489         RET_ONERROR( mywritestr(f, name) )
1490         RET_ONERROR( mywritestr(f, "\n") )
1491         TheApp->incSelectionLinenumber();
1492     }
1493     return(0);
1494 }
1495 
1496 
1497 int
writeEventInStr(int f)1498 NodeData::writeEventInStr(int f)
1499 {
1500     if (m_scene->isX3d())
1501         RET_ONERROR( mywritestr(f, "inputOnly") )
1502     else
1503         RET_ONERROR( mywritestr(f, "eventIn") )
1504     return 0;
1505 }
1506 
1507 int
writeEventOutStr(int f)1508 NodeData::writeEventOutStr(int f)
1509 {
1510     if (m_scene->isX3d())
1511         RET_ONERROR( mywritestr(f, "outputOnly") )
1512     else
1513         RET_ONERROR( mywritestr(f, "eventOut") )
1514     return 0;
1515 }
1516 
1517 int
writeFieldStr(int f)1518 NodeData::writeFieldStr(int f)
1519 {
1520     if (m_scene->isX3d())
1521         RET_ONERROR( mywritestr(f, "initializeOnly") )
1522     else
1523         RET_ONERROR( mywritestr(f, "field") )
1524     return 0;
1525 }
1526 
1527 int
writeExposedFieldStr(int f)1528 NodeData::writeExposedFieldStr(int f)
1529 {
1530     if (m_scene->isX3d())
1531         RET_ONERROR( mywritestr(f, "inputOutput") )
1532     else
1533         RET_ONERROR( mywritestr(f, "exposedField") )
1534     return 0;
1535 }
1536 
1537 
1538 int
writeEventOut(int f,int indent,int i,bool eventName)1539 NodeData::writeEventOut(int f, int indent, int i, bool eventName)
1540 {
1541     if (!m_proto) return(0);
1542 
1543     bool x3d = m_scene->isX3dv();
1544 
1545     EventOut *eventOut = m_proto->getEventOut(i);
1546     const char *name = eventOut->getName(x3d);
1547     const char *isName = searchIsName(i, EL_EVENT_OUT);
1548     if (isName)
1549         RET_ONERROR( writeIs(f, indent, name, isName) )
1550     else if (eventName) {
1551         RET_ONERROR( mywritestr(f, name) )
1552         RET_ONERROR( mywritestr(f, "\n") )
1553         TheApp->incSelectionLinenumber();
1554     }
1555     return(0);
1556 }
1557 
1558 int
writeXmlEventOut(int f,int indent,int i,int when,bool eventName)1559 NodeData::writeXmlEventOut(int f, int indent, int i, int when, bool eventName)
1560 {
1561     if (!m_proto) return(0);
1562 
1563     bool x3d = m_scene->isX3dv();
1564 
1565     EventOut *eventOut = m_proto->getEventOut(i);
1566     bool isScript = eventOut->getFlags() & FF_IN_SCRIPT;
1567     bool inTag = (when == XML_IN_TAG);
1568     const char *name = eventOut->getName(x3d);
1569     if (when == XML_IS) {
1570         const char *isName = searchIsName(i, EL_EVENT_OUT);
1571         if (isName)
1572             RET_ONERROR( writeXmlIs(f, indent, name, isName) )
1573     } else if (inTag && isScript) {
1574             return 0;
1575     } else if (isScript) {
1576         int flags = m_scene->getWriteFlags();
1577         RET_ONERROR( eventOut->write(f, indent, flags) )
1578         TheApp->incSelectionLinenumber();
1579     } else if (eventName) {
1580         RET_ONERROR( mywritestr(f, name) )
1581         RET_ONERROR( mywritestr(f, "\n") )
1582         TheApp->incSelectionLinenumber();
1583     }
1584     return(0);
1585 }
1586 
1587 int
writeRoutes(int f,int indent) const1588 NodeData::writeRoutes(int f, int indent) const
1589 {
1590     if (!m_proto) return(0);
1591 
1592     bool x3d = m_scene->isX3d();
1593 
1594     SocketList::Iterator *j;
1595 
1596     for (int i = 0; i < m_numEventIns; i++) {
1597         for (j = m_inputs[i].first(); j != NULL; j = j->next()) {
1598             if (j->item().getNode()->getFlag(NODE_FLAG_TOUCHED)) {
1599                 Node *src = j->item().getNode();
1600                 int field = j->item().getField();
1601                 if ((m_scene->getWriteFlags() & X3DOM) &&
1602                     (j->item().getNode()->getType() == VRML_SCRIPT)) {
1603                     NodeScript *script = (NodeScript *)j->item().getNode();
1604                     bool flag = false;
1605                     for (int i = 0; i < script->url()->getSize(); i++)
1606                         if (isX3domscript(script->url()->getValue(i)))
1607                             flag = true;
1608                     if (flag)
1609                         continue;
1610 
1611                 }
1612                 if (m_scene->isPureVRML() &&
1613                     (matchNodeClass(PARAMETRIC_GEOMETRY_NODE) ||
1614                      src->matchNodeClass(PARAMETRIC_GEOMETRY_NODE)))
1615                     continue;
1616                 MyString routeString = m_scene->createRouteString(
1617                       src->getName(),
1618                       src->getProto()->getEventOut(field)->getName(x3d),
1619                       m_name, getProto()->getEventIn(i)->getName(x3d));
1620                 m_scene->addRouteString(routeString);
1621             }
1622         }
1623     }
1624 
1625     for (int i = 0; i < m_numEventOuts; i++) {
1626         for (j = m_outputs[i].first(); j != NULL; j = j->next()) {
1627             if (j->item().getNode()->getFlag(NODE_FLAG_TOUCHED)) {
1628                 Node *dst = j->item().getNode();
1629                 int field = j->item().getField();
1630                 if (m_scene->isPureVRML() &&
1631                     (matchNodeClass(PARAMETRIC_GEOMETRY_NODE) ||
1632                      dst->matchNodeClass(PARAMETRIC_GEOMETRY_NODE)))
1633                     continue;
1634                 if (getProto()->getEventOut(i)->getName(x3d).length() == 0)
1635                     continue;
1636                 MyString routestring = m_scene->createRouteString(m_name,
1637                          getProto()->getEventOut(i)->getName(x3d),
1638                          dst->getName(),
1639                          dst->getProto()->getEventIn(field)->getName(x3d));
1640                 m_scene->addRouteString(routestring);
1641             }
1642         }
1643     }
1644 
1645 #ifndef HAVE_ROUTE_AT_END
1646     if (indent==0)
1647        RET_ONERROR( m_scene->writeRouteStrings(f, indent, true) )
1648 #endif
1649     return 0;
1650 }
1651 
1652 void
removeRoutes(void)1653 NodeData::removeRoutes(void)
1654 {
1655     if (!m_proto) return;
1656 
1657     for (int i = 0; i < m_numEventIns; i++) {
1658         while (m_inputs[i].size() > 0) {
1659             SocketList::Iterator *j = m_inputs[i].first();
1660             Node *src = j->item().getNode();
1661             int field = j->item().getField();
1662             m_scene->deleteRoute(src, field, (Node *)this, i);
1663         }
1664     }
1665 
1666     for (int i = 0; i < m_numEventOuts; i++) {
1667         while (m_outputs[i].size() > 0) {
1668             SocketList::Iterator *j = m_outputs[i].first();
1669             Node *dst = j->item().getNode();
1670             int field = j->item().getField();
1671             m_scene->deleteRoute((Node *)this, i, dst, field);
1672         }
1673     }
1674 }
1675 
1676 int
writeCDataFunctionFields(int filedes,int languageFlag,bool forward,bool cont)1677 Node::writeCDataFunctionFields(int filedes, int languageFlag,
1678                                bool forward, bool cont)
1679 {
1680     for (int i = 0; i < m_numFields; i++) {
1681         Field *field = m_proto->getField(i);
1682         FieldValue *value = m_fields[i];
1683 
1684         if (field->getType() == SFNODE) {
1685             if (value) {
1686                 Node *node = ((SFNode *)value)->getValue();
1687                 if (node && (node != this)) { // avoid simple cyclic scenegraph
1688                     RET_ONERROR( node->writeCDataFunction(filedes,
1689                                                           languageFlag,
1690                                                           forward, cont) )
1691                 }
1692             }
1693         } else if (field->getType() == MFNODE) {
1694             if (value) {
1695                 MFNode *nodes = (MFNode *)value;
1696                 for (int i = 0; i < nodes->getSize(); i++) {
1697                     Node *node = nodes->getValue(i);
1698                     if (node && (node != this)) { //avoid simple cyclic scenegraph
1699                         RET_ONERROR( node->writeCDataFunction(filedes,
1700                                                               languageFlag,
1701                                                               forward, cont) )
1702                     }
1703                 }
1704             }
1705         }
1706     }
1707     if ((!cont) && (!isConvertedInCurveAnimaton()))
1708         RET_ONERROR( mywritestr(filedes , "    }\n") )
1709     return 0;
1710 }
1711 
1712 int
writeCGetParent(int filedes,int languageFlag)1713 Node::writeCGetParent(int filedes, int languageFlag)
1714 {
1715     if (getType() == DUNE_CURVE_ANIMATION)
1716         return 0;
1717 
1718     RET_ONERROR( mywritestr(filedes, "         if (") )
1719     RET_ONERROR( writeCVariable(filedes, languageFlag) )
1720     if (languageFlag & JAVA_SOURCE)
1721         RET_ONERROR( mywritestr(filedes, " != null") )
1722     RET_ONERROR( mywritestr(filedes, ")\n") )
1723 
1724     RET_ONERROR( mywritestr(filedes, "              ") )
1725     RET_ONERROR( writeCVariable(filedes, languageFlag) )
1726     RET_ONERROR( mywritestr(filedes, ".m_parent = ") )
1727 
1728     if (hasParent()) {
1729         RET_ONERROR( getParent()->writeCVariable(filedes, languageFlag) )
1730     } else {
1731         if (languageFlag & JAVA_SOURCE)
1732             RET_ONERROR( mywritestr(filedes, "null") )
1733         else
1734             RET_ONERROR( mywritestr(filedes, "NULL") )
1735     }
1736     RET_ONERROR( mywritestr(filedes, ";\n") )
1737     return 0;
1738 }
1739 
1740 int
writeCDataFunction(int filedes,int languageFlag,bool forward,bool cont)1741 Node::writeCDataFunction(int filedes, int languageFlag, bool forward, bool cont)
1742 {
1743     if (getWritten())
1744         return 0;
1745 
1746     if (m_convertedNodes.size() > 0) {
1747         for (long i = 0; i < m_convertedNodes.size(); i++)
1748             RET_ONERROR( m_convertedNodes[i]->writeCDataFunction(filedes,
1749                                                                  languageFlag,
1750                                                                  forward,
1751                                                                  cont) )
1752         setWritten(true);
1753         return 0;
1754     }
1755 
1756     if (!isCWriteable())
1757         return 0;
1758 
1759     if (forward)
1760         writeCDataFunctionFields(filedes, languageFlag, forward, cont);
1761 
1762     if (m_numberCDataFunctions >= 0) {
1763         if (!cont){
1764             RET_ONERROR( mywritestr(filedes , "    ") )
1765             if ((languageFlag & MANY_JAVA_CLASSES) &&
1766                 !isConvertedInCurveAnimaton()) {
1767                 RET_ONERROR( mywritestr(filedes , "static ") )
1768                 RET_ONERROR( mywritef(filedes , "void data%sFunction%d() {\n",
1769                              TheApp->getCPrefix(),
1770                              m_scene->getNumDataFunctions()) )
1771             }
1772         }
1773         m_scene->increaseNumDataFunctions();
1774         if (languageFlag & MANY_JAVA_CLASSES) {
1775             if (!isPROTO()) {
1776                 RET_ONERROR( mywritestr(filedes, "    ") )
1777                 if (languageFlag & MANY_JAVA_CLASSES)
1778                     RET_ONERROR( mywritestr(filedes, "    ") )
1779                 RET_ONERROR( writeCVariable(filedes, languageFlag) )
1780                 RET_ONERROR( mywritestr(filedes, " = new ") )
1781                 RET_ONERROR( mywritestr(filedes, getClassName()) )
1782                 RET_ONERROR( mywritestr(filedes, "();\n") )
1783             }
1784         }
1785 
1786         if (languageFlag & JAVA_SOURCE) {
1787             if (languageFlag & MANY_JAVA_CLASSES)
1788                 RET_ONERROR( mywritestr(filedes, "    ") )
1789         }
1790         RET_ONERROR( mywritestr(filedes, "    ") )
1791         if (languageFlag & C_SOURCE)
1792             RET_ONERROR( mywritestr(filedes, "self->") )
1793         RET_ONERROR( writeCVariable(filedes, languageFlag) )
1794         RET_ONERROR( mywritestr(filedes, ".m_parent = ") )
1795 
1796         if (hasParent()) {
1797             if (languageFlag & (C_SOURCE | CC_SOURCE))
1798                 RET_ONERROR( mywritestr(filedes, "&") )
1799             if (languageFlag & C_SOURCE)
1800                 RET_ONERROR( mywritestr(filedes, "self->") )
1801             RET_ONERROR( getParent()->writeCVariable(filedes, languageFlag) )
1802         } else {
1803             if (languageFlag & JAVA_SOURCE)
1804                 RET_ONERROR( mywritestr(filedes, "null") )
1805             else
1806                 RET_ONERROR( mywritestr(filedes, "NULL") )
1807         }
1808         RET_ONERROR( mywritestr(filedes, ";\n") )
1809 
1810         if ( m_numberCDataFunctions > 0) {
1811             if (languageFlag & MANY_JAVA_CLASSES)
1812                 RET_ONERROR( mywritef(filedes ,
1813                                       "        new %s%sDataClass0();\n",
1814                                       TheApp->getPrefix(), getVariableName()) )
1815             else
1816                 RET_ONERROR( mywritef(filedes ,
1817                                       "        %s%sDataFunction0();\n",
1818                                       TheApp->getPrefix(), getVariableName()) )
1819         }
1820         for (int i = 1; i < m_numberCDataFunctions; i++)
1821             if (languageFlag & MANY_JAVA_CLASSES)
1822                 RET_ONERROR( mywritef(filedes ,
1823                                       "        new %s%sDataClass%d();\n",
1824                                       TheApp->getPrefix(), getVariableName(),
1825                                       i) )
1826             else
1827                 RET_ONERROR( mywritef(filedes ,
1828                                       "        %s%sDataFunction%d();\n",
1829                                       TheApp->getPrefix(), getVariableName(),
1830                                       i) )
1831     }
1832 
1833     if (!forward)
1834         writeCDataFunctionFields(filedes, languageFlag, forward, cont);
1835 
1836     if (hasProtoNodes()) {
1837         Node *protoRoot = ((NodePROTO *)this)->getProtoRoot();
1838         RET_ONERROR( protoRoot->writeCDataFunction(filedes, languageFlag,
1839                                                    forward, cont))
1840 
1841         NodePROTO *nodeProto = (NodePROTO *)this;
1842         for (int i = 1; i < nodeProto->getNumProtoNodes(); i++) {
1843             RET_ONERROR( nodeProto->getProtoNode(i)->writeCDataFunction(
1844                              filedes, languageFlag, cont) )
1845        }
1846     }
1847 
1848     setWritten(true);
1849     return 0;
1850 }
1851 
1852 int
writeC(int f,int languageFlag)1853 Node::writeC(int f, int languageFlag)
1854 {
1855     if (m_convertedNodes.size() > 0) {
1856         for (long i = 0; i < m_convertedNodes.size(); i++)
1857             RET_ONERROR( m_convertedNodes[i]->writeC(f, languageFlag) )
1858         return 0;
1859     }
1860 
1861     if (getType() == VRML_COMMENT) {
1862         return 0;
1863     }
1864     if (m_proto->isMismatchingProto()) {
1865         return 0;
1866     }
1867 
1868     if (isMeshBasedNode() && (!getIndexedFaceSet())) {
1869         RET_ONERROR( mywritef(f, "    ") )
1870         if (languageFlag & C_SOURCE)
1871             RET_ONERROR( mywritef(f, "%sSetGlName(&self->%s, %d);\n",
1872                                   TheApp->getCPrefix(), getVariableName(),
1873                                   m_scene->getGlName()) )
1874         else {
1875             if (languageFlag & JAVA_SOURCE) {
1876                 MyString className = "";
1877                 className += TheApp->getCPrefix();
1878                 className += getVariableName();
1879                 RET_ONERROR( mywritef(f, "%s.", (const char *)className) )
1880             }
1881             RET_ONERROR( mywritef(f, "%s.setGlName(%d);\n", getVariableName(),
1882                                   m_scene->getGlName()) )
1883         }
1884         CGlNameData data;
1885         data.glName = m_scene->getGlName();
1886         data.node = this;
1887         data.nodeName = "";
1888         data.nodeName += getVariableName();
1889         m_scene->m_glNameData.append(data);
1890         m_scene->increaseGlName();
1891     }
1892     if (getType() == VRML_TRANSFORM) {
1893         int numRouteSources = 0;
1894         for (int i = 0; i < m_numEventIns; i++)
1895             for (SocketList::Iterator *j = m_inputs[i].first(); j != NULL;
1896                  j = j->next())
1897                 if (j->item().getNode()->getProto()->isCRouteSource()) {
1898                     numRouteSources++;
1899                 }
1900         RET_ONERROR( mywritestr(f, "    ") )
1901         if (languageFlag & JAVA_SOURCE)
1902             RET_ONERROR( mywritestr(f, "        ") )
1903         if (languageFlag & C_SOURCE)
1904             RET_ONERROR( mywritestr(f, "self->") )
1905         MyString className = "";
1906         if (languageFlag & JAVA_SOURCE) {
1907             className += TheApp->getCPrefix();
1908             className += getVariableName();
1909             RET_ONERROR( mywritef(f, "%s.", (const char *)className) )
1910         }
1911         RET_ONERROR( mywritef(f, "%s.route_sources = ", getVariableName()) )
1912         if (numRouteSources == 0) {
1913             if (languageFlag & JAVA_SOURCE)
1914                 RET_ONERROR( mywritestr(f, " null;\n") )
1915             else
1916                 RET_ONERROR( mywritestr(f, " NULL;\n") )
1917         } else {
1918             if (languageFlag & C_SOURCE)
1919                 RET_ONERROR( mywritef(f,
1920                                  "(%sNode **)malloc(%d * sizeof(%sNode *));\n",
1921                                  TheApp->getCPrefix(), numRouteSources,
1922                                  TheApp->getCPrefix()) )
1923             else if (languageFlag & CC_SOURCE)
1924                 RET_ONERROR( mywritef(f, "new %sNode*[%d];\n",
1925                                       TheApp->getCPrefix(), numRouteSources) )
1926             else if (languageFlag & JAVA_SOURCE)
1927                 RET_ONERROR( mywritef(f, "new %sNode[%d];\n",
1928                                       TheApp->getCPrefix(), numRouteSources) )
1929         }
1930         numRouteSources = 0;
1931         for (int i = 0; i < m_numEventIns; i++)
1932             for (SocketList::Iterator *j = m_inputs[i].first(); j != NULL;
1933                  j = j->next())
1934                 if (j->item().getNode()->getProto()->isCRouteSource()) {
1935                     RET_ONERROR( mywritestr(f, "    ") )
1936                     if (languageFlag & JAVA_SOURCE)
1937                         RET_ONERROR( mywritef(f, "        %s.",
1938                                                  (const char *)className) )
1939                     if (languageFlag & C_SOURCE)
1940                         RET_ONERROR( mywritestr(f, "self->") )
1941                     RET_ONERROR( mywritef(f, "%s.route_sources[%d] = ",
1942                                  getVariableName(), numRouteSources) )
1943                     if (languageFlag & (C_SOURCE | CC_SOURCE))
1944                         RET_ONERROR( mywritestr(f, "&") )
1945                     if (languageFlag & JAVA_SOURCE)
1946                         RET_ONERROR( mywritef(f, "%s%s.", TheApp->getCPrefix(),
1947                             j->item().getNode()->getVariableName()) )
1948 
1949                     if (languageFlag & C_SOURCE)
1950                         RET_ONERROR( mywritestr(f, "self->") )
1951                     RET_ONERROR( mywritestr(f,
1952                         j->item().getNode()->getVariableName()) )
1953                     RET_ONERROR( mywritestr(f, ";\n") )
1954                     numRouteSources++;
1955                 }
1956 
1957         RET_ONERROR( mywritef(f, "    ") )
1958         if (languageFlag & C_SOURCE)
1959             RET_ONERROR( mywritestr(f, "self->") )
1960         if (languageFlag & JAVA_SOURCE) {
1961             MyString className = "";
1962             className += TheApp->getCPrefix();
1963             className += getVariableName();
1964             RET_ONERROR( mywritef(f, "        %s.", (const char *)className) )
1965         }
1966         RET_ONERROR( mywritef(f, "%s.num_route_source = %d;\n",
1967                                  getVariableName(), numRouteSources) )
1968 
1969     }
1970 
1971     // allows several nodetypes to output a warning via inheritance
1972     writeCWarning();
1973 
1974     bool writeInside = true;
1975     if (languageFlag & MANY_JAVA_CLASSES)
1976         if (writeJavaOutsideClass(languageFlag))
1977             writeInside = false;
1978 
1979     if (languageFlag & C_SOURCE) {
1980         RET_ONERROR( mywritestr(f, "    ") )
1981         RET_ONERROR( mywritestr(f, getClassName()) )
1982         RET_ONERROR( mywritestr(f, "Init(&") )
1983         RET_ONERROR( writeCVariable(f, languageFlag) )
1984         RET_ONERROR( mywritestr(f, ");\n") )
1985     }
1986 
1987 
1988     if (languageFlag & (C_SOURCE | CC_SOURCE)) {
1989             RET_ONERROR( mywritestr(f, "    ") )
1990         if (languageFlag & C_SOURCE)
1991             RET_ONERROR( mywritestr(f, "self->") )
1992         RET_ONERROR( mywritestr(f, getVariableName()) )
1993         RET_ONERROR( mywritef(f, ".m_parent = (%sNode *)", TheApp->getCPrefix())
1994                    )
1995         if (getParent() == NULL)
1996             RET_ONERROR( mywritestr(f, "NULL") )
1997         else {
1998             RET_ONERROR( mywritestr(f, "&") )
1999             if (languageFlag & C_SOURCE)
2000                 RET_ONERROR( mywritestr(f, "self->") )
2001             RET_ONERROR( mywritestr(f, getParent()->getVariableName()) )
2002         }
2003         RET_ONERROR( mywritestr(f, ";\n") )
2004     }
2005     if (languageFlag & (C_SOURCE | CC_SOURCE)) {
2006         for (int i = 0; i < m_numFields; i++)
2007             RET_ONERROR( writeCElement(f, EL_FIELD, i, languageFlag, true) )
2008         for (int i = 0; i < m_numFields; i++)
2009             RET_ONERROR( writeCElement(f, EL_FIELD, i, languageFlag, false) )
2010         for (int i = 0; i < m_numEventIns; i++)
2011             RET_ONERROR( writeCElement(f, EL_EVENT_IN, i, languageFlag, true) )
2012         for (int i = 0; i < m_numEventIns; i++)
2013             RET_ONERROR( writeCElement(f, EL_EVENT_IN, i, languageFlag, false) )
2014         for (int i = 0; i < m_numEventOuts; i++)
2015             RET_ONERROR( writeCElement(f, EL_EVENT_OUT, i, languageFlag, true) )
2016         for (int i = 0; i < m_numEventOuts; i++)
2017             RET_ONERROR( writeCElement(f, EL_EVENT_OUT, i, languageFlag, false)
2018                        )
2019     }
2020 
2021     if (writeInside) {
2022         if (hasProtoNodes()) {
2023             if (languageFlag & JAVA_SOURCE) {
2024                 RET_ONERROR( mywritestr(f, "    ") )
2025                 if (languageFlag & MANY_JAVA_CLASSES)
2026                     RET_ONERROR( mywritestr(f, "    ") )
2027             }
2028             Node *protoRoot = ((NodePROTO *)this)->getProtoRoot();
2029             RET_ONERROR( protoRoot->writeC(f, languageFlag) )
2030 
2031             RET_ONERROR( mywritestr(f, "    ") )
2032             RET_ONERROR( writeCVariable(f, languageFlag) )
2033             RET_ONERROR( mywritestr(f, ".m_protoRoot = ") )
2034             if (languageFlag & (C_SOURCE | CC_SOURCE))
2035                 RET_ONERROR( mywritestr(f, "&") )
2036             RET_ONERROR( protoRoot->writeCVariable(f, languageFlag) )
2037             RET_ONERROR( mywritestr(f, ";\n") )
2038 
2039             NodePROTO *nodeProto = (NodePROTO *)this;
2040             for (int i = 1; i < nodeProto->getNumProtoNodes(); i++)
2041                  RET_ONERROR(nodeProto->getProtoNode(i)->writeC(f,
2042                                                                 languageFlag))
2043         }
2044     }
2045 
2046     if (languageFlag & C_SOURCE)
2047         if (this == m_scene->getRoot())
2048             RET_ONERROR( mywritestr(f, "    {\n") )
2049 
2050     if (languageFlag & C_SOURCE) {
2051         RET_ONERROR( mywritestr(f, "    self->") )
2052         RET_ONERROR( mywritestr(f, getVariableName()) )
2053         RET_ONERROR( mywritestr(f, ".") )
2054         RET_ONERROR( mywritestr(f, "m_") )
2055         RET_ONERROR( mywritestr(f, "type = ") )
2056         if (hasProtoNodes())
2057             RET_ONERROR( mywritef(f, "%d", m_scene->getProtoType(m_proto)) )
2058         else
2059             RET_ONERROR( mywritef(f, "%d", getType()) )
2060         RET_ONERROR( mywritestr(f, ";\n") )
2061 
2062         RET_ONERROR( mywritestr(f, "    self->") )
2063         RET_ONERROR( mywritestr(f, getVariableName()) )
2064         RET_ONERROR( mywritestr(f, ".") )
2065         RET_ONERROR( mywritestr(f, "m_") )
2066         RET_ONERROR( mywritestr(f, "data = NULL") )
2067         RET_ONERROR( mywritestr(f, ";\n") )
2068     }
2069 
2070     return 0;
2071 }
2072 
2073 int
writeCDataAsFunctions(int f,int languageFlag,bool cont)2074 Node::writeCDataAsFunctions(int f, int languageFlag, bool cont)
2075 {
2076     if (m_convertedNodes.size() > 0) {
2077         for (long i = 0; i < m_convertedNodes.size(); i++)
2078             RET_ONERROR( m_convertedNodes[i]->writeCDataAsFunctions(f,
2079                                                                    languageFlag)
2080                        )
2081         return 0;
2082     }
2083 
2084     if (getType() == VRML_COMMENT)
2085         return 0;
2086     if (m_proto->isMismatchingProto())
2087         return 0;
2088 
2089     // do not write multiple declarations for USE'd nodes
2090     if (getFlag(NODE_FLAG_TOUCHED))
2091         return 0;
2092     setFlag(NODE_FLAG_TOUCHED);
2093 
2094     if (languageFlag & (C_SOURCE | CC_SOURCE))
2095         return 0;
2096 
2097     m_numberCDataFunctions = 0;
2098 
2099     for (int i = 0; i < m_numFields; i++)
2100         RET_ONERROR( writeCElementFunction(f, EL_FIELD, i, languageFlag, true,
2101                                            cont) )
2102     for (int i = 0; i < m_numFields; i++)
2103         RET_ONERROR( writeCElementFunction(f, EL_FIELD, i, languageFlag, false,
2104                                            cont) )
2105     for (int i = 0; i < m_numEventIns; i++)
2106         RET_ONERROR( writeCElementFunction(f, EL_EVENT_IN, i, languageFlag,
2107                                            true, cont))
2108     for (int i = 0; i < m_numEventIns; i++)
2109         RET_ONERROR( writeCElementFunction(f, EL_EVENT_IN, i, languageFlag,
2110                                            false, cont))
2111     for (int i = 0; i < m_numEventOuts; i++)
2112         RET_ONERROR( writeCElementFunction(f, EL_EVENT_OUT, i, languageFlag,
2113                                            true, cont))
2114     for (int i = 0; i < m_numEventOuts; i++)
2115         RET_ONERROR( writeCElementFunction(f, EL_EVENT_OUT, i, languageFlag,
2116                                            false, cont))
2117 
2118     if (hasProtoNodes()) {
2119         Node *protoRoot = ((NodePROTO *)this)->getProtoRoot();
2120         RET_ONERROR( protoRoot->writeCDataAsFunctions(f, languageFlag) )
2121 
2122         NodePROTO *nodeProto = (NodePROTO *)this;
2123         for (int i = 1; i < nodeProto->getNumProtoNodes(); i++)
2124             RET_ONERROR( nodeProto->getProtoNode(i)->writeCDataAsFunctions(
2125                              f, languageFlag, cont) )
2126     }
2127     return 0;
2128 }
2129 
2130 int
writeCElementFunction(int f,int elementType,int i,int languageFlag,bool nodeFlag,bool cont)2131 Node::writeCElementFunction(int f, int elementType, int i, int languageFlag,
2132                             bool nodeFlag, bool cont)
2133 {
2134     if (m_convertedNodes.size() > 0) {
2135         for (long j = 0; j < m_convertedNodes.size(); j++)
2136             RET_ONERROR( m_convertedNodes[j]->writeCElementFunction(f,
2137                                elementType, i, languageFlag, nodeFlag, cont) )
2138         return 0;
2139     }
2140 
2141     Element *element = m_proto->getElement(elementType, i);
2142     int type = element->getType();
2143 
2144     if (m_scene->isInvalidElement(element))
2145         return 0;
2146 
2147     if (nodeFlag)
2148         if ((type != SFNODE) && (type != MFNODE))
2149             return 0;
2150 
2151     FieldValue *value = NULL;
2152     switch(elementType) {
2153       case EL_FIELD:
2154         value = m_fields[i];
2155         break;
2156       case EL_EVENT_IN:
2157         if (m_proto->getEventIn(i)->getExposedField() != NULL)
2158             return 0;
2159         value = typeDefaultValue(type);
2160         break;
2161       case EL_EVENT_OUT:
2162         if (m_proto->getEventOut(i)->getExposedField() != NULL)
2163             return 0;
2164         value = typeDefaultValue(type);
2165         break;
2166       default:
2167         assert(0);
2168     }
2169 
2170     if (value->writeType(languageFlag)) {
2171         if ((!cont) && languageFlag & MANY_JAVA_CLASSES) {
2172             RET_ONERROR( mywritef(f, "    class %s%sDataClass%d {\n",
2173                                   TheApp->getPrefix(), getVariableName(),
2174                                   m_numberCDataFunctions,
2175                                   (const char*)getClassName()) )
2176             RET_ONERROR( mywritef(f, "        public %s%sDataClass%d() {\n",
2177                                   TheApp->getPrefix(), getVariableName(),
2178                                   m_numberCDataFunctions) )
2179         } else
2180             RET_ONERROR( mywritef(f, "    void %sDataFunction%d() {\n",
2181                                   getVariableName(), m_numberCDataFunctions,
2182                                   (const char*)getClassName()) )
2183         m_numberCDataFunctions++;
2184         RET_ONERROR( writeCElement(f, elementType, i, languageFlag, nodeFlag) )
2185         if (languageFlag & MANY_JAVA_CLASSES)
2186             RET_ONERROR( mywritestr(f, "        }\n") )
2187         RET_ONERROR( mywritestr(f, "    }\n") )
2188     } else if (!nodeFlag) {
2189         // write long array into a series of functions to fight against the
2190         // java "code too long" (64 KB) problem
2191         MFieldValue *mvalue = (MFieldValue *)value;
2192         int javaCodeToLongLimit = 1 << 16;
2193         int javaSizeOfLine = 8;
2194         int maxNumberElements = TheApp->GetWrittenElementsPerJavaArray();
2195         if (maxNumberElements == -1)
2196             maxNumberElements = javaCodeToLongLimit / mvalue->getStride() /
2197                                 javaSizeOfLine / 4;
2198         int numberFunctions = mvalue->getSFSize() / maxNumberElements + 1;
2199         int offset = 0;
2200         for (int i = 0; i < numberFunctions; i++) {
2201             if ((!cont) && languageFlag & MANY_JAVA_CLASSES) {
2202                 RET_ONERROR( mywritef(f, "    class %s%sDataClass%d {\n",
2203                                       TheApp->getPrefix(), getVariableName(),
2204                                       m_numberCDataFunctions,
2205                                       (const char*)getClassName()) )
2206                 RET_ONERROR( mywritef(f, "        public %s%sDataClass%d() {\n",
2207                                       TheApp->getPrefix(), getVariableName(),
2208                                       m_numberCDataFunctions) )
2209             } else
2210                 RET_ONERROR( mywritef(f, "    void %sDataFunction%d() {\n",
2211                                       getVariableName(),
2212                                       m_numberCDataFunctions) )
2213             m_numberCDataFunctions++;
2214             const char *elementName = element->getName(true);
2215 
2216             RET_ONERROR( mywritestr(f, "        ") )
2217             if (languageFlag & MANY_JAVA_CLASSES)
2218                 RET_ONERROR( mywritestr(f, "    ") )
2219             RET_ONERROR( mywritestr(f, getClassName()) )
2220             RET_ONERROR( mywritestr(f, " v = ") )
2221             if (languageFlag & MANY_JAVA_CLASSES) {
2222                 if (getIndexedFaceSet())
2223                      RET_ONERROR(getIndexedFaceSet()->
2224                                  writeCVariable(f, languageFlag) )
2225                 else
2226                      RET_ONERROR( writeCVariable(f, languageFlag) )
2227             } else
2228                 RET_ONERROR( writeCVariable(f, languageFlag) )
2229             RET_ONERROR( mywritestr(f, ";\n") )
2230 
2231             RET_ONERROR( mvalue->writeJavaLongArray(f, languageFlag,
2232                   elementName, offset, maxNumberElements,
2233                   TheApp->isWonderlandModuleExport() &&
2234                   (element->getFlags() & FF_WONDERLAND_ART), m_scene->getURL()) )
2235             if (languageFlag & MANY_JAVA_CLASSES)
2236                 RET_ONERROR( mywritestr(f, "        }\n") )
2237             RET_ONERROR( mywritestr(f, "    }\n") )
2238             offset += maxNumberElements;
2239         }
2240     }
2241 
2242     if (nodeFlag && (value->getType() == SFNODE)) {
2243         if (value) {
2244             Node *node = ((SFNode *)value)->getValue();
2245             if (node && (node != this)) // avoid simple cyclic scenegraph
2246                  RET_ONERROR( node->writeCDataAsFunctions(f, languageFlag) )
2247         }
2248     } else if (nodeFlag && (value->getType() == MFNODE)) {
2249         if (value) {
2250             MFNode *nodes = (MFNode *)value;
2251             for (int i = 0; i < nodes->getSize(); i++) {
2252                 Node *node = nodes->getValue(i);
2253                 if (node && (node != this)) // avoid simple cyclic scenegraph
2254                      RET_ONERROR(node->writeCDataAsFunctions(f, languageFlag) )
2255             }
2256         }
2257     }
2258 
2259     return 0;
2260 }
2261 
2262 int
writeCElement(int f,int elementType,int i,int languageFlag,bool nodeFlag)2263 Node::writeCElement(int f, int elementType, int i, int languageFlag,
2264                     bool nodeFlag)
2265 {
2266     if (!m_proto) return(0);
2267 
2268     Element *element = m_proto->getElement(elementType, i);
2269 
2270     if (m_scene->isInvalidElement(element))
2271         return 0;
2272 
2273     if (element->getFlags() & FF_X3DOM_ONLY)
2274         return 0;
2275 
2276     int type = element->getType();
2277 
2278     FieldValue *value = NULL;
2279     switch(elementType) {
2280       case EL_FIELD:
2281         value = m_fields[i];
2282         break;
2283       case EL_EVENT_IN:
2284         if (m_proto->getEventIn(i)->getExposedField() != NULL)
2285             return 0;
2286         value = typeDefaultValue(type);
2287         break;
2288       case EL_EVENT_OUT:
2289         if (m_proto->getEventOut(i)->getExposedField() != NULL)
2290             return 0;
2291         value = typeDefaultValue(type);
2292         break;
2293       default:
2294         assert(0);
2295     }
2296 
2297     const char *name = element->getName(true);
2298 
2299     if (nodeFlag && (value->getType() == SFNODE)) {
2300         if (value) {
2301             Node *node = ((SFNode *)value)->getValue();
2302             if (node && (node != this)) { // avoid simple cyclic scenegraph
2303                  node->addToConvertedNodes(m_scene->getWriteFlags());
2304                  RET_ONERROR( node->writeC(f, languageFlag) )
2305             }
2306         }
2307     } else if (nodeFlag && (value->getType() == MFNODE)) {
2308         if (value) {
2309             MFNode *nodes = (MFNode *)value;
2310             for (int i = 0; i < nodes->getSize(); i++) {
2311                 Node *node = nodes->getValue(i);
2312                 if (node && (node != this)) { // avoid simple cyclic scenegraph
2313                      node->addToConvertedNodes(m_scene->getWriteFlags());
2314                      RET_ONERROR( node->writeC(f, languageFlag) )
2315                 }
2316             }
2317         }
2318     } else if (!nodeFlag) {
2319         if (value->isArrayInC()) {
2320             if (languageFlag & JAVA_SOURCE)
2321                 RET_ONERROR( mywritestr(f, "    ") )
2322             RET_ONERROR( mywritestr(f, "    {\n") )
2323         }
2324         RET_ONERROR( mywritestr(f, "    ") )
2325         if (languageFlag & JAVA_SOURCE) {
2326             RET_ONERROR( mywritestr(f, "    ") )
2327             if (languageFlag & MANY_JAVA_CLASSES)
2328                 RET_ONERROR( mywritestr(f, "    ") )
2329         }
2330         if (value->isArrayInC()) {
2331             if (languageFlag & (C_SOURCE | CC_SOURCE))
2332                 RET_ONERROR( mywritestr(f, "static ") )
2333             RET_ONERROR( mywritestr(f, value->getTypeC(languageFlag)) )
2334             RET_ONERROR( mywritestr(f, " ") )
2335         } else {
2336             RET_ONERROR( writeCVariable(f, languageFlag) )
2337             RET_ONERROR( mywritestr(f, ".") )
2338         }
2339         if (TheApp->isWonderlandModuleExport() &&
2340             (element->getFlags() & FF_WONDERLAND_ART)) {
2341             addToConvertedNodes(m_scene->getWriteFlags());
2342             RET_ONERROR( value->writeCWonderlandArt(f, name, languageFlag) )
2343         } else {
2344             addToConvertedNodes(m_scene->getWriteFlags());
2345             RET_ONERROR( value->writeC(f, name, languageFlag) )
2346         }
2347         if (value->isArrayInC()) {
2348             if (languageFlag & JAVA_SOURCE) {
2349                 RET_ONERROR( mywritestr(f, "    ") )
2350                 if (languageFlag & MANY_JAVA_CLASSES)
2351                     RET_ONERROR( mywritestr(f, "    ") )
2352             }
2353             RET_ONERROR( mywritestr(f, "    ") )
2354             RET_ONERROR( writeCVariable(f, languageFlag) )
2355             RET_ONERROR( mywritestr(f, ".") )
2356             RET_ONERROR( mywritestr(f, name) )
2357             RET_ONERROR( mywritestr(f, " = ") )
2358             bool isNull = false;
2359             if (languageFlag & (C_SOURCE | CC_SOURCE))
2360                 if (value->isMFieldValue()) {
2361                     MFieldValue *mvalue = (MFieldValue *)value;
2362                     if (mvalue->getSFSize() == 0)
2363                         isNull = true;
2364                 }
2365             if (isNull)
2366                 RET_ONERROR( mywritestr(f, "NULL") )
2367             else {
2368                 RET_ONERROR( mywritestr(f, "m_") )
2369                 RET_ONERROR( mywritestr(f, name) )
2370             }
2371             RET_ONERROR( mywritestr(f, ";\n") )
2372             if (languageFlag & (C_SOURCE | CC_SOURCE)) {
2373                 RET_ONERROR( mywritestr(f, "    ") )
2374                 RET_ONERROR( writeCVariable(f, languageFlag) )
2375                 RET_ONERROR( mywritestr(f, ".") )
2376                 RET_ONERROR( mywritestr(f, name) )
2377                 RET_ONERROR( mywritestr(f, "_length") )
2378                 RET_ONERROR( mywritestr(f, " = ") )
2379                 if (value->isMFieldValue() &&
2380                     (((MFieldValue *)value)->getSFSize() == 0)) {
2381                     RET_ONERROR( mywritestr(f, "0") )
2382                 } else {
2383                     RET_ONERROR( mywritestr(f, "sizeof(") )
2384                     RET_ONERROR( mywritestr(f, "m_") )
2385                     RET_ONERROR( mywritestr(f, name) )
2386                     RET_ONERROR( mywritestr(f, ") / sizeof(") )
2387                     RET_ONERROR( mywritestr(f, value->getTypeC(languageFlag)) )
2388                     RET_ONERROR( mywritestr(f, ")") )
2389                 }
2390                 RET_ONERROR( mywritestr(f, ";\n") )
2391             }
2392             if (languageFlag & JAVA_SOURCE) {
2393                 RET_ONERROR( mywritestr(f, "    ") )
2394                 if (languageFlag & MANY_JAVA_CLASSES)
2395                     RET_ONERROR( mywritestr(f, "    ") )
2396             }
2397             RET_ONERROR( mywritestr(f, "    }\n") )
2398         }
2399     }
2400     return 0;
2401 }
2402 
2403 int
writeCVariable(int f,int languageFlag)2404 NodeData::writeCVariable(int f, int languageFlag)
2405 {
2406     if (languageFlag & C_SOURCE)
2407         RET_ONERROR( mywritestr(f, "self->") )
2408     if (languageFlag & MANY_JAVA_CLASSES) {
2409         if (needExtraJavaClass() || isConvertedInCurveAnimaton())
2410             RET_ONERROR( mywritef(f, "%s%s.", TheApp->getCPrefix(),
2411                                   getVariableName()) )
2412         else if (hasName() || (m_scene->getRoot() == this))
2413             RET_ONERROR( mywritef(f, "%s.", TheApp->getCSceneGraphName()) )
2414     }
2415     RET_ONERROR( mywritestr(f, getVariableName()) )
2416     return 0;
2417 }
2418 
2419 int
writeCProcessEventCallback(int f,int languageFlag)2420 Node::writeCProcessEventCallback(int f, int languageFlag)
2421 {
2422     RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2423     RET_ONERROR( mywritestr(f, m_proto->getCName(true)) )
2424     if (languageFlag & C_SOURCE)
2425         RET_ONERROR( mywritestr(f, "ProcessEventCallback") )
2426     else if (languageFlag & CC_SOURCE) {
2427         RET_ONERROR( mywritestr(f, "::") )
2428         RET_ONERROR( mywritestr(f, "processEventCallback") )
2429     } else if (languageFlag & JAVA_SOURCE) {
2430         RET_ONERROR( mywritestr(f, ".") )
2431         RET_ONERROR( mywritestr(f, m_proto->getProcessEventCallbackName()) )
2432     }
2433     return 0;
2434 }
2435 
2436 int
writeCProcessEvent(int f,int indent,int languageFlag,const char * eventName)2437 Node::writeCProcessEvent(int f, int indent, int languageFlag,
2438                          const char *eventName)
2439 {
2440     if (getType() == DUNE_CURVE_ANIMATION) {
2441         NodeCurveAnimation *curve = (NodeCurveAnimation *) this;
2442         Node *inter = curve->getPositionInterpolator();
2443         RET_ONERROR( inter->writeCProcessEvent(f, indent, languageFlag,
2444                                                eventName) )
2445         inter = curve->getOrientationInterpolator();
2446         RET_ONERROR( inter->writeCProcessEvent(f, indent, languageFlag,
2447                                                eventName) )
2448         return 0;
2449     }
2450 
2451     if ((getType() == VRML_NURBS_SURFACE) && (!m_scene->isX3d()) &&
2452         (strcmp(eventName, "controlPoint") == 0)) {
2453         RET_ONERROR( indentf(f, indent) )
2454         RET_ONERROR( mywritestr(f, "nextEvent = ") )
2455         if (languageFlag & C_SOURCE)
2456             RET_ONERROR( mywritestr(f, "0;\n") )
2457         else
2458             RET_ONERROR( mywritestr(f, "false;\n") )
2459         RET_ONERROR( indentf(f, indent) )
2460         RET_ONERROR( mywritestr(f, "{\n") )
2461     } else {
2462         m_writtenCompleteCProcessEvent = false;
2463 
2464         RET_ONERROR( indentf(f, indent) )
2465         if (languageFlag & JAVA_SOURCE)
2466             RET_ONERROR( mywritestr(f, "    ") )
2467         RET_ONERROR( mywritestr(f, "if (") )
2468         RET_ONERROR( writeCProcessEventCallback(f, languageFlag) )
2469         RET_ONERROR( mywritestr(f, " != ") )
2470         if (languageFlag & JAVA_SOURCE)
2471             RET_ONERROR( mywritestr(f, "null") )
2472         else
2473             RET_ONERROR( mywritestr(f, "NULL") )
2474         RET_ONERROR( mywritestr(f, ") {\n") )
2475 
2476         if (languageFlag & JAVA_SOURCE) {
2477             RET_ONERROR( indentf(f, indent + 8) )
2478             RET_ONERROR( mywritestr(f, "try {\n") )
2479             RET_ONERROR( mywritestr(f, "    ") )
2480         }
2481 
2482         RET_ONERROR( indentf(f, indent + 4) )
2483         if (languageFlag & JAVA_SOURCE)
2484             RET_ONERROR( mywritestr(f, "   ") )
2485         RET_ONERROR( mywritestr(f, "nextEvent = ") )
2486         RET_ONERROR( writeCProcessEventCallback(f, languageFlag) )
2487         if (languageFlag & JAVA_SOURCE)
2488             RET_ONERROR( mywritestr(f, ".processEvent") )
2489         RET_ONERROR( mywritestr(f, "(") )
2490         if (languageFlag & (C_SOURCE | CC_SOURCE))
2491             RET_ONERROR( mywritestr(f, "&self->") )
2492         if (languageFlag & JAVA_SOURCE)
2493             RET_ONERROR( writeCVariable(f, languageFlag) )
2494         else
2495             RET_ONERROR( mywritestr(f, getVariableName()) )
2496         RET_ONERROR( mywritestr(f, ", \"") )
2497         RET_ONERROR( mywritestr(f, eventName) )
2498         RET_ONERROR( mywritestr(f, "\"") )
2499         if (languageFlag & (C_SOURCE | CC_SOURCE))
2500             RET_ONERROR( mywritestr(f, ", data") )
2501         RET_ONERROR( mywritestr(f, ");\n") )
2502 
2503         if (languageFlag & JAVA_SOURCE) {
2504             RET_ONERROR( indentf(f, indent + 8) )
2505             RET_ONERROR( mywritestr(f, "} catch (Exception e) {\n") )
2506             RET_ONERROR( indentf(f, indent + 12) )
2507             RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2508             RET_ONERROR( mywritestr(f, "ShowError(e);\n") )
2509             RET_ONERROR( indentf(f, indent + 8) )
2510             RET_ONERROR( mywritestr(f, "}\n") )
2511         }
2512     }
2513 
2514     RET_ONERROR( indentf(f, indent + 4) )
2515     if (languageFlag & JAVA_SOURCE)
2516         RET_ONERROR( mywritestr(f, "    ") )
2517     RET_ONERROR( mywritestr(f, "if (nextEvent) {\n") )
2518 
2519     return 0;
2520 }
2521 
2522 int
writeCSendEvent(int f,int indent,int languageFlag,EventIn * target,EventOut * source,Node * sNode)2523 NodeData::writeCSendEvent(int f, int indent, int languageFlag,
2524                           EventIn *target, EventOut *source, Node *sNode)
2525 {
2526     const char *sourceVariableName = source->getName(true);
2527     if (source->getExposedField() != NULL)
2528         sourceVariableName = source->getExposedField()->getName(true);
2529 
2530     const char *targetVariableName = target->getName(true);
2531     if (target->getExposedField() != NULL)
2532         targetVariableName = target->getExposedField()->getName(true);
2533 
2534     return writeCDowithEvent(f, indent + 4,  languageFlag, targetVariableName,
2535                              sourceVariableName, sNode,
2536                              isArrayInC(target->getType()), target->getType());
2537 }
2538 
2539 int
writeCCopyEvent(int f,int indent,int languageFlag,EventOut * target,EventOut * source,Node * sNode)2540 NodeData::writeCCopyEvent(int f, int indent, int languageFlag,
2541                           EventOut *target, EventOut *source, Node *sNode)
2542 {
2543     const char *sourceVariableName = source->getName(true);
2544     if (source && source->getExposedField() != NULL)
2545         sourceVariableName = source->getExposedField()->getName(true);
2546 
2547     const char *targetVariableName = target->getName(true);
2548     if (target && target->getExposedField() != NULL)
2549         targetVariableName = target->getExposedField()->getName(true);
2550 
2551     return writeCDowithEvent(f, indent,  languageFlag, targetVariableName,
2552                              sourceVariableName, sNode,
2553                              isArrayInC(target->getType()), target->getType());
2554 }
2555 
2556 int
writeCCopyEvent(int f,int indent,int languageFlag,EventIn * target,EventIn * source,Node * sNode)2557 NodeData::writeCCopyEvent(int f, int indent, int languageFlag,
2558                           EventIn *target, EventIn *source, Node *sNode)
2559 {
2560     const char *sourceVariableName = source->getName(true);
2561     if (source->getExposedField() != NULL)
2562         sourceVariableName = source->getExposedField()->getName(true);
2563 
2564     const char *targetVariableName = target->getName(true);
2565     if (target->getExposedField() != NULL)
2566         targetVariableName = target->getExposedField()->getName(true);
2567 
2568     return writeCDowithEvent(f, indent,  languageFlag, targetVariableName,
2569                              sourceVariableName, sNode,
2570                              isArrayInC(target->getType()), target->getType());
2571 }
2572 
2573 int
writeCDowithEvent(int f,int indent,int languageFlag,const char * targetVariableName,const char * sourceVariableName,Node * sNode,bool isArray,int type)2574 NodeData::writeCDowithEvent(int f, int indent, int languageFlag,
2575                             const char *targetVariableName,
2576                             const char *sourceVariableName,
2577                             Node *sNode, bool isArray, int type)
2578 {
2579     if (!sNode->hasName())
2580         return 0;
2581     if ((languageFlag & JAVA_SOURCE) && isArray) {
2582         RET_ONERROR( indentf(f, indent + 12) )
2583         RET_ONERROR( mywritestr(f, "if ((") )
2584         RET_ONERROR( writeCVariable(f, languageFlag) )
2585         RET_ONERROR( mywritestr(f, ".") )
2586         RET_ONERROR( mywritestr(f, sourceVariableName) )
2587         RET_ONERROR( mywritestr(f, " != null) && (") )
2588         RET_ONERROR( sNode->writeCVariable(f, languageFlag) )
2589         RET_ONERROR( mywritestr(f, " != null)) {\n") )
2590 
2591         RET_ONERROR( indentf(f, indent + 20) )
2592         RET_ONERROR( mywritestr(f, "if ((") )
2593         RET_ONERROR( sNode->writeCVariable(f, languageFlag) )
2594         RET_ONERROR( mywritestr(f, ".") )
2595         RET_ONERROR( mywritestr(f, targetVariableName) )
2596         RET_ONERROR( mywritestr(f, " == null) || (") )
2597         RET_ONERROR( sNode->writeCVariable(f, languageFlag) )
2598         RET_ONERROR( mywritestr(f, ".") )
2599         RET_ONERROR( mywritestr(f, targetVariableName) )
2600         RET_ONERROR( mywritestr(f, ".length != ") )
2601         RET_ONERROR( writeCVariable(f, languageFlag) )
2602         RET_ONERROR( mywritestr(f, ".") )
2603         RET_ONERROR( mywritestr(f, sourceVariableName) )
2604         RET_ONERROR( mywritestr(f, ".length))\n") )
2605 
2606         RET_ONERROR( indentf(f, indent + 24) )
2607         RET_ONERROR( sNode->writeCVariable(f, languageFlag) )
2608         RET_ONERROR( mywritestr(f, ".") )
2609         RET_ONERROR( mywritestr(f, targetVariableName) )
2610         RET_ONERROR( mywritestr(f, " = new ") )
2611         RET_ONERROR( mywritestr(f, getTypeC(type, languageFlag)) )
2612         RET_ONERROR( mywritestr(f, "[") )
2613         RET_ONERROR( writeCVariable(f, languageFlag) )
2614         RET_ONERROR( mywritestr(f, ".") )
2615         RET_ONERROR( mywritestr(f, sourceVariableName) )
2616         RET_ONERROR( mywritestr(f, ".length") )
2617         RET_ONERROR( mywritestr(f, "];\n") )
2618     }
2619 
2620     RET_ONERROR( indentf(f, indent + 8) )
2621     if (languageFlag & JAVA_SOURCE)
2622         RET_ONERROR( mywritestr(f, "    ") )
2623     if ((languageFlag & JAVA_SOURCE) && isArray) {
2624         RET_ONERROR( mywritestr(f, "    ") )
2625     }
2626     if ((languageFlag & JAVA_SOURCE) && (!isArray)) {
2627         RET_ONERROR( sNode->writeCVariable(f, languageFlag) )
2628         RET_ONERROR( mywritestr(f, ".") )
2629         RET_ONERROR( mywritestr(f, targetVariableName) )
2630         RET_ONERROR( mywritestr(f, " = ") )
2631     }
2632     RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2633     RET_ONERROR( mywritestr(f, typeEnumToString(type)) )
2634     RET_ONERROR( mywritestr(f, "SendEvent(") )
2635     Node *writeNode = sNode;
2636     if ((languageFlag & (C_SOURCE | CC_SOURCE)) ||
2637         ((languageFlag & JAVA_SOURCE) && isArray)) {
2638         bool nurbsSurfaceCorrection = false;
2639         if ((sNode->getType() == VRML_NURBS_SURFACE) && (!m_scene->isX3d()) &&
2640             strcmp(targetVariableName, "controlPoint") == 0) {
2641             nurbsSurfaceCorrection = true;
2642             MeshBasedNode *mesh = (MeshBasedNode *)sNode;
2643             if (mesh->getIndexedFaceSet() &&
2644                 mesh->getIndexedFaceSet()->getType() == VRML_INDEXED_FACE_SET) {
2645                 NodeIndexedFaceSet *face = (NodeIndexedFaceSet *)
2646                                            mesh->getIndexedFaceSet();
2647                 writeNode = face->coord()->getValue();
2648            }
2649         }
2650         if (sNode->getType() == VRML_COORDINATE) {
2651             if (sNode->getParent()->isMeshBasedNode()) {
2652                 MeshBasedNode *mesh = (MeshBasedNode *)sNode->getParent();
2653                 if (mesh->getIndexedFaceSet() &&
2654                     mesh->getIndexedFaceSet()->getType() ==
2655                     VRML_INDEXED_FACE_SET) {
2656                     NodeIndexedFaceSet *face = (NodeIndexedFaceSet *)
2657                                                mesh->getIndexedFaceSet();
2658                     writeNode = face->coord()->getValue();
2659                 }
2660             }
2661         }
2662         if (languageFlag & (C_SOURCE | CC_SOURCE)) {
2663             if (!isArrayInC(type))
2664                 RET_ONERROR( mywritestr(f, "&(") )
2665             RET_ONERROR( mywritestr(f, "self->") )
2666         }
2667         if (languageFlag & JAVA_SOURCE) {
2668             RET_ONERROR( mywritestr(f, "X3d") )
2669             RET_ONERROR( mywritestr(f, writeNode->getVariableName()) )
2670             RET_ONERROR( mywritestr(f, ".") )
2671         }
2672         RET_ONERROR( mywritestr(f, writeNode->getVariableName()) )
2673         RET_ONERROR( mywritestr(f, ".") )
2674         if (nurbsSurfaceCorrection)
2675             RET_ONERROR( mywritestr(f, "point") )
2676         else
2677             RET_ONERROR( mywritestr(f, targetVariableName) )
2678         if (languageFlag & (C_SOURCE | CC_SOURCE))
2679             if (!isArray)
2680                 RET_ONERROR( mywritestr(f, ")") )
2681         RET_ONERROR( mywritestr(f, ", ") )
2682     }
2683     if (languageFlag & CC_SOURCE)
2684         RET_ONERROR( mywritestr(f, "self->") )
2685     RET_ONERROR( writeCVariable(f, languageFlag) )
2686     RET_ONERROR( mywritestr(f, ".") )
2687     RET_ONERROR( mywritestr(f, sourceVariableName) )
2688     if (isMFType(type)) {
2689         RET_ONERROR( mywritestr(f, ", ") )
2690         if (languageFlag & CC_SOURCE)
2691             RET_ONERROR( mywritestr(f, "self->") )
2692         RET_ONERROR( writeCVariable(f, languageFlag) )
2693         RET_ONERROR( mywritestr(f, ".") )
2694         RET_ONERROR( mywritestr(f, sourceVariableName) )
2695         if (languageFlag & JAVA_SOURCE)
2696             RET_ONERROR( mywritestr(f, ".length") )
2697         else
2698             RET_ONERROR( mywritestr(f, "_length") )
2699     }
2700     RET_ONERROR( mywritestr(f, ");\n") )
2701 
2702     if ((languageFlag & JAVA_SOURCE) && isArray) {
2703         RET_ONERROR( indentf(f, indent + 12) )
2704         RET_ONERROR( mywritestr(f, "}\n") )
2705     }
2706     return 0;
2707 }
2708 
2709 
2710 bool
hasRouteForProcessEvent(void)2711 NodeData::hasRouteForProcessEvent(void)
2712 {
2713     bool hasRoute = false;
2714 
2715     SocketList::Iterator *j;
2716     for (int i = 0; i < getProto()->getNumEventOuts(); i++) {
2717         for (j = m_outputs[i].first(); j != NULL; j = j->next()) {
2718             RouteSocket s = j->item();
2719 
2720             Node *sNode = s.getNode();
2721             if (!((sNode == NULL) || (s.getField() == -1))) {
2722                 hasRoute = true;
2723             }
2724         }
2725     }
2726     return hasRoute;
2727 }
2728 
2729 int
writeCAndFollowRoutes(int f,int indent,int languageFlag,bool writeSensorNodes,const char * eventName)2730 Node::writeCAndFollowRoutes(int f, int indent, int languageFlag,
2731                             bool writeSensorNodes, const char *eventName)
2732 {
2733     bool x3d = m_scene->isX3d();
2734 
2735     bool hasRoute = hasRouteForProcessEvent();
2736 
2737     int countCloseWings = 0;
2738 
2739     if (!hasName())
2740         return 0;
2741 
2742     Proto *proto = getProto();
2743     if (hasRoute && !getProto()->isLoaded()) {
2744         m_writtenCompleteCProcessEvent = true;
2745         RET_ONERROR( writeCProcessEvent(f, indent + 4, languageFlag,
2746                                         eventName) )
2747         RET_ONERROR( indentf(f, indent + 8) )
2748         RET_ONERROR( mywritestr(f, "}\n") )
2749         countCloseWings++;
2750     }
2751 
2752     if (isInsideProto() && getProtoParent()) {
2753         Node *parentNode = getProtoParent();
2754         Proto *parentProto = parentNode->getProto();
2755 
2756         for (int i = 0; i < m_proto->getNumEventOuts(); i++) {
2757             int event = getOutsideProto()->lookupIsEventOut(this, i);
2758             if (event < 0)
2759                 continue;
2760             EventOut *source = m_proto->getEventOut(i);
2761             int isEventOut = event;
2762             if (isEventOut != -1) {
2763                 EventOut *protoTarget = parentProto->getEventOut(isEventOut);
2764                 if (this->writeCCopyEvent(f, indent, languageFlag,
2765                                           protoTarget, source, getProtoParent()
2766                                          ) != 0)
2767                    return -1;
2768             }
2769         }
2770     } else if (isPROTO()) {
2771         for (int i = 0; i < m_proto->getNumEventOuts(); i++) {
2772             for (int j = 0; j < m_proto->getEventOut(i)->getNumIs(); j++) {
2773                  Node *isNode = m_proto->getEventOut(i)->getIsNode(j);
2774                  int event = m_proto->getEventOut(i)->getIsField(j);
2775                  if (event < 0)
2776                      continue;
2777                  EventOut *source = m_proto->getEventOut(i);
2778                  int isEventOut = event;
2779                  if (isEventOut != -1) {
2780                      EventOut *protoTarget = isNode->getProto()->getEventOut(
2781                          isEventOut);
2782                      if (isNode->writeCCopyEvent(f, indent, languageFlag,
2783                                                  source, protoTarget, this
2784                                                 ) != 0)
2785                      return -1;
2786 
2787                      RET_ONERROR( isNode->writeCProcessEvent(f, indent + 4,
2788                                                              languageFlag,
2789                                                              eventName) )
2790                      RET_ONERROR( indentf(f, indent + 8) )
2791                      RET_ONERROR( mywritestr(f, "}\n") )
2792                      countCloseWings++;
2793                 }
2794             }
2795         }
2796     }
2797     if (getProto()->isLoaded()) {
2798         for (int i = 0; i < m_proto->getNumEventIns(); i++) {
2799             bool exposed = false;
2800             int event = getProto()->lookupIsEventIn(eventName);
2801             if (event < 0) {
2802                 int exf = getProto()->lookupIsExposedField(eventName);
2803                 if (exf > -1) {
2804                    ExposedField *exField = getProto()->getExposedField(exf);
2805                    exposed = true;
2806                    event = exField->getEventIn();
2807                 }
2808             }
2809             if (event < 0)
2810                 continue;
2811             EventIn *target = m_proto->getEventIn(i);
2812             MyString eventInName = "";
2813             if (exposed)
2814                 eventInName += "set_";
2815             eventInName += eventName;
2816             if (strcmp(target->getName(true), eventInName) != 0)
2817                 continue;
2818             int isEventIn = event;
2819             if (isEventIn != -1) {
2820                 if (exposed)
2821                     for (int j = 0;
2822                          j < proto->getExposedField(isEventIn)->getNumIs();
2823                          j++) {
2824                         ExposedField *eF = m_proto->getExposedField(isEventIn);
2825                         Node *node = eF->getIsNode(j);
2826                         node = m_scene->searchProtoNodeId(node->getId());
2827                         if (node) {
2828                             EventIn *protoSource = node->getProto()->getEventIn(
2829                                                        eF->getIsField(j));
2830                             if (this->writeCCopyEvent(f, indent, languageFlag,
2831                                                       protoSource, target, node
2832                                                       ) != 0)
2833                                 return -1;
2834                         }
2835                     }
2836                 else
2837                     for (int j = 0;
2838                          j < proto->getEventIn(isEventIn)->getNumIs();
2839                          j++) {
2840                         EventIn *eI = m_proto->getEventIn(isEventIn);
2841                         Node *node = eI->getIsNode(j);
2842                         node = m_scene->searchProtoNodeId(node->getId());
2843                         EventIn *protoSource = node->getProto()->getEventIn(
2844                                                    eI->getIsField(j));
2845                         if (this->writeCCopyEvent(f, indent, languageFlag,
2846                                                   protoSource, target, node
2847                                                  ) != 0)
2848                             return -1;
2849                     }
2850             }
2851         }
2852     }
2853 
2854     SocketList::Iterator *j;
2855     for (int i = 0; i < getProto()->getNumEventOuts(); i++) {
2856         int numOutput = 0;
2857         for (j = m_outputs[i].first(); j != NULL; j = j->next()) {
2858             numOutput++;
2859             RouteSocket s = j->item();
2860 
2861             Node *sNode = s.getNode();
2862 
2863             bool isCurveAnimation = (sNode->getType() == DUNE_CURVE_ANIMATION);
2864 
2865             EventIn *target = sNode->getProto()->getEventIn(s.getField());
2866             if (isInAlreadyWrittenEventOuts(i, numOutput, m_nodePROTO))
2867                 continue;
2868             EventOut *source = getProto()->getEventOut(i);
2869 
2870             RET_ONERROR( indentf(f, indent + 8) )
2871             if ((languageFlag & JAVA_SOURCE) && !isCurveAnimation) {
2872                 RET_ONERROR( indentf(f, indent + 4) )
2873                 RET_ONERROR( mywritestr(f, "if (") )
2874                 RET_ONERROR( sNode->writeCVariable(f, languageFlag) )
2875                 RET_ONERROR( mywritestr(f, " != null) ") )
2876             }
2877             RET_ONERROR( mywritestr(f, "{\n") )
2878 
2879             if (isInsideProto()) {
2880                 sNode = m_scene->searchProtoNodeIdInNode(m_nodePROTO,
2881                                                          sNode->getId());
2882             if (!sNode->hasName())
2883                 continue;
2884 
2885             bool isCurveAnimation = (sNode->getType() == DUNE_CURVE_ANIMATION);
2886 
2887                 if (sNode == NULL) {
2888                     swDebugf("internal Error: sNode == NULL\n");
2889                     return -1;
2890                 }
2891             }
2892 
2893             if (((getNodeClass() & SENSOR_NODE) ||
2894                  (getType() == VRML_COLLISION)) &&
2895                 hasOutputsOrIs()) {
2896                 m_scene->addToSensorNodes(this);
2897             }
2898 
2899             bool replaceEventOut = false;
2900             if (sNode->getType() == DUNE_CURVE_ANIMATION) {
2901                 NodeCurveAnimation *curve = (NodeCurveAnimation *) sNode;
2902                 if (s.getField() == curve->getFraction_Field()) {
2903                     replaceEventOut = true;
2904                     NodePositionInterpolator *inter =
2905                         (NodePositionInterpolator *)(curve->
2906                         getPositionInterpolator());
2907                     source = inter->getProto()->getEventOut(
2908                                  inter->set_fraction_Field());
2909                     if (getType() == VRML_TIME_SENSOR) {
2910                         NodeTimeSensor *timer = (NodeTimeSensor *)this;
2911                         int eventOut = timer->getProto()->lookupEventOut(
2912                                      "fraction_changed", true);
2913                         source = timer->getProto()->getEventOut(eventOut);
2914                     }
2915 
2916                     int eventWritten = m_writtenCompleteCProcessEvent;
2917 
2918                     RET_ONERROR(writeCSendEvent(f, indent, languageFlag,
2919                                                 target, source, inter) )
2920                     if (eventWritten | (!(languageFlag & JAVA_SOURCE))) {
2921                         RET_ONERROR( indentf(f, indent + 8) )
2922                         RET_ONERROR( mywritestr(f, "}\n") )
2923                         RET_ONERROR( indentf(f, indent + 4) )
2924                         RET_ONERROR( mywritestr(f, "}\n") )
2925                     }
2926 
2927                     NodeOrientationInterpolator *inter2 =
2928                         (NodeOrientationInterpolator *)(curve->
2929                         getOrientationInterpolator());
2930                     source = inter2->getProto()->getEventOut(
2931                                  inter2->set_fraction_Field());
2932                     if (getType() == VRML_TIME_SENSOR) {
2933                         NodeTimeSensor *timer = (NodeTimeSensor *)this;
2934                         int eventOut = timer->getProto()->lookupEventOut(
2935                                      "fraction_changed", true);
2936                         source = timer->getProto()->getEventOut(eventOut);
2937                     }
2938 
2939                     if (writeCSendEvent(f, indent, languageFlag, target,
2940                                         source, inter2) != 0)
2941                         return -1;
2942                 }
2943             }
2944             bool replaceEventIn = false;
2945             if (getType() == DUNE_CURVE_ANIMATION) {
2946                 NodeCurveAnimation *curve = (NodeCurveAnimation *) this;
2947                 if (i == curve->getPosition_Field()) {
2948                     replaceEventIn = true;
2949                     NodePositionInterpolator *inter =
2950                         (NodePositionInterpolator *)(curve->
2951                         getPositionInterpolator());
2952                     source = inter->getProto()->getEventOut(
2953                                  inter->value_changed_Field());
2954                     if (inter->writeCSendEvent(f, indent, languageFlag,
2955                                                target, source, sNode) != 0)
2956                         return -1;
2957                 }
2958                 if (i == curve->getOrientation_Field()) {
2959                     replaceEventIn = true;
2960                     NodeOrientationInterpolator *inter =
2961                         (NodeOrientationInterpolator *)(curve->
2962                         getOrientationInterpolator());
2963                     source = inter->getProto()->getEventOut(
2964                                  inter->value_changed_Field());
2965                     if (inter->writeCSendEvent(f, indent, languageFlag,
2966                                                target, source, sNode) != 0)
2967                         return -1;
2968                 }
2969             }
2970             if ((!replaceEventOut) && (!replaceEventIn))
2971                 if (writeCSendEvent(f, indent, languageFlag,
2972                                     target, source, sNode) != 0)
2973                     return -1;
2974 
2975             const char *targetVariableName = target->getName(true);
2976             if (target->getExposedField() != NULL)
2977                 targetVariableName = target->getExposedField()->getName(true);
2978             if (!isInAlreadyWrittenEventOuts(i, numOutput, m_nodePROTO))
2979                 appendToAlreadyWrittenEventOuts(i, numOutput, m_nodePROTO);
2980 
2981             RET_ONERROR( sNode->writeCAndFollowRoutes(f, indent + 8,
2982                                                       languageFlag,
2983                                                       writeSensorNodes,
2984                                                       targetVariableName) )
2985 
2986             RET_ONERROR( indentf(f, indent + 8) )
2987             if (languageFlag & JAVA_SOURCE)
2988                 RET_ONERROR( mywritestr(f, "    ") )
2989             RET_ONERROR( mywritestr(f, "}\n") )
2990 
2991             Field *field = getProto()->getField(s.getField());
2992             if (field) {
2993                 ExposedField *expField = field->getExposedField();
2994                 if (expField) {
2995                     int eventOut = expField->getEventOut();
2996                     EventOut *source = getProto()->getEventOut(eventOut);
2997                     if (source) {
2998                         SocketList::Iterator *i;
2999                         for (i = m_outputs[eventOut].first(); i != NULL;
3000                              i = i->next()) {
3001                             RouteSocket s = i->item();
3002                             Node *sNode = s.getNode();
3003 
3004                             EventIn *target =
3005                                  sNode->getProto()->getEventIn(s.getField());
3006                             if (writeCSendEvent(f, indent + 4, languageFlag,
3007                                                 target, source, sNode) != 0)
3008                                 return -1;
3009                         }
3010                     }
3011                 }
3012             }
3013         }
3014     }
3015     if (getProto()->isLoaded() && !hasRoute)
3016         countCloseWings++;
3017     for (int i = 0; i < countCloseWings; i++) {
3018         RET_ONERROR( indentf(f, indent + 4 - i * 4) )
3019         RET_ONERROR( mywritestr(f, "}\n") )
3020     }
3021     return 0;
3022 }
3023 
3024 int
writeCInstallDynamicNodeCallback(int f,int languageFlag,Proto * proto)3025 Node::writeCInstallDynamicNodeCallback(int f, int languageFlag, Proto *proto)
3026 {
3027     if (languageFlag & C_SOURCE) {
3028         RET_ONERROR( mywritestr(f, "    ") )
3029         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3030         RET_ONERROR( mywritestr(f, proto->getCName(true)) )
3031         RET_ONERROR( mywritestr(f, "ProcessEventCallback = ") )
3032         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3033         RET_ONERROR( mywritestr(f, proto->getCName(true)) )
3034         RET_ONERROR( mywritestr(f, "SendEventsCallback;\n") )
3035     } else if (languageFlag & CC_SOURCE) {
3036         RET_ONERROR( mywritestr(f, "    ") )
3037         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3038         RET_ONERROR( mywritestr(f, proto->getCName(true)) )
3039         RET_ONERROR( mywritestr(f, "::") )
3040         RET_ONERROR( mywritestr(f, "processEventCallback = ") )
3041         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3042         RET_ONERROR( mywritestr(f, proto->getCName(true)) )
3043         RET_ONERROR( mywritestr(f, "SendEventsCallback;\n") )
3044     } else if (languageFlag & JAVA_SOURCE) {
3045         RET_ONERROR( mywritestr(f, "    ") )
3046         RET_ONERROR( mywritestr(f, "    {\n") )
3047         RET_ONERROR( mywritestr(f, "    ") )
3048         RET_ONERROR( mywritestr(f, "    ") )
3049         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3050         RET_ONERROR( mywritestr(f, proto->getCName(true)) )
3051         RET_ONERROR( mywritestr(f, "SendEventsCallback var = new ") )
3052         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3053         RET_ONERROR( mywritestr(f, proto->getCName(true)) )
3054         RET_ONERROR( mywritestr(f, "SendEventsCallback();\n") )
3055         RET_ONERROR( mywritestr(f, "    ") )
3056         RET_ONERROR( mywritestr(f, "    ") )
3057         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3058         RET_ONERROR( mywritestr(f, proto->getCName(true)) )
3059         RET_ONERROR( mywritestr(f, ".set") )
3060         RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3061         RET_ONERROR( mywritestr(f, proto->getCName(true)) )
3062         RET_ONERROR( mywritestr(f, "ProcessEventCallback(var);\n") )
3063         RET_ONERROR( mywritestr(f, "        }\n") )
3064     }
3065     return 0;
3066 }
3067 
3068 int
lookupEventIn(const char * name,bool x3d) const3069 NodeData::lookupEventIn(const char *name, bool x3d) const
3070 {
3071     return m_proto ? m_proto->lookupEventIn(name, x3d) : INVALID_INDEX;
3072 }
3073 
3074 int
lookupEventOut(const char * name,bool x3d) const3075 NodeData::lookupEventOut(const char *name, bool x3d) const
3076 {
3077     return m_proto ? m_proto->lookupEventOut(name, x3d) : INVALID_INDEX;
3078 }
3079 
3080 MyString
newEventName(int typeEnum,bool out)3081 NodeData::newEventName(int typeEnum, bool out)
3082 {
3083     bool x3d = m_scene->isX3d();
3084     char name[1024];
3085     MyString eventName = "";
3086     const char *typestr = typeEnumToString(typeEnum);
3087     if (typestr[0] == 'M')
3088         eventName += "m";
3089     for (unsigned int i = 2; i < strlen(typestr); i++)
3090         eventName += tolower(typestr[i]);
3091     int counter = 0;
3092     bool foundflag;
3093     do {
3094         foundflag = false;
3095         counter++;
3096         const char *format = "%d_in";
3097         if (out)
3098             format = "%d_out";
3099         mysnprintf(name, 1023, (const char *)format, counter);
3100 
3101         int numberEvents = 0;
3102         if (out)
3103             numberEvents = m_proto->getNumEventOuts();
3104         else
3105             numberEvents = m_proto->getNumEventIns();
3106         for (int i = 0; i < numberEvents; i++) {
3107             const char *oldName;
3108             if (out)
3109                oldName = (const char*) m_proto->getEventOut(i)->getName(x3d);
3110             else
3111                oldName = (const char*) m_proto->getEventIn(i)->getName(x3d);
3112             MyString cmpName = "";
3113             cmpName += eventName;
3114             cmpName += name;
3115             if (strcmp(oldName, (const char*)cmpName) == 0)
3116                 foundflag = true;
3117         }
3118     } while (foundflag == true);
3119     eventName += name;
3120     return eventName;
3121 }
3122 
3123 void
addInput(int eventIn,Node * src,int eventOut)3124 NodeData::addInput(int eventIn, Node *src, int eventOut)
3125 {
3126     if (eventIn >= m_numEventIns)
3127         if (isDynamicFieldsNode()) {
3128             int typeEnum = src->getProto()->getEventOut(eventOut)->getType();
3129             MyString event = "";
3130             event += newEventName(typeEnum, false);
3131             if (TheApp->mainWnd() != NULL) {
3132                 ScriptEventDialog dlg(TheApp->mainWnd(), IDD_SCRIPT_EVENT,
3133                                       event, (Node *)this);
3134                 dlg.DoModal();
3135                 if (dlg.GetValue()) {
3136                     event = "";
3137                     event += dlg.GetValue();
3138                 }
3139             }
3140             ((DynamicFieldsNode *)this)->addEventIn(typeEnum, event);
3141             update();
3142             NodeUpdate *hint= new NodeUpdate((Node *)this, NULL, 0);
3143             m_scene->UpdateViews(NULL, UPDATE_CHANGE_INTERFACE_NODE,
3144                                  (Hint*) hint);
3145         }
3146     m_inputs[eventIn].append(RouteSocket(src, eventOut));
3147 }
3148 
3149 void
addOutput(int eventOut,Node * dst,int eventIn)3150 NodeData::addOutput(int eventOut, Node *dst, int eventIn)
3151 {
3152     if (eventOut >= m_numEventOuts)
3153         if (isNodeWithAdditionalEvents()) {
3154             int typeEnum = dst->getProto()->getEventIn(eventIn)->getType();
3155             MyString event = "";
3156             event += newEventName(typeEnum, true);
3157             if (TheApp->mainWnd() != NULL) {
3158                 ScriptEventDialog dlg(TheApp->mainWnd(), IDD_SCRIPT_EVENT,
3159                                       event, (Node *)this);
3160                 dlg.DoModal();
3161                 if (dlg.GetValue()) {
3162                     event = "";
3163                     event += dlg.GetValue();
3164                 }
3165             }
3166             ((DynamicFieldsNode *)this)->addEventOut(typeEnum, event);
3167             update();
3168             NodeUpdate *hint= new NodeUpdate((Node *)this, NULL, 0);
3169             m_scene->UpdateViews(NULL, UPDATE_CHANGE_INTERFACE_NODE,
3170                                  (Hint*) hint);
3171         }
3172     m_outputs[eventOut].append(RouteSocket(dst, eventIn));
3173 }
3174 
3175 void
removeInput(int eventIn,Node * src,int eventOut)3176 NodeData::removeInput(int eventIn, Node *src, int eventOut)
3177 {
3178     SocketList::Iterator *j = m_inputs[eventIn].find(RouteSocket(src, eventOut));
3179     if (j)
3180         m_inputs[eventIn].remove(j);
3181 }
3182 
3183 void
removeOutput(int eventOut,Node * dst,int eventIn)3184 NodeData::removeOutput(int eventOut, Node *dst, int eventIn)
3185 {
3186     SocketList::Iterator *j = m_outputs[eventOut].find(RouteSocket(dst,
3187                                                                    eventIn));
3188     if (j)
3189         m_outputs[eventOut].remove(j);
3190 }
3191 
3192 void
update()3193 NodeData::update()
3194 {
3195     // used by Script to update its fields and
3196     // used by shapes to redraw after a change of a MF-field and
3197     // used by nodes to redraw parent after a change of a field
3198 }
3199 
3200 void
reInit()3201 NodeData::reInit()
3202 {
3203     // used to reinitialise private data of a "copy"-ed node
3204     // e.g. to reinitialise mesh data of some geometric shapes
3205 }
3206 
3207 
3208 void
addParent(Node * parent,int field)3209 Node::addParent(Node *parent, int field)
3210 {
3211     for (long i = 0; i < m_parents.size(); i++)
3212         if ((m_parents[i].m_node == parent) && (m_parents[i].m_field == field)){
3213             m_geometricParentIndex = i;
3214             return; // parent already set
3215         }
3216     m_parents.append(Parent(parent, field, this));
3217     m_geometricParentIndex = m_parents.size() - 1;
3218 }
3219 
3220 void
removeParent(void)3221 Node::removeParent(void)
3222 {
3223     if (m_geometricParentIndex != -1) {
3224         for (long i = m_geometricParentIndex + 1; i < m_parents.size(); i++)
3225             if (m_parents[i].m_self)
3226                 m_parents[i].m_self->m_geometricParentIndex--;
3227         m_parents.remove(m_geometricParentIndex);
3228         m_geometricParentIndex = -1;
3229     }
3230 }
3231 
3232 
3233 int
findChild(Node * child,int field) const3234 NodeData::findChild(Node *child, int field) const
3235 {
3236     assert(field >= 0 && field < m_numFields);
3237 
3238     FieldValue *value = m_fields[field];
3239 
3240     if (value && value->getType() == SFNODE) {
3241         return (((SFNode *) value)->getValue() == child) ? 0 : -1;
3242     } else if (value && value->getType() == MFNODE) {
3243         NodeList *list = ((MFNode *) value)->getValues();
3244         for (long i = 0; i < list->size(); i++) {
3245             if (list->get(i) == child) return i;
3246         }
3247         return -1;
3248     } else {
3249         return -1;
3250     }
3251 }
3252 
3253 bool
hasAncestor(Node * node) const3254 Node::hasAncestor(Node *node) const
3255 {
3256     if (this != m_scene->getRoot()) {
3257         if (hasParent()) {
3258             Node *parent = getParent();
3259             if (parent == node || parent->hasAncestor(node))
3260                 return true;
3261         }
3262     }
3263     return false;
3264 }
3265 
3266 bool
checkValid(Element * field)3267 NodeData::checkValid(Element *field)
3268 {
3269     if (m_scene != NULL) {
3270         if (m_scene->isInvalidElement(field))
3271             return false;
3272     }
3273     return true;
3274 }
3275 
3276 int
findValidFieldType(int childType)3277 NodeData::findValidFieldType(int childType)
3278 {
3279     int match = -1;
3280     for (int field = 0; field < m_numFields; field++) {
3281         if (validChildType(field, childType)) {
3282             if (match != -1) {
3283                 // ambiguous
3284                 return - 1;
3285             }
3286             match = field;
3287         }
3288     }
3289     return match;
3290 }
3291 
3292 int
findFirstValidFieldType(int childType)3293 NodeData::findFirstValidFieldType(int childType)
3294 {
3295     for (int field = 0; field < m_numFields; field++) {
3296         if (validChildType(field, childType)) {
3297             return field;
3298         }
3299     }
3300     return -1;
3301 }
3302 
3303 int
findValidField(Node * child)3304 NodeData::findValidField(Node *child)
3305 {
3306     int ret = findValidFieldType(child->getNodeClass());
3307     if (ret == -1)
3308         ret = findValidFieldType(child->getType());
3309     return ret;
3310 }
3311 
3312 int
findChildType(int childType)3313 NodeData::findChildType(int childType)
3314 {
3315     int match = -1;
3316     for (int field = 0; field < m_numFields; field++) {
3317         if (checkChildType(field, childType, false)) {
3318             if (match != -1) {
3319                 // ambiguous
3320                 return -1;
3321             }
3322             match = field;
3323         }
3324     }
3325     return match;
3326 }
3327 
3328 bool
validChild(int field,Node * child)3329 NodeData::validChild(int field, Node *child)
3330 {
3331     return validChildType(field, child->getNodeClass());
3332 }
3333 
3334 bool
validChildType(int field,int childType)3335 NodeData::validChildType(int field, int childType)
3336 {
3337     return checkChildType(field, childType, true);
3338 }
3339 
3340 bool
checkChildType(int field,int childType,bool checkNewNode)3341 NodeData::checkChildType(int field, int childType, bool checkNewNode)
3342 {
3343     if (field < 0 || field >= m_numFields) return false;
3344 
3345     Field *def = m_proto->getField(field);
3346 
3347     // SFNode field already in use ?
3348     if (def->getType() == SFNODE) {
3349         SFNode *node = (SFNode *)m_fields[field];
3350         if (checkNewNode)
3351             if (node->getValue() != NULL)
3352                 return false;
3353     }
3354 
3355     if ((def->getType() == SFNODE) || (def->getType() == MFNODE)) {
3356         int nodeType = def->getNodeType();
3357 
3358         if (childType & NOT_SELF_NODE) {
3359             int bits = ::getMaskedNodeClass(nodeType);
3360             if (bits == 0) {
3361                bits = nodeType & (~NOT_SELF_NODE);
3362                if (bits & childType)
3363                    return false;
3364             } else
3365                if (bits & childType)
3366                    return false;
3367         }
3368         if (nodeType == ANY_NODE) {
3369             return checkValid(def);
3370         } else if ((::getMaskedNodeClass(childType) != 0) &&
3371                    (::getMaskedNodeClass(childType) ==
3372                     ::getMaskedNodeClass(nodeType))) {
3373             return checkValid(def);
3374         } else if (::matchNodeClass(nodeType, childType)) {
3375             return checkValid(def);
3376         } else if ((getType() == VRML_CONTOUR_2D) &&
3377                    (childType == NURBS_CONTROL_CURVE_NODE)) {
3378             return checkValid(def);
3379         } else
3380            return false;
3381     } else {
3382         return false;
3383     }
3384     return false;
3385 }
3386 
3387 void
setFlagRec(int flag)3388 NodeData::setFlagRec(int flag)
3389 {
3390     setFlag(flag);
3391 
3392     for (int i = 0; i < m_numFields; i++) {
3393         if (m_fields[i]->getType() == MFNODE) {
3394             MFNode *nodes = (MFNode *) m_fields[i];
3395             for (int j = 0; j < nodes->getSize(); j++)
3396                 if (nodes->getValue(j) != NULL)
3397                     nodes->getValue(j)->setFlagRec(flag);
3398         } else if (m_fields[i]->getType() == SFNODE) {
3399             SFNode *value = (SFNode *) m_fields[i];
3400             if (value->getValue()) value->getValue()->setFlagRec(flag);
3401         }
3402     }
3403 }
3404 
3405 void
clearFlagRec(int flag)3406 NodeData::clearFlagRec(int flag)
3407 {
3408     clearFlag(flag);
3409 
3410     for (int i = 0; i < m_numFields; i++) {
3411         if (m_fields[i] && m_fields[i]->getType() == MFNODE) {
3412             MFNode *nodes = (MFNode *) m_fields[i];
3413             for (int j = 0; j < nodes->getSize(); j++)
3414                 if (nodes->getValue(j) != NULL)
3415                     nodes->getValue(j)->clearFlagRec(flag);
3416         } else if (m_fields[i] && m_fields[i]->getType() == SFNODE) {
3417             SFNode *value = (SFNode *) m_fields[i];
3418             if (value->getValue()) value->getValue()->clearFlagRec(flag);
3419         }
3420     }
3421 }
3422 
3423 class ReceiveData {
3424 public:
3425     Proto *outSideProto;
3426     int field;
3427     double timestamp;
3428     FieldValue *value;
3429 };
3430 
branchReceiveEvent(Node * node,void * data)3431 static bool branchReceiveEvent(Node *node, void *data)
3432 {
3433     ReceiveData *receiveData = (ReceiveData *)data;
3434     if ((node != NULL) && (node->isPROTO()))
3435         if (strcmp(node->getProto()->getName(true),
3436                    receiveData->outSideProto->getName(true)) == 0) {
3437             NodePROTO *protoNode = (NodePROTO *)node;
3438             Proto *proto = protoNode->getProto();
3439             for (int i = 0; i < proto->getNumEventOuts(); i++) {
3440                 EventOut *evOut = proto->getEventOut(i);
3441                 for (int j = 0; j < evOut->getNumIs(); j++) {
3442                     if (evOut->getIsField(j) == receiveData->field) {
3443                         for (int i = 0; i < proto->getNumEventOuts(); i++) {
3444                             if (protoNode->getOutput(i).size() > 0 &&
3445                                 protoNode->getOutput(i).first() != NULL) {
3446                                 RouteSocket s =
3447                                      protoNode->getOutput(i).first()->item();
3448                                 s.getNode()->receiveEvent(s.getField(),
3449                                     receiveData->timestamp, receiveData->value);
3450                             }
3451                         }
3452                     }
3453                 }
3454             }
3455         }
3456     return true;
3457 }
3458 
3459 void
sendEvent(int eventOut,double timestamp,FieldValue * value)3460 NodeData::sendEvent(int eventOut, double timestamp, FieldValue *value)
3461 {
3462     assert(eventOut >= 0 && eventOut <= m_numEventOuts);
3463 
3464     // handle IS
3465     EventOut *evOut = m_proto->getEventOut(eventOut);
3466     if (getOutsideProto()) {
3467         for (int i = 0; i < getOutsideProto()->getNumEventOuts(); i++)
3468             if (getOutsideProto()->getEventOut(i)->getIsField(i) == eventOut)
3469                 evOut = getOutsideProto()->getEventOut(i);
3470         if (evOut && (evOut->getFlags() & FF_IS))
3471             for (int i = 0; i < evOut->getNumIs(); i++) {
3472                 Node *isNode = evOut->getIsNode(i);
3473 
3474                 ReceiveData receiveData;
3475                 receiveData.outSideProto = getOutsideProto();
3476                 receiveData.field = evOut->getIsField(i);
3477                 receiveData.timestamp = timestamp;
3478                 receiveData.value = value;
3479 
3480                 m_scene->getRoot()->doWithBranch(branchReceiveEvent,
3481                                                  &receiveData, false);
3482             }
3483     }
3484     evOut = m_proto->getEventOut(eventOut);
3485     if ((m_isEventOuts.size() > 0) && (m_isEventOuts[eventOut] != NULL))
3486         evOut = m_isEventOuts[eventOut];
3487     if (evOut && (evOut->getFlags() & FF_IS))
3488         for (int i = 0; i < evOut->getNumIs(); i++)
3489             if (evOut->getFlags() & EOF_IS_HIDDEN) {
3490                 Node *isNode = evOut->getIsNode(i);
3491                 isNode->sendEvent(evOut->getIsField(i), timestamp, value);
3492             }
3493 
3494     SocketList::Iterator *i;
3495     for (i = m_outputs[eventOut].first(); i != NULL; i = i->next()) {
3496         RouteSocket s = i->item();
3497         s.getNode()->receiveEvent(s.getField(), timestamp, value);
3498     }
3499 }
3500 
3501 void
receiveEvent(int eventIn,double timestamp,FieldValue * value)3502 NodeData::receiveEvent(int eventIn, double timestamp, FieldValue *value)
3503 {
3504     if (TheApp->getDemoMode()) {
3505         if ((getType() == VRML_VIEWPOINT) && !TheApp->timeOut())
3506             return;
3507     }
3508 
3509     // check to see if this eventIn is part of an exposedField or
3510     // conntected to a normal field
3511 
3512     int field = -1;
3513     ExposedField *e = m_proto->getEventIn(eventIn)->getExposedField();
3514 
3515     if (e) {
3516         field = e->getFieldIndex();
3517         eventIn = e->getEventIn();
3518     } else
3519         field = m_proto->getEventIn(eventIn)->getField();
3520 
3521     if (field != -1) {
3522         // set the appropriate field
3523         setField(field, value);
3524         m_scene->OnFieldChange((Node*)this, field);
3525         // fire off an event here?
3526     }
3527 }
3528 
3529 void
addIsElement(Node * node,int field,int elementType,Proto * origProto,int origField,int flags)3530 NodeData::addIsElement(Node *node, int field, int elementType,
3531                        Proto *origProto, int origField, int flags)
3532 {
3533     switch(elementType) {
3534       case EL_EVENT_IN:
3535         if (origField < origProto->getNumEventIns()) {
3536             if (m_isEventIns.size() == 0)
3537                 for (int i = 0; i < origProto->getNumEventIns(); i++)
3538                     m_isEventIns[i] = NULL;
3539             m_isEventIns[origField] = new EventIn(origProto->
3540                                                   getEventIn(origField));
3541             m_isEventIns[origField]->addIs(node, field, elementType,
3542                                            origProto, origField, flags);
3543         }
3544         break;
3545       case EL_EVENT_OUT:
3546         if (origField < origProto->getNumEventOuts()) {
3547             if (m_isEventOuts.size() == 0)
3548                 for (int i = 0; i < origProto->getNumEventOuts(); i++)
3549                     m_isEventOuts[i] = NULL;
3550 /*
3551 // hier/hier
3552             if (origProto->getExposedField(origField))
3553                 m_isExposedFields[origField] = new ExposedField(origProto->
3554                     getExposedField(origField));
3555             if (m_isEventOuts[origField])
3556                 m_isEventOuts[origField]->addIs(node, field, elementType,
3557                                                 origProto, origField, flags);
3558 // da/da
3559 */
3560 // hier
3561             m_isEventOuts[origField] = new EventOut(origProto->
3562                                                     getEventOut(origField));
3563             m_isEventOuts[origField]->addIs(node, field, elementType,
3564                                             origProto, origField, flags);
3565 // da
3566         }
3567         break;
3568       case EL_EXPOSED_FIELD:
3569         if (origField < origProto->getNumExposedFields()) {
3570             for (int i = 0; i < origProto->getNumExposedFields(); i++)
3571                 m_isExposedFields[i] = NULL;
3572             m_isExposedFields[origField] = new ExposedField(origProto->
3573                                                    getExposedField(origField));
3574             m_isExposedFields[origField]->addIs(node, field, elementType,
3575                                                 origProto, origField, flags);
3576         }
3577         break;
3578       case EL_FIELD:
3579         if (origField < origProto->getNumEventIns()) {
3580             for (int i = 0; i < origProto->getNumFields(); i++)
3581                 m_isFields[i] = NULL;
3582             m_isFields[origField] = new Field(origProto->getField(origField));
3583             m_isFields[origField]->addIs(node, field, elementType,
3584                                          origProto, origField, flags);
3585         }
3586         break;
3587     }
3588 }
3589 
3590 // compare content
3591 bool
isEqual(Node * node)3592 NodeData::isEqual(Node* node)
3593 {
3594     if (node == NULL) {
3595 #ifdef HAVE_NULL_COMPARE
3596         if (this == NULL)
3597             return true;
3598         else
3599 #endif
3600             return false;
3601     }
3602     if (m_identifier == node->m_identifier)
3603         return true;
3604     return false;
3605 }
3606 
3607 // compare content
3608 bool
isEqualCopy(Node * node)3609 NodeData::isEqualCopy(Node* node)
3610 {
3611     if (node == NULL) {
3612 #ifdef HAVE_NULL_COMPARE
3613         if (this == NULL)
3614             return true;
3615         else
3616 #endif
3617             return false;
3618     }
3619     if (m_identifierCopy >= 0)
3620         if (m_identifierCopy == node->m_identifierCopy)
3621             return true;
3622     if (m_identifierCopy == node->m_identifier)
3623         return true;
3624     if (m_identifier == node->m_identifierCopy)
3625         return true;
3626     return false;
3627 }
3628 
3629 bool
hasRoute(SocketList socketlist)3630 NodeData::hasRoute(SocketList socketlist)
3631 {
3632    if (socketlist.first() == NULL)
3633       return false;
3634    else
3635       return true;
3636 }
3637 
3638 Path *
getPath() const3639 Node::getPath() const
3640 {
3641     int len = 0;
3642     const Node *node = this;
3643     const Node *protoRoot = node;
3644 
3645     for (protoRoot = this; protoRoot->hasParentOrProtoParent();
3646          protoRoot = protoRoot->getParentOrProtoParent())
3647         len += 2;
3648 
3649     MyArray<int> protoList;
3650     m_scene->getProtoList(&protoList, protoRoot);
3651     if (protoList.size() > 0)
3652         len += 4;
3653 
3654     if (len == 0) {
3655         Path *path = new Path(NULL, 0, m_scene);
3656         return path;
3657     }
3658 
3659     int *list = new int[len];
3660 
3661     int i = len - 1;
3662 
3663     for (node = this; node->hasParentOrProtoParent();
3664          node = node->getParentOrProtoParent()) {
3665         Node *parent = node->getParentOrProtoParent();
3666         int field = node->getParentFieldOrProtoParentField();
3667         FieldValue *value = parent->getField(field);
3668         if (value->getType() == MFNODE) {
3669             list[i--] = ((MFNode *) value)->getValues()->find((Node *) node);
3670         } else if (value->getType() == SFNODE)  {
3671             list[i--] = 0;
3672         } else {
3673             assert(0);
3674         }
3675         list[i--] = field;
3676     }
3677 
3678     if (protoList.size() > 0) {
3679         list[i--] = 0;
3680         list[i--] = 0;
3681         list[i--] = protoList[1];
3682         list[i--] = protoList[0];
3683     }
3684 
3685     Path *path = new Path(list, len, m_scene);
3686     delete [] list;
3687     list = NULL;
3688     return path;
3689 }
3690 
3691 bool
isInScene(Scene * scene) const3692 Node::isInScene(Scene* scene) const
3693 {
3694     if (scene != m_scene)
3695         return false;
3696     if (scene == NULL)
3697         return false;
3698     if (this == m_scene->getRoot())
3699         return true;
3700     if (((NodeData *)this)->isInsideProto()) {
3701         Node *node = ((NodeData *)this)->getNodePROTO();
3702         if (node)
3703             return node->isInScene(scene);
3704         else
3705             return false;
3706     }
3707     if (!hasParent())
3708         return false;
3709     return true;
3710 }
3711 
3712 bool
supportAnimation(void)3713 Node::supportAnimation(void)
3714 {
3715     Proto *proto = getProto();
3716     for (int i = 0; i < proto->getNumEventIns(); i++) {
3717         int type = proto->getEventIn(i)->getType();
3718         if (m_scene->isInvalidElement(proto->getEventIn(i)))
3719             continue;
3720 
3721         if (typeDefaultValue(type)->supportAnimation(m_scene->isX3d()))
3722             return true;
3723     }
3724     return false;
3725 }
3726 
3727 
3728 bool
supportInteraction(void)3729 Node::supportInteraction(void)
3730 {
3731     Proto *proto = getProto();
3732     for (int i = 0; i < proto->getNumEventIns(); i++) {
3733         int type = proto->getEventIn(i)->getType();
3734         if (typeDefaultValue(type)->supportInteraction())
3735             return true;
3736     }
3737     return false;
3738 }
3739 
3740 bool
isInvalidChild(void)3741 Node::isInvalidChild(void)
3742 {
3743     if (this == m_scene->getRoot())
3744         return true;
3745     if (isInvalidChildNode() && hasParent())
3746         return true;
3747     return false;
3748 }
3749 
3750 Vec3f
getMinBoundingBox(void)3751 Node::getMinBoundingBox(void)
3752 {
3753    return Vec3f(FLT_MAX, FLT_MAX, FLT_MAX);
3754 }
3755 
3756 Vec3f
getMaxBoundingBox(void)3757 Node::getMaxBoundingBox(void)
3758 {
3759    return Vec3f(FLT_MIN, FLT_MIN, FLT_MIN);
3760 }
3761 
3762 Vec3f
getBboxSize(void)3763 Node::getBboxSize(void)
3764 {
3765     Vec3f min = getMinBoundingBox();
3766     Vec3f max = getMaxBoundingBox();
3767     if ((min.x == FLT_MAX) && (min.y == FLT_MAX) && (min.y == FLT_MAX) &&
3768         (max.x == FLT_MIN) && (max.y == FLT_MIN) && (max.y == FLT_MIN))
3769         return Vec3f(0, 0, 0);
3770     return Vec3f(max.x - min.x, max.y - min.y, max.z - min.z);
3771 }
3772 
3773 Vec3f
getBboxCenter(void)3774 Node::getBboxCenter(void)
3775 {
3776     Vec3f min = getMinBoundingBox();
3777     Vec3f max = getMaxBoundingBox();
3778     if ((min.x == FLT_MAX) && (min.y == FLT_MAX) && (min.y == FLT_MAX) &&
3779         (max.x == FLT_MIN) && (max.y == FLT_MIN) && (max.y == FLT_MIN))
3780         return Vec3f(0, 0, 0);
3781     return Vec3f((max.x + min.x) / 2.0f,
3782                  (max.y + min.y) / 2.0f,
3783                  (max.z + min.z) / 2.0f);
3784 }
3785 
3786 void
appendComment(Node * node)3787 Node::appendComment(Node *node)
3788 {
3789     m_commentsList->append(node);
3790 }
3791 
appendTo(NodeList * nodelist)3792 void Node::appendTo(NodeList* nodelist)
3793 {
3794     for (long i = 0;i < m_commentsList->size(); i++)
3795        nodelist->append((*m_commentsList)[i]);
3796     nodelist->append(this);
3797     m_commentsList->resize(0);
3798 }
3799 
3800 void
doWithParents(DoWithNodeCallback callback,void * data,bool searchInRest,bool callSelf)3801 Node::doWithParents(DoWithNodeCallback callback, void *data,
3802                     bool searchInRest, bool callSelf)
3803 {
3804     for (long i = 0; i < m_parents.size(); i++) {
3805         bool call = true;
3806         if ((long)i == m_geometricParentIndex)
3807             if (!callSelf)
3808                 call = false;
3809         if (call)
3810             if (!callback(m_parents[i].m_node, data))
3811                 if (!searchInRest)
3812                     break;
3813     }
3814 }
3815 
3816 void
doWithSiblings(DoWithNodeCallback callback,void * data,bool searchInRest,bool callSelf)3817 Node::doWithSiblings(DoWithNodeCallback callback, void *data,
3818                      bool searchInRest, bool callSelf)
3819 {
3820     if (hasParent()) {
3821         Node *parent = getParent();
3822         int parentField = getParentField();
3823         FieldValue *parentValue = parent->getField(parentField);
3824         if (parentValue->getType() == MFNODE) {
3825             MFNode *value = (MFNode *)parentValue;
3826             for (int i = 0; i < value->getSize(); i++) {
3827                 Node *sibling = value->getValue(i);
3828                 if (sibling != NULL) {
3829                     bool call = true;
3830                     if (sibling == this)
3831                         if (!callSelf)
3832                             call = false;
3833                     if (call)
3834                         if (!callback(sibling, data))
3835                             if (!searchInRest)
3836                                 break;
3837                 }
3838             }
3839         }
3840     }
3841 }
3842 
3843 void
doWithNextSiblings(DoWithNodeCallback callback,void * data,bool searchInRest,bool callSelf)3844 Node::doWithNextSiblings(DoWithNodeCallback callback, void *data,
3845                          bool searchInRest, bool callSelf)
3846 {
3847     bool skip = true;
3848     if (hasParent()) {
3849         Node *parent = getParent();
3850         int parentField = getParentField();
3851         FieldValue *parentValue = parent->getField(parentField);
3852         if (parentValue->getType() == MFNODE) {
3853             MFNode *value = (MFNode *)parentValue;
3854             for (int i = 0; i < value->getSize(); i++) {
3855                 Node *sibling = value->getValue(i);
3856                 if (sibling != NULL) {
3857                     bool call = true;
3858                     if (sibling == this) {
3859                         skip = false;
3860                         if (!callSelf)
3861                             call = false;
3862                     }
3863                     if (call && (!skip))
3864                         if (!callback(sibling, data))
3865                             if (!searchInRest)
3866                                 break;
3867                 }
3868             }
3869         }
3870     }
3871 }
3872 
doWithBranch(DoWithNodeCallback callback,void * data,bool searchInRest,bool skipBranch,bool skipProto,bool callSelf,bool skipInline,bool searchInConvertedNodes)3873 bool Node::doWithBranch(DoWithNodeCallback callback, void *data,
3874                         bool searchInRest, bool skipBranch,
3875                         bool skipProto, bool callSelf, bool skipInline,
3876                         bool searchInConvertedNodes)
3877 {
3878 #ifdef HAVE_NULL_COMPARE
3879     if (this == NULL)
3880         return false;
3881 #endif
3882     if (TheApp->getSkipChecks())
3883         return false;
3884     bool searchOn = true;
3885     bool handleInline = !skipInline;
3886     if (searchOn && (!skipProto) && hasProtoNodes()) {
3887         NodePROTO *nodeProto = (NodePROTO *)this;
3888         for (int i = 0; i < nodeProto->getNumProtoNodes(); i++)
3889             if (!(nodeProto->getProtoNode(i)->doWithBranch(callback, data,
3890                   false, true, false, true, skipInline,
3891                   searchInConvertedNodes)))
3892                 return false;
3893     }
3894     // search in current node itself
3895     if (callSelf)
3896         searchOn = callback(this, data);
3897     if (searchOn)
3898         for (int i = 0; i < getNumConvertedNodes(); i++) {
3899             searchOn = callback(getConvertedNode(i), data);
3900             if (!searchOn)
3901                 break;
3902         }
3903     if (searchOn) {
3904         // search in children of of current node
3905         for (int i = 0; i < m_proto->getNumFields(); i++) {
3906             if (m_scene->isInvalidElement(m_proto->getField(i)))
3907                 continue;
3908 
3909             if (m_proto->getField(i) &&
3910                 m_proto->getField(i)->getType() == SFNODE) {
3911                 Node *child = ((SFNode *)getField(i))->getValue();
3912                 if (child) {
3913                     if (child == this) {
3914                         swDebugf("%s %s: %s",
3915                                  "Warning: simple cyclic scenegraph: USE",
3916                                  (const char *)getName(),
3917                                  "invalid VRML/X3D file...\n");
3918                         return false;
3919                     }
3920                     if (child == getParent()) {
3921                         swDebugf("%s %s: %s",
3922                                  "Warning: simple cyclic scenegraph: USE",
3923                                   (const char *)getName(),
3924                                   "invalid VRML/X3D file...\n");
3925                         return false;
3926                     }
3927                     if (!child->doWithBranch(callback, data, false,
3928                                              skipBranch, skipProto, callSelf,
3929                                              skipInline, searchInConvertedNodes)) {
3930                         if (skipBranch)
3931                             continue;
3932                         else
3933                             return false;
3934                     }
3935                 }
3936             } else {
3937                 NodeList *childList = NULL;
3938                 if (handleInline && ((getType() == VRML_INLINE) ||
3939                                      (getType() == VRML_INLINE_LOAD_CONTROL))) {
3940                      NodeInline *node = (NodeInline *)this;
3941                      childList = node->getLoadedNodes();
3942                      handleInline = false;
3943                 }
3944                 if (m_proto->getField(i) &&
3945                     m_proto->getField(i)->getType() == MFNODE)
3946                     childList = ((MFNode *)getField(i))->getValues();
3947                 if (childList) {
3948                     for (long j = 0; j < childList->size(); j++) {
3949                         Node *child = childList->get(j);
3950                         if (child == this) {
3951                             swDebugf("%s %s: %s",
3952                                      "Warning: simple cyclic scenegraph: USE",
3953                                      (const char *)getName(),
3954                                      "invalid VRML/X3D file...\n");
3955                             return false;
3956                         }
3957                         if (child == getParent()) {
3958                             swDebugf("%s %s: %s",
3959                                      "Warning: simple cyclic scenegraph: USE",
3960                                      (const char *)getName(),
3961                                      "invalid VRML/X3D file...\n");
3962                             return false;
3963                         }
3964                         if (child) {
3965                             if (!child->doWithBranch(callback, data,
3966                                                      false, skipBranch,
3967                                                      skipProto, callSelf,
3968                                                      skipInline,
3969                                                      searchInConvertedNodes)) {
3970                                 if (skipBranch)
3971                                     continue;
3972                                 else
3973                                     return false;
3974                             }
3975                         }
3976                     }
3977                 }
3978             }
3979         }
3980         if (searchInRest) {
3981             // search in next children of current parent
3982             if (this != m_scene->getRoot()) {
3983                 m_scene->getNodes()->clearFlag(NODE_FLAG_TOUCHED);
3984                 if (hasParent() && isInScene(m_scene)) {
3985                     Node *parent = getParent();
3986                     FieldValue *selfField = parent->getField(getParentField());
3987                     if ((selfField != NULL) &&
3988                         (selfField->getType() == MFNODE)) {
3989                         int index = parent->findChild(this, getParentField());
3990                         MFNode *mfNode = (MFNode *)selfField;
3991                         NodeList *childList = mfNode->getValues();
3992                         if (childList)
3993                             for (long j = index + 1; j < childList->size();
3994                                  j++) {
3995                                 Node *child = childList->get(j);
3996                                 if (child) {
3997                                     if (child == getParent()) {
3998                                         swDebugf("%s %s: %s",
3999                                                  "Warning: simple cyclic scenegraph: USE",
4000                                                  (const char *)getName(),
4001                                                  "invalid VRML/X3D file...\n");
4002                                                   return false;
4003                                     }
4004                                     if (!child->doWithBranch(callback, data,
4005                                            false, skipBranch, skipProto,
4006                                            callSelf, skipInline,
4007                                            searchInConvertedNodes)) {
4008                                         if (skipBranch)
4009                                             continue;
4010                                         else
4011                                             return false;
4012                                     }
4013                                 }
4014                             }
4015                         }
4016                     }
4017                 }
4018         }
4019     }
4020     return searchOn;
4021 }
4022 
4023 bool
doWithSimilarBranch(DoWithSimilarBranchCallback callback,Node * similarNode,void * data)4024 Node::doWithSimilarBranch(DoWithSimilarBranchCallback callback,
4025                           Node *similarNode, void *data)
4026 {
4027     if (!callback(this, similarNode, data))
4028         return false;
4029     if (m_numFields != similarNode->getProto()->getNumFields())
4030         return false;
4031     for (int i = 0; i < m_numFields; i++) {
4032         if (m_fields[i]->getType() == SFNODE) {
4033             if (similarNode->getField(i)->getType() != SFNODE)
4034                 return false;
4035             Node *child = ((SFNode *) m_fields[i])->getValue();
4036             Node *node = ((SFNode *) similarNode->getField(i))->getValue();
4037             if (child && node) {
4038                 if (!child->doWithSimilarBranch(callback, node, data))
4039                     return false;
4040             } else if (child || node)
4041                 return false;
4042         } else if (m_fields[i]->getType() == MFNODE) {
4043             if (similarNode->getField(i)->getType() != MFNODE)
4044                 return false;
4045             NodeList *childList = ((MFNode *) m_fields[i])->getValues();
4046             NodeList *nodeList = ((MFNode *)
4047                                   similarNode->getField(i))->getValues();
4048             if (childList && nodeList) {
4049                 if (childList->size() != nodeList->size())
4050                     return false;
4051                 for (long j = 0; j < childList->size(); j++) {
4052                     Node *child = childList->get(j);
4053                     Node *node = nodeList->get(j);
4054                     if (child && node) {
4055                         if (!child->doWithSimilarBranch(callback, node, data))
4056                             return false;
4057                     } else if (child || node)
4058                         return false;
4059                 }
4060             } else if ((childList != NULL) || (nodeList != NULL))
4061                 return false;
4062         }
4063     }
4064     return true;
4065 }
4066 
4067 void
copyChildrenTo(Node * copyedNode,bool copyNonNodes)4068 Node::copyChildrenTo(Node *copyedNode, bool copyNonNodes)
4069 {
4070     for (int i = 0; i < m_numFields; i++) {
4071         if (m_fields[i] && m_fields[i]->getType() == SFNODE) {
4072             Node *child = ((SFNode *) m_fields[i])->getValue();
4073             if (child) {
4074                 long id = getId();
4075                 Node *copyChild = child->copy();
4076                 copyChild->setId(id);
4077                 copyChild->ref();
4078                 copyedNode->unSetVariableName();
4079                 copyedNode->setField(i, new SFNode(copyChild));
4080                 child->copyChildrenTo(copyChild, copyNonNodes);
4081                 child->copyOutputsTo(copyChild);
4082                 child->copyInputsTo(copyChild);
4083             }
4084         } else if (m_fields[i] && m_fields[i]->getType() == MFNODE) {
4085             NodeList *childList = ((MFNode *) m_fields[i])->getValues();
4086             if (childList) {
4087                 MFNode *field = new MFNode((MFNode *)m_fields[i]);
4088                 if (field) {
4089                     copyedNode->setField(i, field);
4090                     MFNode *mfnode = (MFNode *) copyedNode->getField(i);
4091                     for (long j = 0; j < childList->size(); j++) {
4092                         Node *copyChild = mfnode->getValue(j);
4093                         if (copyChild && childList->get(j)) {
4094                             childList->get(j)->ref();
4095                             childList->get(j)->unSetVariableName();
4096                             childList->get(j)->copyChildrenTo(copyChild,
4097                                                               copyNonNodes);
4098                             childList->get(j)->copyOutputsTo(copyChild);
4099                             childList->get(j)->copyInputsTo(copyChild);
4100                         }
4101                     }
4102                 }
4103             } else if (m_fields[i] && copyNonNodes) {
4104                 FieldValue *value = m_fields[i];
4105                 if (value)
4106                     setField(i, value->copy());
4107             }
4108         }
4109     }
4110 }
4111 
4112 void
copyOutputsTo(Node * copyedNode)4113 Node::copyOutputsTo(Node *copyedNode)
4114 {
4115     for (int i = 0; i < m_proto->getNumEventOuts(); i++) {
4116         for (SocketList::Iterator *j = getOutput(i).first();
4117              j != NULL; j = j->next())
4118             copyedNode->addOutput(i, j->item().getNode(),
4119                                      j->item().getField());
4120     }
4121 }
4122 
4123 
4124 void
copyInputsTo(Node * copyedNode)4125 Node::copyInputsTo(Node *copyedNode)
4126 {
4127     for (int i = 0; i < m_proto->getNumEventIns(); i++) {
4128         for (SocketList::Iterator *j = getInput(i).first();
4129              j != NULL; j = j->next())
4130             copyedNode->addInput(i, j->item().getNode(),
4131                                      j->item().getField());
4132     }
4133 }
4134 
4135 void
doWithAllElements(DoWithAllElementsCallback callback,void * data)4136 Node::doWithAllElements(DoWithAllElementsCallback callback, void *data)
4137 {
4138     int i = 0;
4139     for (i = 0; i < m_proto->getNumFields(); i++)
4140         callback(m_proto->getField(i), data);
4141     for (i = 0; i < m_proto->getNumEventIns(); i++)
4142         callback(m_proto->getEventIn(i), data);
4143     for (i = 0; i < m_proto->getNumEventOuts(); i++)
4144         callback(m_proto->getEventOut(i), data);
4145     for (i = 0; i < m_proto->getNumExposedFields(); i++)
4146         callback(m_proto->getExposedField(i), data);
4147 }
4148 
4149 void
removeChildren(void)4150 NodeData::removeChildren(void)
4151 {
4152     for (int i = 0; i < m_numFields; i++)
4153         if (m_fields[i]->getType() == SFNODE)
4154             setField(i, new SFNode(NULL));
4155         else if (m_fields[i]->getType() == MFNODE)
4156             setField(i, new MFNode());
4157 }
4158 
4159 void
handleIs(void)4160 NodeData::handleIs(void)
4161 {
4162     // PROTO initialisation ready ?
4163     if (!getProto()->isLoaded())
4164         return;
4165 
4166     bool x3d = m_scene->isX3d();
4167 
4168     // handle IS
4169     for (int i = 0; i < m_proto->getNumExposedFields(); i++) {
4170         m_isExposedFields[i] = NULL;
4171         ExposedField *field = m_proto->getExposedField(i);
4172         if (field && field->getFlags() & FF_IS)
4173             for (int j = 0; j < field->getNumIs(); j++)
4174                 if (field->getFlags() & FF_IS) {
4175                     Node *isNode = field->getIsNode(j);
4176                     Proto *proto = isNode->getProto();
4177                     if (field->getIsField(j) < 0)
4178                         continue;
4179                     FieldValue *value = field->getValue()->copy();
4180                     if ((isNode != NULL))
4181                         isNode->setField(field->getIsField(j), value);
4182                     m_isExposedFields[i] = new ExposedField(field);
4183                     isNode->addIsElement((Node *)this, i,
4184                                          EL_EXPOSED_FIELD, proto,
4185                                          field->getIsField(j),
4186                                          field->getIsField(j));
4187             }
4188     }
4189     for (int i = 0; i < m_proto->getNumFields(); i++) {
4190         m_isFields[i] = NULL;
4191         Field *field = m_proto->getField(i);
4192         if (field && field->getFlags() & FF_IS)
4193             for (int j = 0; j < field->getNumIs(); j++)
4194                 if (field->getFlags() & FF_IS) {
4195                     Node *isNode = field->getIsNode(j);
4196                     Proto *proto = isNode->getProto();
4197                     FieldValue *value = field->getDefault(x3d)->copy();
4198                     if ((isNode != NULL)) {
4199                         isNode->setField(field->getIsField(j), value);
4200                     }
4201                     m_isFields[i] = new Field(field);
4202                     isNode->addIsElement((Node *)this, i, EL_FIELD, proto,
4203                                          field->getIsField(j),
4204                                          field->getIsField(j));
4205                 }
4206     }
4207 
4208     for (int i = 0; i < m_proto->getNumEventOuts(); i++) {
4209         m_isEventOuts[i] = NULL;
4210         EventOut *eventOut = m_proto->getEventOut(i);
4211         if (eventOut && eventOut->getFlags() & FF_IS)
4212             for (int j = 0; j < eventOut->getNumIs(); j++)
4213                 if (eventOut->getFlags() & EOF_IS) {
4214                     Node *isNode = eventOut->getIsNode(j);
4215                     Proto *proto = isNode->getProto();
4216                     int evOut = eventOut->getIsField(j);
4217                     if (evOut < 0)
4218                         continue;
4219                     m_isEventOuts[i] = new EventOut(eventOut);
4220                     isNode->addIsElement((Node *)this, i, EL_EVENT_OUT,
4221                                          proto, evOut, EOF_IS_HIDDEN);
4222                 }
4223     }
4224     for (int i = 0; i < m_proto->getNumEventIns(); i++) {
4225         m_isEventIns[i] = NULL;
4226         EventIn *eventIn = m_proto->getEventIn(i);
4227         if (eventIn && eventIn->getFlags() & FF_IS)
4228             for (int j = 0; j < eventIn->getNumIs(); j++)
4229                 if (eventIn->getFlags() & EIF_IS) {
4230                     Node *isNode = eventIn->getIsNode(j);
4231                     Proto *proto = isNode->getProto();
4232                     int evIn = eventIn->getIsField(j);
4233                     m_isEventIns[i] = new EventIn(eventIn);
4234                     isNode->addIsElement((Node *)this, i, EL_EVENT_IN,
4235                                          proto, evIn, EIF_IS_HIDDEN);
4236                 }
4237     }
4238 }
4239 
4240 Node *
getIsNode(int nodeIndex)4241 NodeData::getIsNode(int nodeIndex)
4242 {
4243     NodePROTO *nodeProto = (NodePROTO *)this;
4244     if (nodeIndex < 0)
4245         return NULL;
4246     Node *nodeInPROTO = nodeProto->getIsNode(nodeIndex);
4247     if (nodeInPROTO)
4248         return nodeInPROTO;
4249     return NULL;
4250 }
4251 
4252 bool
isDefault(int field) const4253 NodeData::isDefault(int field) const
4254 {
4255     bool x3d = m_scene->isX3d();
4256 
4257     if (getProto()->getField(field) == NULL)
4258         return false;
4259     if (m_fields[field] == NULL)
4260         return false;
4261     return m_fields[field]->equals(
4262                 getProto()->getField(field)->getDefault(x3d));
4263 }
4264 
4265 bool
isDefaultAngle(int field) const4266 NodeData::isDefaultAngle(int field) const
4267 {
4268     bool x3d = m_scene->isX3d();
4269     double angleUnit = m_scene->getUnitAngle();
4270     if (angleUnit == 0)
4271         angleUnit = 1;
4272     return m_fields[field]->equalsAngle(
4273                getProto()->getField(field)->getDefault(x3d), angleUnit);
4274 }
4275 
4276 bool
hasInputsOrIs(void)4277 NodeData::hasInputsOrIs(void)
4278 {
4279     if (hasInputs())
4280         return true;
4281     for (int i = 0; i < m_proto->getNumFields(); i++) {
4282         Field *field = getProto()->getField(i);
4283         if (field->getFlags() & FF_HIDDEN)
4284             continue;
4285         if (isInsideProto() && getOutsideProto()->lookupIsField((Node *)this, i)
4286             != -1)
4287             return true;
4288     }
4289     return false;
4290 }
4291 
4292 bool
hasInputsIs(void)4293 NodeData::hasInputsIs(void)
4294 {
4295     for (int i = 0; i < m_proto->getNumEventIns(); i++) {
4296         EventIn *eventIn = getProto()->getEventIn(i);
4297         if (eventIn == NULL)
4298             continue;
4299         if (eventIn->getFlags() & FF_HIDDEN)
4300             continue;
4301         if (isPROTO() && getProto()->lookupIsEventIn((Node *)this, i) != -1)
4302             return true;
4303     }
4304     return false;
4305 }
4306 
4307 bool
hasOutputsOrIs(void)4308 NodeData::hasOutputsOrIs(void)
4309 {
4310     if (hasOutputs())
4311         return true;
4312     for (int i = 0; i < m_proto->getNumEventOuts(); i++)
4313         if (isInsideProto() && getOutsideProto()->lookupIsEventOut(
4314                                    (Node *)this, i)
4315             != -1)
4316             return true;
4317     for (int i = 0; i < m_proto->getNumExposedFields(); i++)
4318         if (isInsideProto() && getOutsideProto()->lookupIsExposedField(
4319                                    (Node *)this, i)
4320             != -1)
4321             return true;
4322     return false;
4323 }
4324 
4325 bool
hasInputs(void)4326 NodeData::hasInputs(void)
4327 {
4328     for (int j = 0; j < m_proto->getNumEventIns(); j++)
4329         if (getInput(j).size() > 0)
4330             return true;
4331     return false;
4332 }
4333 
4334 bool
hasOutputs(void)4335 NodeData::hasOutputs(void)
4336 {
4337     for (int j = 0; j < m_proto->getNumEventOuts(); j++)
4338         if (getOutput(j).size() > 0)
4339             return true;
4340     return false;
4341 }
4342 
4343 bool
hasInput(const char * routename) const4344 NodeData::hasInput(const char* routename) const
4345 {
4346     bool x3d = m_scene->isX3d();
4347     for (int i = 0; i < m_proto->getNumEventIns(); i++)
4348         if (strcmp(m_proto->getEventIn(i)->getName(x3d), routename) == 0) {
4349             if (getInput(i).size() > 0)
4350                 return true;
4351             else
4352                 return false;
4353         }
4354     return false;
4355 }
4356 
4357 bool
hasOutput(const char * routename) const4358 NodeData::hasOutput(const char* routename) const
4359 {
4360     bool x3d = m_scene->isX3d();
4361     for (int i = 0; i < m_proto->getNumEventOuts(); i++)
4362         if (strcmp(m_proto->getEventOut(i)->getName(x3d), routename) == 0) {
4363             if (getOutput(i).size() > 0)
4364                 return true;
4365             else
4366                 return false;
4367         }
4368     assert(0);
4369     return false;
4370 }
4371 
4372 int
writeProtoArguments(int f) const4373 NodeData::writeProtoArguments(int f) const
4374 {
4375     int flags = m_scene->getWriteFlags() | WITHOUT_VALUE;
4376     for (int i = 0; i < m_proto->getNumFields(); i++) {
4377         if (m_scene->isInvalidElement(m_proto->getField(i)))
4378             continue;
4379         RET_ONERROR( m_proto->getField(i)->write(f, 1, flags) )
4380         TheApp->incSelectionLinenumber();
4381     }
4382     for (int i = 0; i < m_proto->getNumExposedFields(); i++) {
4383         if (m_scene->isInvalidElement(m_proto->getExposedField(i)))
4384             continue;
4385         RET_ONERROR( m_proto->getExposedField(i)->write(f, 1, flags) )
4386         TheApp->incSelectionLinenumber();
4387     }
4388     for (int i = 0; i < m_proto->getNumEventIns(); i++) {
4389         if (m_scene->isInvalidElement(m_proto->getEventIn(i)))
4390             continue;
4391         RET_ONERROR( m_proto->getEventIn(i)->write(f, 1, flags) )
4392         TheApp->incSelectionLinenumber();
4393     }
4394     for (int i = 0; i < m_proto->getNumEventOuts(); i++) {
4395         if (m_scene->isInvalidElement(m_proto->getEventOut(i)))
4396             continue;
4397         RET_ONERROR( m_proto->getEventOut(i)->write(f, 1, flags) )
4398         TheApp->incSelectionLinenumber();
4399     }
4400     return 0;
4401 }
4402 
4403 bool
hasDefault(int flag)4404 NodeData::hasDefault(int flag)
4405 {
4406     bool x3d = m_scene->isX3d();
4407     for (int i = 0; i < m_numFields; i++) {
4408         Field *field = m_proto->getField(i);
4409         if (field->getFlags() & flag)
4410             if (!(m_fields[i]->equals(field->getDefault(x3d))))
4411                 return false;
4412     }
4413     return true;
4414 }
4415 
searchInputs(Node * node,void * data)4416 static bool searchInputs(Node *node, void *data)
4417 {
4418     bool *result = (bool *)data;
4419     if (node->hasInputs()) {
4420         *result = true;
4421         return false;
4422     }
4423     return true;
4424 }
4425 
4426 bool
hasBranchInputs(void)4427 Node::hasBranchInputs(void)
4428 {
4429     bool result = false;
4430     doWithBranch(searchInputs, &result);
4431     return result;
4432 }
4433 
removeConvertedNode(Node * node,void * data)4434 static bool removeConvertedNode(Node *node, void *data)
4435 {
4436     if (node != NULL) {
4437         node->removeRoutes();
4438         node->getScene()->removeNode(node);
4439         node->getScene()->undef(node->getName());
4440         node->getScene()->OnRemoveNode(node, NULL, -1);
4441     }
4442     return true;
4443 }
4444 
4445 
4446 void
deleteConvertedNodes(void)4447 NodeData::deleteConvertedNodes(void)
4448 {
4449     for (long i = 0; i < m_convertedNodes.size(); i++)
4450         m_convertedNodes[i]->doWithBranch(removeConvertedNode, NULL,
4451                                          false);
4452     m_convertedNodes.resize(0);
4453 }
4454 
4455 bool
needExtraJavaClass(void)4456 NodeData::needExtraJavaClass(void)
4457 {
4458     if (m_convertedNodes.size() > 0)
4459         for (long i = 0; i < m_convertedNodes.size(); i++)
4460             if (m_convertedNodes[i]->needExtraJavaClass())
4461                 return true;
4462 //    if (hasName() || (m_scene->getRoot() == this))
4463     if ((m_scene->getRoot() == this))
4464         return false;
4465     return true;
4466 }
4467 
4468 bool
writeJavaOutsideClass(int languageFlag)4469 NodeData::writeJavaOutsideClass(int languageFlag)
4470 {
4471     return ((languageFlag & MANY_JAVA_CLASSES) &&
4472             (languageFlag & OUTSIDE_JAVA_CLASS));
4473 }
4474 
4475 void
generateTreeLabel(void)4476 NodeData::generateTreeLabel(void)
4477 {
4478     m_treeLabel = "";
4479     if (TheApp->is4Catt())
4480         if (isMesh()) {
4481             if (hasTwoSides()) {
4482                if (isDoubleSided())
4483                    m_treeLabel += "(2 sides) ";
4484                else
4485                    m_treeLabel += "(1 side) ";
4486             } else
4487                m_treeLabel += "(only 1 side) ";
4488         }
4489     m_treeLabel += getName();
4490     if (hasName())
4491         m_treeLabel += " ";
4492     const char *protoName = m_proto->getName(m_scene->isX3d());
4493     m_treeLabel += protoName;
4494 }
4495 
4496 Node *
getParentOrProtoParent(void) const4497 Node::getParentOrProtoParent(void) const
4498 {
4499     Node *parent = getParent();
4500     if (parent == NULL)
4501         if (((NodeData *)this)->isInsideProto() && (m_nodePROTO != NULL))
4502             return m_nodePROTO->getParent();
4503     return parent;
4504 }
4505 
4506 int
getParentFieldOrProtoParentField(void) const4507 Node::getParentFieldOrProtoParentField(void) const
4508 {
4509     Node *parent = getParent();
4510     if (parent == NULL)
4511         if (((NodeData *)this)->isInsideProto() && (m_nodePROTO != NULL))
4512             return m_nodePROTO->getParentField();
4513     return getParentField();
4514 }
4515 
4516 int
getParentIndex(void) const4517 Node::getParentIndex(void) const
4518 {
4519     FieldValue *value = getParentFieldValue();
4520     if (value == NULL)
4521         return -1;
4522     if (value->getType() == MFNODE) {
4523         MFNode *mfValue = (MFNode *)value;
4524         for (int i = 0; i < mfValue->getSize(); i++) {
4525             Node *node = mfValue->getValue(i);
4526             if (node->isEqual((Node *)this))
4527                 if (m_geometricParentIndex == node->getGeometricParentIndex())
4528                     return i;
4529             }
4530     }
4531     return -1;
4532 }
4533 
4534 Node *
searchParent(int nodeType) const4535 Node::searchParent(int nodeType) const
4536 {
4537     for (long i = 0; i < m_parents.size(); i++) {
4538         Node *node = m_parents[i].m_node;
4539         if (node->getType() == nodeType)
4540             return node;
4541     }
4542     return getParent();
4543 }
4544 
4545 Node *
searchParentField(int parentField) const4546 Node::searchParentField(int parentField) const
4547 {
4548     for (long i = 0; i < m_parents.size(); i++) {
4549         if (m_parents[i].m_field == parentField)
4550             return m_parents[i].m_node;
4551     }
4552     return getParent();
4553 }
4554 
4555 FieldValue *
getParentFieldValue(void) const4556 Node::getParentFieldValue(void) const
4557 {
4558     if (!hasParent())
4559         return NULL;
4560     Node *parent = getParent();
4561     int parentField = getParentField();
4562     return parentField == -1 ? NULL : parent->getField(parentField);
4563 }
4564 
4565 void
setParentFieldValue(FieldValue * value)4566 Node::setParentFieldValue(FieldValue *value)
4567 {
4568     if (!hasParent())
4569         return;
4570     Node *parent = getParent();
4571     int parentField = getParentField();
4572     if (parentField > -1)
4573         parent->setField(parentField, value);
4574 }
4575 
4576 int
getSiblingIndex(void)4577 Node::getSiblingIndex(void)
4578 {
4579     int parentIndex = getParentIndex();
4580     if (parentIndex > -1)
4581         return parentIndex;
4582     return -1;
4583 }
4584 
4585 int
getPrevSiblingIndex(void)4586 Node::getPrevSiblingIndex(void)
4587 {
4588     int parentIndex = getParentIndex();
4589     if (parentIndex > 0)
4590         return parentIndex - 1;
4591     return -1;
4592 }
4593 
4594 int
getNextSiblingIndex(void)4595 Node::getNextSiblingIndex(void)
4596 {
4597     FieldValue *value = getParentFieldValue();
4598     if (value == NULL)
4599         return -1;
4600     if (value->getType() == MFNODE) {
4601         MFNode *mfValue = (MFNode *)value;
4602         for (int i = 0; i < mfValue->getSize() - 1; i++) {
4603             Node *node = mfValue->getValue(i);
4604             if (node->isEqual((Node *)this))
4605                 if (m_geometricParentIndex == node->getGeometricParentIndex())
4606                     return i + 1;
4607             }
4608     }
4609     return -1;
4610 }
4611 
4612 Node *
getPrevSibling(void)4613 Node::getPrevSibling(void)
4614 {
4615     FieldValue *value = getParentFieldValue();
4616     if (value == NULL)
4617         return NULL;
4618     if (value->getType() == MFNODE) {
4619         MFNode *mfValue = (MFNode *)value;
4620         int parentIndex = getParentIndex();
4621         if (parentIndex > 0)
4622             return mfValue->getValue(parentIndex - 1);
4623     }
4624     return NULL;
4625 }
4626 
4627 Node *
getNextSibling(void)4628 Node::getNextSibling(void)
4629 {
4630     FieldValue *value = getParentFieldValue();
4631     if (value == NULL)
4632         return NULL;
4633     if (value->getType() == MFNODE) {
4634         MFNode *mfValue = (MFNode *)value;
4635         for (int i = 0; i < mfValue->getSize() - 1; i++) {
4636             Node *node = mfValue->getValue(i);
4637             if (node->isEqual((Node *)this))
4638                 if (m_geometricParentIndex == node->getGeometricParentIndex())
4639                     return mfValue->getValue(i + 1);
4640             }
4641     }
4642     return NULL;
4643 }
4644 
4645 void
setDefault(void)4646 NodeData::setDefault(void)
4647 {
4648     bool x3d = m_scene->isX3d();
4649     for (int i = 0; i < m_numFields; i++) {
4650         Field *field = m_proto->getField(i);
4651         if ((field->getType() != SFNODE) && (field->getType() != MFNODE))
4652             m_scene->setField((Node *)this, i, field->getDefault(x3d)->copy());
4653     }
4654 }
4655 
4656 void
setNodePROTO(NodePROTO * node)4657 Node::setNodePROTO(NodePROTO *node)
4658 {
4659     m_nodePROTO = node;
4660     m_insideProto = ((Node *)node)->getProto();
4661     setProtoParent(node);
4662 }
4663 
4664 
4665 bool
isDeepInsideProto(void)4666 Node::isDeepInsideProto(void)
4667 {
4668     if (m_insideProto)
4669         return true;
4670     if (isPROTO())
4671         return true;
4672 #ifdef HAVE_NULL_COMPARE
4673     if (this == NULL)
4674         return false;
4675 #endif
4676     Node *parent = this;
4677     if (hasParent())
4678          while (parent->hasParent()) {
4679              if (parent->isInsideProto())
4680                  return true;
4681              parent = parent->getParent();
4682         }
4683     else
4684         return false;
4685     return false;
4686 }
4687 
4688 char*
getExportMaterialName(const char * defaultName)4689 Node::getExportMaterialName(const char *defaultName)
4690 {
4691     Node *node = this;
4692     // search for DEF name till root of scenegraph
4693     while (1) {
4694         if (node->hasName()) {
4695             char *name = strdup(node->getName());
4696             if (TheApp->SkipMaterialNameBeforeFirstUnderscore()) {
4697                 char *lastPartOfName = strchr(name, '_');
4698                 if (lastPartOfName) {
4699                     if (strlen(lastPartOfName + 1) > 0) {
4700                         name = lastPartOfName + 1;
4701                     } else if (defaultName != NULL) {
4702                         return buildExportMaterialName(defaultName);
4703                     }
4704                 }
4705             }
4706             if (TheApp->SkipMaterialNameAfterLastUnderscore()) {
4707                 char *endPointer = (char *)strrchr(name, '_');
4708                 if (endPointer) {
4709                     endPointer[0] = 0;
4710                     if ((strlen(name) == 0) && (defaultName != NULL))
4711                         return buildExportMaterialName(defaultName);
4712                 }
4713             }
4714             return buildExportMaterialName(name);
4715         } else {
4716             if (node->hasParent())
4717                 node = node->getParent();
4718             else {
4719                if (defaultName != NULL)
4720                    return buildExportMaterialName(defaultName);
4721             }
4722         }
4723     }
4724     return buildExportMaterialName(defaultName);
4725 }
4726 
4727 
4728 Node *
convert2X3d(void)4729 NodeData::convert2X3d(void) {
4730     if (getFlag(NODE_FLAG_CONVERTED))
4731         return NULL;
4732     setFlag(NODE_FLAG_CONVERTED);
4733     for (int i = 0; i < m_numFields; i++)
4734         if (m_fields[i] != NULL) {
4735            if (m_fields[i]->getType() == SFNODE) {
4736                if (((SFNode *) m_fields[i])->getValue())
4737                    ((SFNode *) m_fields[i])->getValue()->convert2X3d();
4738            } else if (m_fields[i]->getType() == MFNODE)
4739                ((MFNode *) m_fields[i])->convert2X3d();
4740         }
4741     return NULL;
4742 }
4743 
4744 Node *
convert2Vrml(void)4745 NodeData::convert2Vrml(void) {
4746     if (getFlag(NODE_FLAG_CONVERTED))
4747         return NULL;
4748     setFlag(NODE_FLAG_CONVERTED);
4749     for (int i = 0; i < m_numFields; i++)
4750         if (m_fields[i] != NULL) {
4751            if (m_fields[i]->getType() == SFNODE) {
4752                if (((SFNode *) m_fields[i])->getValue())
4753                    ((SFNode *) m_fields[i])->getValue()->convert2Vrml();
4754            } else if (m_fields[i]->getType() == MFNODE)
4755                ((MFNode *) m_fields[i])->convert2Vrml();
4756         }
4757     return NULL;
4758 }
4759 
4760 bool
canWriteAc3d(void)4761 NodeData::canWriteAc3d(void)
4762 {
4763     for (int i = 0; i < m_numFields; i++)
4764         if (m_fields[i] != NULL) {
4765             if (m_fields[i]->getType() == SFNODE) {
4766                 Node *node = ((SFNode *)m_fields[i])->getValue();
4767                 if (node && (node != this)) // avoid simple cyclic scenegraph
4768                     return node->canWriteAc3d();
4769             } else if (m_fields[i]->getType() == MFNODE) {
4770                 MFNode *nodes = (MFNode *) m_fields[i];
4771                 for (int j = 0; j < nodes->getSize(); j++) {
4772                     Node *node = nodes->getValue(j);
4773                     if (node && (node != this)) // avoid simple cyclic scenegraph
4774                         if (node->canWriteAc3d())
4775                             return true;
4776                 }
4777             }
4778         }
4779     return false;
4780 }
4781 
4782 int
writeAc3d(int f,int indent)4783 NodeData::writeAc3d(int f, int indent)
4784 {
4785     for (int i = 0; i < m_numFields; i++)
4786         if (m_fields[i] != NULL) {
4787            if (m_fields[i]->getType() == SFNODE)
4788                RET_ONERROR( ((SFNode *) m_fields[i])->writeAc3d(f, indent) )
4789            else if (m_fields[i]->getType() == MFNODE)
4790                RET_ONERROR( ((MFNode *) m_fields[i])->writeAc3d(f, indent) )
4791         }
4792     return 0;
4793 }
4794 
4795 int
writeRib(int f,int indent)4796 NodeData::writeRib(int f, int indent)
4797 {
4798     for (int i = 0; i < m_numFields; i++)
4799         if (m_fields[i] != NULL) {
4800            if (m_fields[i]->getType() == SFNODE)
4801                RET_ONERROR( ((SFNode *) m_fields[i])->writeRib(f, indent) )
4802            else if (m_fields[i]->getType() == MFNODE)
4803                RET_ONERROR( ((MFNode *) m_fields[i])->writeRib(f, indent) )
4804         }
4805     return 0;
4806 }
4807 
4808 
4809 int
writePovray(int f,int indent)4810 NodeData::writePovray(int f, int indent)
4811 {
4812     for (int i = 0; i < m_numFields; i++)
4813         if (m_fields[i] != NULL) {
4814            if (m_fields[i]->getType() == SFNODE)
4815                RET_ONERROR( ((SFNode *) m_fields[i])->writePovray(f, indent) )
4816            else if (m_fields[i]->getType() == MFNODE)
4817                RET_ONERROR( ((MFNode *) m_fields[i])->writePovray(f, indent) )
4818         }
4819     return 0;
4820 }
4821 
4822 void
handleAc3dMaterial(ac3dMaterialCallback callback,Scene * scene)4823 NodeData::handleAc3dMaterial(ac3dMaterialCallback callback, Scene* scene)
4824 {
4825     for (int i = 0; i < m_numFields; i++)
4826         if (m_fields[i] != NULL) {
4827            if (m_fields[i]->getType() == SFNODE) {
4828                SFNode *field = (SFNode *) m_fields[i];
4829                field->handleAc3dMaterial(callback, scene);
4830            } else if (m_fields[i]->getType() == MFNODE) {
4831                MFNode *field = (MFNode *) m_fields[i];
4832                field->handleAc3dMaterial(callback, scene);
4833            }
4834         }
4835 }
4836 
4837 long
getId(void)4838 NodeData::getId(void)
4839 {
4840     return m_identifier;
4841 }
4842 
4843 void
setId(long id)4844 NodeData::setId(long id)
4845 {
4846     m_identifier = id;
4847 }
4848 
4849 
4850 bool
isPROTO(void) const4851 NodeData::isPROTO(void) const
4852 {
4853     return false;
4854 }
4855 
4856 bool
canWriteCattGeo(void)4857 Node::canWriteCattGeo(void)
4858 {
4859     for (int i = 0; i < m_numFields; i++)
4860         if (m_fields[i] != NULL) {
4861            if (m_fields[i]->getType() == SFNODE) {
4862                Node *node = ((SFNode *)m_fields[i])->getValue();
4863                if (node && (node != this)) // avoid simple cyclic scenegraph
4864                    return node->canWriteCattGeo();
4865            } else if (m_fields[i]->getType() == MFNODE) {
4866                MFNode *nodes = (MFNode *) m_fields[i];
4867                for (int j = 0; j < nodes->getSize(); j++) {
4868                    Node *node = nodes->getValue(j);
4869                    if (node && (node != this)) // avoid simple cyclic scenegraph
4870                        if (node->canWriteCattGeo())
4871                            return true;
4872                }
4873            }
4874         }
4875     return false;
4876 }
4877 
4878 int
writeCattGeo(int f,int indent)4879 Node::writeCattGeo(int f, int indent)
4880 {
4881     for (int i = 0; i < m_numFields; i++)
4882         if (m_fields[i] != NULL) {
4883            if (m_fields[i]->getType() == SFNODE)
4884                RET_ONERROR( ((SFNode *) m_fields[i])->writeCattGeo(f, indent) )
4885            else if (m_fields[i]->getType() == MFNODE)
4886                RET_ONERROR( ((MFNode *) m_fields[i])->writeCattGeo((Node *)this,
4887                                                                    f, indent) )
4888         }
4889     return 0;
4890 }
4891 
4892 bool
canWriteLdrawDat(void)4893 NodeData::canWriteLdrawDat(void)
4894 {
4895     for (int i = 0; i < m_numFields; i++)
4896         if (m_fields[i] != NULL) {
4897            if (m_fields[i]->getType() == SFNODE) {
4898                Node *node = ((SFNode *)m_fields[i])->getValue();
4899                if (node && (node != this)) // avoid simple cyclic scenegraph
4900                    return node->canWriteLdrawDat();
4901            } else if (m_fields[i]->getType() == MFNODE) {
4902                MFNode *nodes = (MFNode *) m_fields[i];
4903                for (int j = 0; j < nodes->getSize(); j++) {
4904                    Node *node = nodes->getValue(j);
4905                    if (node && (node != this)) // avoid simple cyclic scenegraph
4906                        if (node->canWriteLdrawDat())
4907                            return true;
4908                }
4909            }
4910         }
4911     return false;
4912 }
4913 
4914 int
writeLdrawDat(int f,int indent)4915 NodeData::writeLdrawDat(int f, int indent)
4916 {
4917     for (int i = 0; i < m_numFields; i++)
4918         if (m_fields[i] != NULL) {
4919            if (m_fields[i]->getType() == SFNODE)
4920                RET_ONERROR( ((SFNode *) m_fields[i])->writeLdrawDat(f, indent) )
4921            else if (m_fields[i]->getType() == MFNODE)
4922                RET_ONERROR( ((MFNode *) m_fields[i])->writeLdrawDat(f, indent) )
4923         }
4924     return 0;
4925 }
4926 
4927 
4928 void
addToConvertedNodes(int writeFlags)4929 NodeData::addToConvertedNodes(int writeFlags)
4930 {
4931     if (m_alreadyConverted)
4932         return;
4933     // add to "m_convertedNodes"
4934     if (isMeshBasedNode())
4935         ((MeshBasedNode *)this)->addToConvertedNodes(writeFlags);
4936     m_alreadyConverted = true;
4937 }
4938 
4939 NodeHAnimHumanoid *
getHumanoid()4940 Node::getHumanoid()
4941 {
4942     NodeHAnimHumanoid *human = NULL;
4943     Node *child = this;
4944     while (child && (child != m_scene->getRoot()))  {
4945         if (child->getType() == X3D_HANIM_HUMANOID) {
4946             human = (NodeHAnimHumanoid *)child;
4947             break;
4948          }
4949          child = child->getParent();
4950     }
4951     return human;
4952 }
4953 
4954 bool
showFields()4955 Node::showFields()
4956 {
4957     if (m_proto->showFields())
4958         return true;
4959     return m_proto->showFields(m_scene->isX3d());
4960 }
4961 
4962 int
getContainerField(void)4963 Node::getContainerField(void)
4964 {
4965     return m_containerField;
4966 }
4967 
4968 void
setContainerField(int containerField)4969 Node::setContainerField(int containerField)
4970 {
4971     m_containerField = containerField;
4972 }
4973 
4974 NodeList
getParents(void)4975 Node::getParents(void)
4976 {
4977     NodeList ret;
4978     for (int i = 0; i < getNumParents(); i++)
4979         ret.append(getParent(i));
4980     return ret;
4981 }
4982 
4983 Node *
getIndexedFaceSet(void)4984 Node::getIndexedFaceSet(void) {
4985     if (isMeshBasedNode())
4986         return ((MeshBasedNode *)this)->getIndexedFaceSet();
4987     return NULL;
4988 }
4989 
4990 void
setAlreadyConverted(void)4991 Node::setAlreadyConverted(void)
4992 {
4993     if (isMeshBasedNode())
4994         ((MeshBasedNode *)this)->setAlreadyConverted();
4995 }
4996 
4997 bool
isCWriteable()4998 Node::isCWriteable()
4999 {
5000     bool x3d = getScene()->isX3d();
5001     if (getProto()->isX3dInternalProto())
5002         return true;
5003     if (getScene()->belongsToNodeWithExternProto(getProto()->getName(x3d)) ||
5004         getType() == VRML_NURBS_SURFACE || getType() == VRML_NURBS_CURVE)
5005         return false;
5006     return true;
5007 }
5008 
5009