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