1 /*
2 * Scene.cpp
3 *
4 * Copyright (C) 1999 Stephen F. White
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 /***************************************************************************
23 * Scene::Download() based on ftpget example of Curl library
24 *
25 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
26 *
27 * This software is licensed as described in the file COPYING, which
28 * you should have received as part of this distribution. The terms
29 * are also available at https://curl.haxx.se/docs/copyright.html.
30 *
31 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
32 * copies of the Software, and permit persons to whom the Software is
33 * furnished to do so, under the terms of the COPYING file.
34 *
35 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
36 * KIND, either express or implied.
37 *
38 ***************************************************************************/
39
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <limits.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <ctype.h>
48 #include "stdafx.h"
49 #ifndef _WIN32
50 # include <unistd.h>
51 # include <fcntl.h>
52 #endif
53 #include "Util.h"
54 #include "resource.h"
55
56 #ifdef HAVE_LIBZ
57 extern "C" {
58 # include "zlib.h"
59 }
60 #endif
61
62 #ifdef HAVE_LIBCURL
63 # include <curl/curl.h>
64 #endif
65
66 #include "swt.h"
67
68 #include "Scene.h"
69 #include "SceneProtoMap.h"
70 #include "SceneView.h"
71 #include "WonderlandModuleExport.h"
72 #include "Matrix.h"
73 #include "FieldValue.h"
74 #include "FieldCommand.h"
75 #include "MFieldCommand.h"
76 #include "CommandList.h"
77 #include "RouteCommand.h"
78 #include "UnRouteCommand.h"
79 #include "MoveCommand.h"
80 #include "Node.h"
81 #include "DynamicFieldsNode.h"
82 #include "SFNode.h"
83 #include "SFRotation.h"
84 #include "SFTime.h"
85 #include "MFNode.h"
86 #include "Proto.h"
87 #include "parser.h"
88 #include "Path.h"
89 #include "Field.h"
90 #include "EventIn.h"
91 #include "EventOut.h"
92 #include "ExposedField.h"
93 #include "URL.h"
94 #include "FontInfo.h"
95 #include "DuneApp.h"
96 #include "WriteFlags.h"
97 #include "RenderState.h"
98 #include "Interpolator.h"
99 #include "NextCommand.h"
100 #include "FaceData.h"
101
102 #include "NodeTimeSensor.h"
103 #include "NodeVrmlCut.h"
104 #include "NodeVrmlScene.h"
105 #include "NodeNavigationInfo.h"
106 #include "NodeViewpoint.h"
107 #include "NodeOrthoViewpoint.h"
108 #include "NodeGeoViewpoint.h"
109 #include "NodeBackground.h"
110 #include "NodeCurveAnimation.h"
111 #include "NodeFog.h"
112 #include "NodeInline.h"
113 #include "NodeGroup.h"
114 #include "NodeShape.h"
115 #include "NodeIndexedFaceSet.h"
116 #include "NodeIndexedLineSet.h"
117 #include "NodeIndexedTriangleSet.h"
118 #include "NodeTriangleSet.h"
119 #include "NodeNurbsCurve.h"
120 #include "NodeNurbsSurface.h"
121 #include "NodeCattExportRec.h"
122 #include "NodeLdrawDatExport.h"
123 #include "NodeViewport.h"
124 #include "NodeTransform.h"
125
126 #define ARRAY_SIZE(v) ((int) (sizeof(v) / sizeof(v[0])))
127
128 #define PICK_BUFFER_SIZE 65536
129 #define PICK_REGION_SIZE 2.5
130
131 #define MAX_JAVA_CALLS 8000
132
133 enum {
134 PICKED_NODE,
135 PICKED_HANDLE,
136 PICKED_RIGID_BODY_HANDLE,
137 PICKED_3DCURSOR
138 };
139
Scene()140 Scene::Scene()
141 {
142 m_writeFlags = 0;
143
144 m_numSymbols = 0;
145
146 m_headlight = true;
147 m_numLights = 0;
148 m_numClipPlanes = 0;
149 m_selection = NULL;
150 m_selectedHandles.resize(0);
151 m_selectionMode = TheApp->GetIntPreference("SelectionMode",
152 SELECTION_MODE_VERTICES);
153 m_lastSelectedHandle = -1;
154 m_isNewSelectedHandle = false;
155 m_singleSelectedHandle = true;
156 m_transformMode = new TransformMode(
157 (TMode) TheApp->GetIntPreference("TransformMode",TM_HOVER),
158 (TDimension) TheApp->GetIntPreference("TransformDimension",TM_3D),
159 (T2axes) TheApp->GetIntPreference("Transform2Axes",TM_NEAR_FAR));
160 if (TheApp->getMaxNumberAxesInputDevices()<=4)
161 if ((m_transformMode->tmode == TM_6D) || (m_transformMode->tmode == TM_6D))
162 m_transformMode->tmode = TM_HOVER;
163 if (TheApp->getMaxNumberAxesInputDevices()<3)
164 if (m_transformMode->tmode == TM_ROCKET)
165 m_transformMode->tmode = TM_HOVER;
166 if (TheApp->getMaxNumberAxesInputDevices()<2)
167 if (m_transformMode->tmode >= TM_6D)
168 m_transformMode->tmode = TM_TRANSLATE;
169
170 m_root = NULL;
171 m_unmodified = NULL;
172 resetWriteFlags(0);
173 m_extraModifiedFlag = false;
174
175 m_x3dVersion = -1;
176
177 m_unitLength = 1;
178 m_unitAngle = 1;
179
180 SceneProtoMap::createProtoMap(&m_protos, this);
181
182 StringArray *allNodeNames = getAllNodeNames();
183 m_numberBuildinProtos = allNodeNames->size();
184 delete allNodeNames;
185
186 m_root = createNode("Group");
187 m_root->ref();
188 m_rootField = ((NodeGroup *) m_root)->children_Field();
189 m_running = false;
190 m_recording = false;
191
192 m_setViewpoint = false;
193
194 m_defaultViewpoint = NULL;
195 m_currentViewpoint = NULL;
196 updateViewpoint();
197
198 m_setNavigationInfo = false;
199 m_defaultNavigationInfo = (NodeNavigationInfo *)
200 createNode("NavigationInfo");
201 m_defaultNavigationInfo->ref();
202
203 m_currentNavigationInfo = m_defaultNavigationInfo;
204 m_currentNavigationInfo->ref();
205
206 m_currentFog = NULL;
207 m_currentBackground = NULL;
208
209 m_numProtoNames = 0;
210 m_numProtoDefinitions = 0;
211
212 m_navigationMouseMode = true;
213 m_navigationInputDeviceMode = true;
214
215 m_routeList.Init();
216
217 m_selectlevel = 1;
218 m_hasFocus = false;
219
220 m_viewOfLastSelection = NULL;
221 m_selection_is_in_scene = false;
222 m_URL = "";
223 m_newURL = "";
224 m_errorLineNumber = -1;
225
226 m_obj3dCursor = gluNewQuadric();
227
228 m_backupCommandList = NULL;
229
230 m_use3dCursor = false;
231
232 m_nodesWithExternProto.append("Contour2D");
233 m_nodesWithExternProto.append("CoordinateDeformer");
234 m_nodesWithExternProto.append("InlineLoadControl");
235 m_nodesWithExternProto.append("LoadSensor");
236
237 m_nodesWithExternProto.append("NurbsCurve");
238 m_nodesWithExternProto.append("NurbsCurve2D");
239 m_nodesWithExternProto.append("NurbsGroup");
240 m_nodesWithExternProto.append("NurbsPositionInterpolator");
241 m_nodesWithExternProto.append("NurbsSurface");
242 m_nodesWithExternProto.append("NurbsTextureSurface");
243 m_nodesWithExternProto.append("TrimmedSurface");
244
245 m_nodesWithExternProto.append("Arc2D");
246 m_nodesWithExternProto.append("ArcClose2D");
247 m_nodesWithExternProto.append("BooleanFilter");
248 m_nodesWithExternProto.append("BooleanSequencer");
249 m_nodesWithExternProto.append("BooleanToggle");
250 m_nodesWithExternProto.append("BooleanTrigger");
251 m_nodesWithExternProto.append("Circle2D");
252 m_nodesWithExternProto.append("ColorRGBA");
253 m_nodesWithExternProto.append("CoordinateInterpolator2D");
254 m_nodesWithExternProto.append("Disk2D");
255 m_nodesWithExternProto.append("FillProperties");
256 m_nodesWithExternProto.append("IntegerSequencer");
257 m_nodesWithExternProto.append("IntegerTrigger");
258 m_nodesWithExternProto.append("KeySensor");
259 m_nodesWithExternProto.append("LineProperties");
260 m_nodesWithExternProto.append("Metadata");
261 m_nodesWithExternProto.append("MetadataBoolean");
262 m_nodesWithExternProto.append("MetadataDouble");
263 m_nodesWithExternProto.append("MetadataFloat");
264 m_nodesWithExternProto.append("MetadataInteger");
265 m_nodesWithExternProto.append("MetadataSet");
266 m_nodesWithExternProto.append("MetadataString");
267 m_nodesWithExternProto.append("MultiTexture");
268 m_nodesWithExternProto.append("Polyline2D");
269 m_nodesWithExternProto.append("Polypoint2D");
270 m_nodesWithExternProto.append("PositionInterpolator2D");
271 m_nodesWithExternProto.append("Rectangle2D");
272 m_nodesWithExternProto.append("StringSensor");
273 m_nodesWithExternProto.append("TimeTrigger");
274 m_nodesWithExternProto.append("TriangleSet2D");
275
276 m_nodesWithExternProto.append("SuperEllipsoid");
277 m_nodesWithExternProto.append("SuperExtrusion");
278 m_nodesWithExternProto.append("SuperShape");
279 m_nodesWithExternProto.append("SuperRevolver");
280
281 m_nodesWithExternProto.append("CattExportRec");
282 m_nodesWithExternProto.append("CattExportSrc");
283
284 m_nodesWithExternProto.append("LdrawDatExport");
285 m_nodesWithExternProto.append("WonderlandImportJava");
286
287 m_nodesWithExternProto.append("VrmlCut");
288 m_nodesForceExternProtoWrite.append("VrmlCut");
289 m_nodesWithExternProto.append("VrmlScene");
290 m_nodesForceExternProtoWrite.append("VrmlScene");
291
292 m_nodesWithExternProto.append("CurveAnimation");
293
294 m_nodesWithExternProto.append("ARSensor");
295 m_nodesWithExternProto.append("COVER");
296 m_nodesWithExternProto.append("CubeTexture");
297 m_nodesWithExternProto.append("JoystickSensor");
298 m_nodesWithExternProto.append("LabView");
299 m_nodesWithExternProto.append("SpaceSensor");
300 m_nodesWithExternProto.append("Sky");
301 m_nodesWithExternProto.append("SteeringWheel");
302 m_nodesWithExternProto.append("TUIButton");
303 m_nodesWithExternProto.append("TUIComboBox");
304 m_nodesWithExternProto.append("TUIFloatSlider");
305 m_nodesWithExternProto.append("TUIFrame");
306 m_nodesWithExternProto.append("TUILabel");
307 m_nodesWithExternProto.append("TUIListBox");
308 m_nodesWithExternProto.append("TUIMap");
309 m_nodesWithExternProto.append("TUIProgressBar");
310 m_nodesWithExternProto.append("TUISlider");
311 m_nodesWithExternProto.append("TUISplitter");
312 m_nodesWithExternProto.append("TUITab");
313 m_nodesWithExternProto.append("TUITabFolder");
314 m_nodesWithExternProto.append("TUIToggleButton");
315 m_nodesWithExternProto.append("Vehicle");
316 m_nodesWithExternProto.append("VirtualAcoustics");
317 m_nodesWithExternProto.append("VirtualSoundSource");
318 m_nodesWithExternProto.append("Wave");
319
320 m_nodesWithExternProto.append("BlendMode");
321 m_nodesWithExternProto.append("ColorSetInterpolator");
322 m_nodesWithExternProto.append("CubicBezier2DOrientationInterpolator");
323 m_nodesWithExternProto.append("CubicBezierPositionInterpolator");
324 m_nodesWithExternProto.append("GeneratedShadowMap");
325 m_nodesWithExternProto.append("MatrixTransform");
326 m_nodesWithExternProto.append("KambiAppearance");
327 m_nodesWithExternProto.append("KambiHeadLight");
328 m_nodesWithExternProto.append("KambiInline");
329 m_nodesWithExternProto.append("KambiNavigationInfo");
330 m_nodesWithExternProto.append("KambiTriangulation");
331 m_nodesWithExternProto.append("OctreeProperties");
332 m_nodesWithExternProto.append("ProjectedTextureCoordinate");
333 m_nodesWithExternProto.append("RenderedTexture");
334 m_nodesWithExternProto.append("Teapot");
335 m_nodesWithExternProto.append("Text3D");
336 m_nodesWithExternProto.append("KambiTriangulation");
337 m_nodesWithExternProto.append("VectorInterpolator");
338
339 m_externProtoWarning = true;
340 TheApp->readProtoLibrary(this);
341 m_isParsing = false;
342 m_hasJoints = false;
343 m_showJoints = false;
344 m_headlightIsSet = false;
345 m_xrayRendering = false;
346 m_defNode = NULL;
347 buildInteractiveProtos();
348 m_importIntoVrmlScene = false;
349 m_rigidBodyHandleNode = NULL;
350 m_writeKanimNow = false;
351 m_ac3dEmptyMaterial = 0;
352 m_canUpdateViewsSelection = true;
353 m_variableCounter = 0;
354 m_deselect = false;
355 zeroNumDataClasses();
356 zeroNumDataFunctions();
357 m_startNumDataFunctions = 0;
358 m_numDataFunctionsPerClass = 0;
359 m_numDraw = 0;
360 m_lastSelectedHAnimJoint = NULL;
361 m_downloaded = false;
362 m_path = "";
363 m_pathIntern = "";
364 m_firstSelectionRangeHandle = -1;
365 m_saved_vrml = true;
366 m_saved_x3dv = true;
367 m_saved_x3dxml = true;
368 setSelection(getRoot());
369 setViewPorts();
370 m_oldTime = swGetCurrentTime();
371 updateTime();
372 m_viewpointUpdated = false;
373 m_drawViewPorts = true;
374 m_width = 1024;
375 m_height = 768;
376 m_hasParticleSystem = false;
377 m_hasMovieTexture = false;
378 m_infoHandles = false;
379 m_glName = 0;
380 m_vertexModifier = NULL;
381 m_storeAsHtml = false;
382 m_similarNameFlag = true;
383 m_convexHullCounter = 0;
384 }
385
386 void
updateViewpoint(void)387 Scene::updateViewpoint(void)
388 {
389 if (m_defaultViewpoint)
390 m_defaultViewpoint->unref();
391 m_defaultViewpoint = (NodeViewpoint *) createNode("Viewpoint");
392 m_defaultViewpoint->ref();
393
394 if (m_currentViewpoint)
395 m_currentViewpoint->unref();
396 m_currentViewpoint = m_defaultViewpoint;
397 m_currentViewpoint->ref();
398
399 m_viewpointUpdated = true;
400 }
401
~Scene()402 Scene::~Scene()
403 {
404 TheApp->SetIntPreference("TransformMode",m_transformMode->tmode);
405 TheApp->SetIntPreference("TransformDimension",m_transformMode->tdimension);
406 TheApp->SetIntPreference("Transform2Axes",m_transformMode->t2axes);
407
408 TheApp->SetIntPreference("SelectionMode", m_selectionMode);
409 /*
410 while (!m_undoStack.empty()) delete m_undoStack.pop();
411
412 while (!m_redoStack.empty()) delete m_redoStack.pop();
413 */
414
415 m_defaultViewpoint->unref();
416 m_currentViewpoint->unref();
417
418 delete m_selection;
419 m_selection = NULL;
420
421 m_root->unref();
422
423 ProtoMap::Chain::Iterator *j;
424
425 for (int i = 0; i < m_protos.width(); i++) {
426 for (j = m_protos.chain(i).first(); j != NULL; j = j->next()) {
427 delete j->item()->getData();
428 }
429 }
430 for (long i = 0; i < m_fonts.size(); i++) {
431 delete m_fonts[i];
432 }
433 gluDeleteQuadric(m_obj3dCursor);
434 }
435
updateSceneMap(void)436 void Scene::updateSceneMap(void)
437 {
438 SceneProtoMap::updateProtoMap(&m_protos, this);
439 }
440
def(const char * nodeName,Node * value)441 void Scene::def(const char *nodeName, Node *value)
442 {
443 if (value && nodeName && (strlen(nodeName) > 0)) {
444 value->setName(nodeName);
445 m_nodeMap[nodeName] = value;
446 Proto *proto = value->getProto();
447 if (proto && (proto->isDynamicProto()))
448 proto->buildExportNames(nodeName);
449 }
450 }
451
undef(MyString nodeName)452 void Scene::undef(MyString nodeName)
453 {
454 if (nodeName && nodeName.length() > 0) {
455 m_defNode = m_nodeMap[nodeName];
456 if (m_defNode && m_defNode->getRefs() > 1)
457 m_nodeMap.remove(nodeName);
458 }
459 }
460
use(const char * nodeName)461 Node *Scene::use(const char *nodeName)
462 {
463 return m_nodeMap[nodeName];
464 }
465
unuse(const char * nodeName)466 void Scene::unuse(const char *nodeName)
467 {
468 NodeMap::Chain::Iterator *nodeIterator;
469 NodeMap::Chain::Iterator *j;
470 for (int i = 0; i < m_nodeMap.width(); i++) {
471 for (j = m_nodeMap.chain(i).first(); j != NULL; j = j->next())
472 nodeIterator = j;
473 }
474 if (nodeIterator) {
475 Node *node = nodeIterator->item()->getData();
476 if (node->hasParent()) {
477 Node *parent = node->getParent();
478 int parentField = node->getParentField();
479 MFNode *mfnode = (MFNode *)parent->getField(parentField);
480 int index = 0;
481 for (int i = 0; i < mfnode->getSize(); i++) {
482 if (mfnode->getValue(i) == node)
483 index = i;
484 }
485 Node *selection = node->getScene()->getSelection()->getNode();
486 MoveCommand command(node, parent, parentField, NULL, -1, index,
487 true);
488 command.execute();
489 selection->getScene()->UpdateViews(NULL, UPDATE_ALL, NULL);
490 selection->getScene()->setSelection(selection);
491 selection->getScene()->UpdateViews(NULL, UPDATE_SELECTION, NULL);
492 }
493 }
494 }
495
canUse(Node * parentNode,int parentField)496 bool Scene::canUse(Node *parentNode, int parentField)
497 {
498 if (m_defNode == NULL)
499 return false;
500 // avoid to create recursive scenegraphs
501 if (m_defNode == parentNode)
502 return false;
503 return getDestField(m_defNode, parentNode, parentField) >= 0;
504 }
505
use(Node * parentNode,int parentField)506 bool Scene::use(Node *parentNode, int parentField)
507 {
508 // avoid to create recursive scenegraphs
509 Node *testRecursive = parentNode;
510 while (testRecursive->hasParent()) {
511 if (testRecursive == m_defNode)
512 return false;
513 testRecursive = testRecursive->getParent();
514 }
515
516 int destField = getDestField(m_defNode, parentNode, parentField);
517 if (destField >= 0)
518 execute(new MoveCommand(m_defNode, NULL, -1, parentNode, destField));
519
520 return true;
521 }
522
getDestField(Node * src,Node * dest,int destField)523 int Scene::getDestField(Node* src, Node *dest, int destField)
524 {
525 int field = destField;
526 if (field == -1)
527 field = dest->findValidField(src);
528 if (dest->validChildType(field, src->getNodeClass()) ||
529 dest->validChildType(field, src->getType())) {
530 if (src->isInvalidChildNode()) {
531 if (dest->getType() == VRML_NURBS_GROUP)
532 return field;
533 if (dest->getProto()->getField(field)->getNodeType() & CHILD_NODE)
534 return -1;
535 }
536 return field;
537 }
538 return -1;
539 }
540
541 int
addSymbol(MyString s)542 Scene::addSymbol(MyString s)
543 {
544 int &id = m_symbols[s];
545
546 if (id == 0) {
547 id = m_numSymbols++;
548 m_symbolList[id] = s;
549 }
550 return id;
551 }
552
553 const MyString &
getSymbol(int id) const554 Scene::getSymbol(int id) const
555 {
556 return m_symbolList[id];
557 }
558
559 void
setNodes(NodeList * nodes)560 Scene::setNodes(NodeList *nodes)
561 {
562 ((NodeGroup *)m_root)->children(new MFNode(nodes));
563 }
564
searchViewPortOrParticles(Node * node,void * data)565 static bool searchViewPortOrParticles(Node *node, void *data)
566 {
567 Scene *scene = (Scene *)data;
568 if (node->getType() == X3D_VIEWPORT) {
569 scene->addViewPort(node);
570 } else if (node->getType() == X3D_LAYOUT_GROUP) {
571 scene->addViewPort(node);
572 } else if (node->getType() == X3D_LAYOUT_LAYER) {
573 scene->addViewPort(node);
574 } else if (node->getType() == X3D_PARTICLE_SYSTEM) {
575 scene->setParticleSystem(true);
576 }
577 return true;
578 }
579
searchMovieTexture(Node * node,void * data)580 static bool searchMovieTexture(Node *node, void *data)
581 {
582 Scene *scene = (Scene *)data;
583 if (node->getType() == VRML_MOVIE_TEXTURE) {
584 scene->setMovieTexture(true);
585 }
586 return true;
587 }
588
589 void
setViewPorts(void)590 Scene::setViewPorts(void)
591 {
592 m_viewports.resize(0);
593 m_hasParticleSystem = false;
594 m_hasMovieTexture = false;
595 m_root->doWithBranch(searchViewPortOrParticles, this);
596 m_root->doWithBranch(searchMovieTexture, this);
597 }
598
599 void
addNodes(Node * targetNode,int targetField,NodeList * nodes,int scanFor)600 Scene::addNodes(Node *targetNode, int targetField, NodeList *nodes, int scanFor)
601 {
602 if (targetNode == NULL)
603 m_root->addFieldNodeList(m_rootField, nodes);
604 else if (targetField == -1)
605 targetNode->addFieldNodeList(m_rootField, nodes);
606 else if (targetNode->getField(targetField) &&
607 targetNode->getField(targetField)->getType() == MFNODE) {
608 targetNode->setField(targetField, new MFNode(nodes));
609 } else if (targetNode->getField(targetField) &&
610 targetNode->getField(targetField)->getType() == SFNODE) {
611 SFNode *oldSFNode = (SFNode *)targetNode->getField(targetField);
612 MoveCommand *removeCommand = new MoveCommand(oldSFNode->getValue(),
613 targetNode, targetField,
614 NULL, -1);
615 removeCommand->execute();
616 if (nodes->size() > 0) {
617 Node *lastNode = nodes->get(nodes->size() - 1);
618 MoveCommand *addCommand = new MoveCommand(lastNode, NULL, -1,
619 targetNode, targetField);
620 addCommand->execute();
621 }
622 } else if (targetNode->getField(targetField)) {
623 // wrong targetField
624 assert(0);
625 }
626 if ((scanFor == SCAN_FOR_BOTH) || (scanFor == SCAN_FOR_EXTERN_PROTO))
627 scanForExternProtos(nodes);
628 if ((scanFor == SCAN_FOR_BOTH) || (scanFor == SCAN_FOR_INLINE))
629 scanForInlines(nodes);
630 scanForMultimedia(nodes);
631 nodes->clearFlag(NODE_FLAG_TOUCHED);
632 for (long i = 0; i < nodes->size(); i++)
633 if (nodes->get(i))
634 nodes->get(i)->doWithBranch(searchViewPortOrParticles, this,
635 false);
636 }
637
loadInline(Node * node,void * data)638 static bool loadInline(Node *node, void *data)
639 {
640 if ((node->getType() == VRML_INLINE) ||
641 (node->getType() == VRML_INLINE_LOAD_CONTROL))
642 if (TheApp->loadNewInline()) {
643 NodeInline *nodeInline =(NodeInline *)node;
644 node->getScene()->readInline(nodeInline);
645 if (node->getLoadedNodes() != NULL)
646 for (long j = 0; j < node->getLoadedNodes()->size(); j++) {
647 Node *inlinedNode = node->getLoadedNodes()->get(j);
648 inlinedNode->doWithBranch(loadInline, NULL);
649 }
650 }
651 return true;
652 }
653
readInlines(Node * node,void * data)654 static bool readInlines(Node *node, void *data)
655 {
656 if ((node->getType() == VRML_INLINE) ||
657 (node->getType() == VRML_INLINE_LOAD_CONTROL))
658 loadInline(node, NULL);
659 return true;
660 }
661
662 void
scanForInlines(NodeList * nodes)663 Scene::scanForInlines(NodeList *nodes)
664 {
665 nodes->doWithBranch(readInlines, NULL, false, true, false, true, false);
666 }
667
loadMultimedia(Node * node,void * data)668 static bool loadMultimedia(Node *node, void *data)
669 {
670 if ((node->getType() == VRML_IMAGE_TEXTURE) ||
671 (node->getType() == VRML_AUDIO_CLIP) ||
672 (node->getType() == VRML_MOVIE_TEXTURE) ||
673 (node->getType() == VRML_GEO_LOD) ||
674 (node->getType() == X3DOM_BINARY_GEOMETRY) ||
675 (node->getType() == X3DOM_EXTERNAL_GEOMETRY) ||
676 (node->getType() == X3DOM_POP_GEOMETRY_LEVEL) ||
677 (node->getType() == X3DOM_MULTI_PART) ||
678 (node->getType() == X3D_IMAGE_TEXTURE_3D) ||
679 (node->getType() == X3D_DIS_ENTITY_TYPE_MAPPING))
680 node->load();
681 return true;
682 }
683
684
685 void
scanForMultimedia(NodeList * nodes)686 Scene::scanForMultimedia(NodeList *nodes)
687 {
688 nodes->doWithBranch(loadMultimedia, NULL, false, true, false, true, false);
689 }
690
691
recreateNodePROTO(Node * node,void * data)692 static bool recreateNodePROTO(Node *node, void *data)
693 {
694 if (node->isPROTO() && (node->getProto()->isLoaded())) {
695 NodePROTO *protoNode = (NodePROTO *)node;
696 if (!(protoNode->isLoaded())) {
697 protoNode->handleIs();
698 protoNode->createPROTO();
699 protoNode->reInit();
700 }
701 }
702 return true;
703 }
704
705 void
scanForExternProtos(NodeList * nodes)706 Scene::scanForExternProtos(NodeList *nodes)
707 {
708 ProtoMap::Chain::Iterator *j;
709 for (int i = 0; i < m_protos.width(); i++) {
710 for (j = m_protos.chain(i).first(); j != NULL; j = j->next()) {
711 Proto *proto = j->item()->getData();
712 if (proto == NULL)
713 continue;
714 if (belongsToNodeWithExternProto(proto->getName(isX3d())))
715 continue;
716 if (proto->isCoverProto() ||
717 proto->isKambiProto() ||
718 proto->isX3domProto())
719 continue;
720 if (proto->isX3dInternalProto())
721 continue;
722 if (proto == NULL)
723 continue;
724 if (proto->isLoaded())
725 continue;
726 if (proto->isLoading())
727 continue;
728 #ifdef NURBS_CURVE_ANIMATION_COMPATIBILTY
729 if (strcmp(proto->getName(true), "NurbsCurveAnimation") == 0) {
730 readExternProto(proto);
731 continue;
732 }
733 #endif
734 if ((proto->getUrls() != NULL) && (!proto->isInternUrl())) {
735 if (!readExternProto(proto)) {
736 MFString *urls = (MFString *)proto->getUrls();
737 MyString files = "";
738 for (int i = 0; i < urls->getSize(); i++) {
739 files += urls->getValue(i);
740 static MyString path = urls->getValue(i);
741 if (Download((const char*)getURL(), &path))
742 break;
743 files += " ";
744 if (i == urls->getSize() -1)
745 TheApp->MessageBox(IDS_EXTERNPROTO_FILE_FAILED,
746 proto->getName(isX3d()), files);
747 }
748 }
749 }
750 }
751 }
752 nodes->doWithBranch(recreateNodePROTO, NULL, false, true, false, true,
753 false);
754 }
755
756 void
addToNodeList(Node * node)757 Scene::addToNodeList(Node *node)
758 {
759 m_nodeList.append(node);
760 }
761
checkNodeType(Node * node,void * data)762 static bool checkNodeType(Node *node, void *data)
763 {
764 int *nodeType = (int *) data;
765 if (node->getType() == *nodeType)
766 node->getScene()->addToNodeList(node);
767 return true;
768 }
769
770 NodeList *
searchNodeType(int nodeType)771 Scene::searchNodeType(int nodeType)
772 {
773 m_nodeList.resize(0);
774 m_root->doWithBranch(checkNodeType, &nodeType);
775 NodeList *nodeList = new NodeList();
776 for (long i = 0; i < m_nodeList.size(); i++)
777 nodeList->append(m_nodeList[i]);
778 // delete returned NodeList after usage
779 return nodeList;
780 }
781
782 void
readInline(NodeInline * node)783 Scene::readInline(NodeInline *node)
784 {
785 if (node->alreadyLoaded()) {
786 return;
787 }
788 MyString oldDir = "";
789 oldDir += TheApp->getImportURL();
790 MFString *urls = node->url();
791 if (urls == NULL)
792 return;
793 for (int j = 0; j < urls->getSize(); j++) {
794 if (urls->getValue(j).length() == 0)
795 continue;
796 URL url(oldDir, urls->getValue(j));
797 MyString path;
798 if (Download(url, &path)) {
799 TheApp->setImportURL(url.GetPath());
800 struct stat fileStat;
801 MyString filename = "";
802 filename += path;
803 if (stat(filename, &fileStat) == 0) {
804 if (S_ISREG(fileStat.st_mode)) {
805 bool oldX3d = isX3d();
806 FILE *file = fopen(filename, "rb");
807 if (file == NULL) {
808 TheApp->MessageBoxPerror(IDS_INLINE_FILE_FAILED,
809 filename);
810 continue;
811 }
812 double oldUnitLength = getUnitLength();
813 pushUnitLength();
814 TheApp->setImportFile(filename);
815 parse(file, node, -1, SCAN_FOR_BOTH);
816 TheApp->setSkipChecks(false);
817 node->setUnitLength(oldUnitLength / getUnitLength());
818 popUnitLength();
819 fclose(file);
820 if (oldX3d && (!isX3d()))
821 setX3d();
822 else if ((!oldX3d) && isX3d())
823 setVrml();
824 break;
825 }
826 }
827 }
828 }
829 TheApp->setImportURL(oldDir);
830 }
831
832 bool
readExternProto(Proto * proto)833 Scene::readExternProto(Proto *proto)
834 {
835 if (proto->isInternUrl())
836 return true;
837 if (proto->isDefined() && proto->isLoaded())
838 return true;
839 MyString oldDir = "";
840 oldDir += TheApp->getImportURL();
841 FILE* file = NULL;
842 bool oldX3d = isX3d();
843 MFString *urls = (MFString *)proto->getUrls();
844 if (urls == NULL)
845 return false;
846 for (int j = 0; j < urls->getSize(); j++) {
847 if (urls->getValue(j).length() == 0)
848 continue;
849 URL url(oldDir, urls->getValue(j));
850 url.TrimTopic();
851 MyString path;
852 if (Download(url, &path)) {
853 struct stat fileStat;
854 const char *filename = path;
855 if (stat(filename, &fileStat) == 0) {
856 if (S_ISREG(fileStat.st_mode)) {
857 file = fopen(filename, "rb");
858 if (file == NULL)
859 continue;
860 Node *oldTargetNode = targetNode;
861 int oldTargetField = targetField;
862 // fake root node, will be ignored later
863 NodeGroup *node = (NodeGroup *)createNode("Group");
864 if (proto->isLoading()) {
865 fclose(file);
866 return true;
867 }
868 proto->setLoading(true);
869 double oldUnitLength = getUnitLength();
870 pushUnitLength();
871 pushUnitAngle();
872 TheApp->setImportURL(oldDir);
873 TheApp->setImportFile(filename);
874 parse(file, node, node->children_Field(),
875 SCAN_FOR_EXTERN_PROTO);
876 proto->setLoaded(true);
877 proto->setUnitLength(oldUnitLength / getUnitLength());
878 proto->setUnitAngle(getUnitAngle());
879 popUnitAngle();
880 popUnitLength();
881 proto->setLoading(false);
882 targetNode = oldTargetNode;
883 targetField = oldTargetField;
884 fclose(file);
885 if (oldX3d && (!isX3d()))
886 setX3d();
887 else if ((!oldX3d) && isX3d())
888 setVrml();
889 updateNodePROTOs(proto);
890 break;
891 }
892 }
893 }
894 }
895 if (file == NULL)
896 return false;
897 return true;
898 }
899
900
getProfileCallback(Node * node,void * data)901 static bool getProfileCallback(Node *node, void *data)
902 {
903 int *currentProfile = (int *)data;
904 if (node->getProfile() > *currentProfile)
905 *currentProfile = node->getProfile();
906 return true;
907 }
908
909
910 int
writeRouteStrings(int filedes,int indent,bool end)911 Scene::writeRouteStrings(int filedes, int indent, bool end)
912 {
913 static bool alreadyIn = false;
914 // avoid recursive call of writeRouteStrings via Node::write
915 if (alreadyIn)
916 return 0;
917 alreadyIn = true;
918 // write tempory nodes first
919 for (long i = 0; i < m_delayedWriteNodes.size(); i++) {
920 int ret = 0;
921 if (isX3dXml())
922 ret = m_delayedWriteNodes[i]->writeXml(filedes, indent);
923 else
924 ret = m_delayedWriteNodes[i]->write(filedes, indent);
925 if (ret < 0) {
926 alreadyIn = false;
927 return ret;
928 }
929 removeNode(m_delayedWriteNodes[i]);
930 }
931 if (m_delayedWriteNodes.size() > 0)
932 m_delayedWriteNodes.resize(0);
933 alreadyIn = false;
934
935 // sort out multiple ROUTEs
936 if (m_routeList.size() != 0)
937 for (List<MyString>::Iterator* routepointer = m_routeList.first();
938 routepointer != NULL; routepointer = routepointer->next() )
939 for (List<MyString>::Iterator* routepointer2 = m_routeList.first();
940 routepointer2 != NULL; routepointer2 = routepointer2->next() )
941 if (routepointer2 != routepointer)
942 if (strcmp((const char*) routepointer->item(),
943 (const char*) routepointer2->item()) == 0)
944 m_routeList.remove(routepointer2);
945
946 if (m_routeList.size() != 0) {
947 for (List<MyString>::Iterator* routepointer = m_routeList.first();
948 routepointer != NULL; routepointer = routepointer->next() )
949 {
950 RET_ONERROR( indentf(filedes, indent) )
951 RET_ONERROR( mywritestr(filedes, (const char*) routepointer->item()) )
952 RET_ONERROR( mywritestr(filedes, "\n") )
953 TheApp->incSelectionLinenumber();
954 }
955 RET_ONERROR( mywritestr(filedes, "\n") )
956 TheApp->incSelectionLinenumber();
957 m_routeList.removeAll();
958 }
959
960 // sort out multiple ROUTEs
961 if (end && m_endRouteList.size() != 0)
962 for (List<MyString>::Iterator* routepointer = m_endRouteList.first();
963 routepointer != NULL; routepointer = routepointer->next() )
964 for (List<MyString>::Iterator* routepointer2 = m_endRouteList.first();
965 routepointer2 != NULL; routepointer2 = routepointer2->next() )
966 if (routepointer2 != routepointer)
967 if (strcmp((const char*) routepointer->item(),
968 (const char*) routepointer2->item()) == 0)
969 m_endRouteList.remove(routepointer2);
970
971 if (end && m_endRouteList.size() != 0) {
972 for (List<MyString>::Iterator* routepointer = m_endRouteList.first();
973 routepointer != NULL; routepointer = routepointer->next() )
974 {
975 RET_ONERROR( indentf(filedes, indent) )
976 RET_ONERROR( mywritestr(filedes, (const char*) routepointer->item()) )
977 RET_ONERROR( mywritestr(filedes, "\n") )
978 TheApp->incSelectionLinenumber();
979 }
980 RET_ONERROR( mywritestr(filedes, "\n") )
981 TheApp->incSelectionLinenumber();
982 m_endRouteList.removeAll();
983 }
984 return 0;
985 }
986
writeExternProto(int f,const char * protoName)987 int Scene::writeExternProto(int f, const char* protoName)
988 {
989 // search if EXTERNPROTO already exist
990 bool foundProto = false;
991 for (int i = 0; i < m_numProtoNames; i++)
992 if (strcmp((const char*)m_protoNames[i], protoName)==0) {
993 foundProto = true;
994 // force writing of some nodes despite EXTERNPROTO already exist
995 for (long j = 0; j < m_nodesForceExternProtoWrite.size(); j++)
996 if (strcmp(m_nodesForceExternProtoWrite[j], protoName) == 0)
997 foundProto = false;
998 }
999
1000 if (!foundProto) {
1001 // write EXTERNPROTO
1002 const NodeList *nodes = getNodes();
1003 for (long i = 0; i < nodes->size(); i++) {
1004 Node *node = nodes->get(i);
1005 if (node->isInScene(this)) {
1006 const char *nodeName = node->getProto()->getName(isX3d());
1007 if (strcmp(nodeName, protoName)==0) {
1008 RET_ONERROR( node->writeProto(f) )
1009 RET_ONERROR( mywritestr(f ,"\n\n") )
1010 TheApp->incSelectionLinenumber(2);
1011 break;
1012 }
1013 }
1014 }
1015 }
1016 return 0;
1017 }
1018
1019
avoidProtoOnPureVrml(MyString name)1020 static bool avoidProtoOnPureVrml(MyString name)
1021 {
1022 if (strcmp(name, "SuperEllipsoid") == 0)
1023 return true;
1024 if (strcmp(name, "SuperExtrusion") == 0)
1025 return true;
1026 if (strcmp(name, "SuperRevolver") == 0)
1027 return true;
1028 if (strcmp(name, "SuperShape") == 0)
1029 return true;
1030 if (strcmp(name, "CurveAnimation") == 0)
1031 return true;
1032 if (strcmp(name, "NurbsCurve") == 0)
1033 return true;
1034 if (strcmp(name, "NurbsCurve2D") == 0)
1035 return true;
1036 if (strcmp(name, "NurbsGroup") == 0)
1037 return true;
1038 if (strcmp(name, "NurbsOrientationInterpolator") == 0)
1039 return true;
1040 if (strcmp(name, "NurbsPositionInterpolator") == 0)
1041 return true;
1042 if (strcmp(name, "NurbsSet") == 0)
1043 return true;
1044 if (strcmp(name, "NurbsSurface") == 0)
1045 return true;
1046 if (strcmp(name, "NurbsSurfaceInterpolator") == 0)
1047 return true;
1048 if (strcmp(name, "NurbsSweptSurface") == 0)
1049 return true;
1050 if (strcmp(name, "NurbsSwungSurface") == 0)
1051 return true;
1052 if (strcmp(name, "NurbsTextureCoordinate") == 0)
1053 return true;
1054 if (strcmp(name, "NurbsTextureSurface") == 0)
1055 return true;
1056 if (strcmp(name, "NurbsTrimmedSurface") == 0)
1057 return true;
1058 if (strcmp(name, "Contour2D") == 0)
1059 return true;
1060 if (strcmp(name, "CoordinateDeformer") == 0)
1061 return true;
1062 if (strcmp(name, "Polyline2D") == 0)
1063 return true;
1064 if (strcmp(name, "TrimmedSurface") == 0)
1065 return true;
1066 if (strcmp(name, "KambiAppearance") == 0)
1067 return true;
1068 if (strcmp(name, "KambiHeadLight") == 0)
1069 return true;
1070 if (strcmp(name, "KambiInline") == 0)
1071 return true;
1072 if (strcmp(name, "KambiNavigationInfo") == 0)
1073 return true;
1074 if (strcmp(name, "KambiOctreeProperties") == 0)
1075 return true;
1076 if (strcmp(name, "KambiTriangulation") == 0)
1077 return true;
1078 if (strcmp(name, "Text3D") == 0)
1079 return true;
1080
1081 return false;
1082 }
1083
avoidProtoOnX3dom(MyString name)1084 static bool avoidProtoOnX3dom(MyString name)
1085 {
1086 return avoidProtoOnPureVrml(name);
1087 }
1088
avoidProtoOnX3d(MyString name)1089 static bool avoidProtoOnX3d(MyString name)
1090 {
1091 if (strcmp(name, "NurbsCurve") == 0)
1092 return true;
1093 if (strcmp(name, "NurbsCurve2D") == 0)
1094 return true;
1095 if (strcmp(name, "NurbsGroup") == 0)
1096 return true;
1097 if (strcmp(name, "NurbsOrientationInterpolator") == 0)
1098 return true;
1099 if (strcmp(name, "NurbsPositionInterpolator") == 0)
1100 return true;
1101 if (strcmp(name, "NurbsSet") == 0)
1102 return true;
1103 if (strcmp(name, "NurbsSurface") == 0)
1104 return true;
1105 if (strcmp(name, "NurbsSurfaceInterpolator") == 0)
1106 return true;
1107 if (strcmp(name, "NurbsTextureSurface") == 0)
1108 return true;
1109 if (strcmp(name, "NurbsSweptSurface") == 0)
1110 return true;
1111 if (strcmp(name, "NurbsSwungSurface") == 0)
1112 return true;
1113 if (strcmp(name, "MultiTexture") == 0)
1114 return true;
1115 if (strcmp(name, "MultiTextureCoordinate") == 0)
1116 return true;
1117 if (strcmp(name, "MultiTextureTransform") == 0)
1118 return true;
1119 if (strcmp(name, "Contour2D") == 0)
1120 return true;
1121 if (strcmp(name, "LoadSensor") == 0)
1122 return true;
1123 if (strcmp(name, "Arc2D") == 0)
1124 return true;
1125 if (strcmp(name, "ArcClose2D") == 0)
1126 return true;
1127 if (strcmp(name, "BooleanFilter") == 0)
1128 return true;
1129 if (strcmp(name, "BooleanToggle") == 0)
1130 return true;
1131 if (strcmp(name, "BooleanTrigger") == 0)
1132 return true;
1133 if (strcmp(name, "Circle2D") == 0)
1134 return true;
1135 if (strcmp(name, "ColorRGBA") == 0)
1136 return true;
1137 if (strcmp(name, "ContourPolyline2D") == 0)
1138 return true;
1139 if (strcmp(name, "CoordinateInterpolator2D") == 0)
1140 return true;
1141 if (strcmp(name, "Disk2D") == 0)
1142 return true;
1143 if (strcmp(name, "FillProperties") == 0)
1144 return true;
1145 if (strcmp(name, "IntegerSequencer") == 0)
1146 return true;
1147 if (strcmp(name, "IntegerTrigger") == 0)
1148 return true;
1149 if (strcmp(name, "KeySensor") == 0)
1150 return true;
1151 if (strcmp(name, "LineProperties") == 0)
1152 return true;
1153 if (strcmp(name, "Polypoint2D") == 0)
1154 return true;
1155 if (strcmp(name, "Polyline2D") == 0)
1156 return true;
1157 if (strcmp(name, "PositionInterpolator2D") == 0)
1158 return true;
1159 if (strcmp(name, "Rectangle2D") == 0)
1160 return true;
1161 if (strcmp(name, "StringSensor") == 0)
1162 return true;
1163 if (strcmp(name, "TimeTrigger") == 0)
1164 return true;
1165 if (strcmp(name, "TriangleSet2D") == 0)
1166 return true;
1167 if (strcmp(name, "InlineLoadControl") == 0)
1168 return true;
1169 return false;
1170 }
1171
avoidComponentOnPureX3dv(MyString name)1172 static bool avoidComponentOnPureX3dv(MyString name)
1173 {
1174 if (strcmp(name, "NURBS") == 0)
1175 return true;
1176 return false;
1177 }
1178
getComponents(Node * node,void * data)1179 static bool getComponents(Node *node, void *data)
1180 {
1181 StringMap *components = (StringMap *) data;
1182 if (node->isPROTO())
1183 ((NodePROTO *)node)->getComponentsInBranch(getComponents, data);
1184 else {
1185 int level = node->getComponentLevel();
1186 if (level != -1) {
1187 const char* name = node->getComponentName();
1188 StringMap::Chain::Iterator *j;
1189 bool hasAlreadyName = false;
1190 for (int i = 0; i < components->width(); i++)
1191 for (j = components->chain(i).first(); j != NULL; j = j->next())
1192 if (strcmp(name, j->item()->getKey()) == 0)
1193 hasAlreadyName = true;
1194 bool x3d = node->getScene()->isX3d();
1195 if (node->getScene()->isPureX3dv() &&
1196 avoidComponentOnPureX3dv(node->getProto()->getName(x3d)))
1197 return true;
1198 if (!hasAlreadyName)
1199 (*components)[name] = level;
1200 else if (level > (*components)[name])
1201 (*components)[name] = level;
1202 }
1203 }
1204 return true;
1205 }
1206
1207 int
writeComponents(int f)1208 Scene::writeComponents(int f)
1209 {
1210 StringMap components;
1211 m_root->doWithBranch(getComponents, &components);
1212
1213 if (components.width() == 0)
1214 return 0;
1215
1216 StringMap::Chain::Iterator *j;
1217 for (int i = 0; i < components.width(); i++)
1218 for (j = components.chain(i).first(); j != NULL; j = j->next())
1219 if (j->item()->getData() != -1) {
1220 if (isX3dv())
1221 RET_ONERROR( mywritestr(f, "COMPONENT ") )
1222 else if (isX3dXml()) {
1223 RET_ONERROR( indentf(f, TheApp->GetIndent()) )
1224 RET_ONERROR( mywritestr(f, "<component name='") )
1225 }
1226 RET_ONERROR( mywritestr(f, (const char *) j->item()->getKey()) )
1227 if (isX3dv())
1228 RET_ONERROR( mywritestr(f, ":") )
1229 else if (isX3dXml())
1230 RET_ONERROR( mywritestr(f, "' level='") )
1231 RET_ONERROR( mywritef(f, "%d", j->item()->getData()) )
1232 if (isX3dXml())
1233 RET_ONERROR( mywritestr(f, "'/>") )
1234 RET_ONERROR( mywritestr(f, "\n") )
1235 TheApp->incSelectionLinenumber();
1236 }
1237
1238 return 0;
1239 }
1240
1241 #define RET_RESET_FLAGS_ONERROR(x) RET_AND_RESET_ONERROR(x, \
1242 { \
1243 TheApp->disableEFloatWriteFormat(m_writeFlags); \
1244 if (m_writeFlags & TEMP_EXPORT) \
1245 m_writeFlags = oldWriteFlags; \
1246 })
1247
1248
getVariableNames(Node * node,void * data)1249 static bool getVariableNames(Node *node, void *data)
1250 {
1251 if (node != NULL) {
1252 node->getVariableName();
1253 if (node->isPROTO()) {
1254 NodePROTO *protoNode = (NodePROTO *)node;
1255 for (int i = 0; i < protoNode->getNumProtoNodes(); i++)
1256 protoNode->getProtoNode(i)->doWithBranch(getVariableNames,
1257 data);
1258 }
1259 }
1260 return true;
1261 }
1262
generateConvertedNodes(Node * node,void * data)1263 static bool generateConvertedNodes(Node *node, void *data)
1264 {
1265 int *writeFlags = (int *)data;
1266 if (node != NULL) {
1267 node->addToConvertedNodes(*writeFlags);
1268 }
1269 return true;
1270 }
1271
convertBackAndDeleteConvertedNodes(Node * node,void * data)1272 static bool convertBackAndDeleteConvertedNodes(Node *node, void *data)
1273 {
1274 Scene *scene = (Scene *)data;
1275 node->deleteConvertedNodes();
1276 if ((node->getType() != VRML_NURBS_GROUP) && !scene->isX3d())
1277 node->convert2Vrml();
1278 return true;
1279 }
1280
markUsedProto(Node * node,void * data)1281 static bool markUsedProto(Node *node, void *data)
1282 {
1283 Scene *scene = (Scene *)data;
1284 if (node == NULL)
1285 return true;
1286 Proto *proto = scene->getProto(node->getProto()->getName(false));
1287 if (proto == NULL)
1288 return true;
1289 proto->setInUse(true);
1290 proto->setIsInScene(true);
1291 if ((node->getType() == VRML_INLINE) ||
1292 (node->getType() == VRML_INLINE_LOAD_CONTROL)) {
1293 NodeList *nodelist = node->getLoadedNodes();
1294 if (nodelist != NULL)
1295 for (long i = 0; i < nodelist->size(); i++)
1296 nodelist->get(i)->doWithBranch(markUsedProto, data);
1297 }
1298
1299 return true;
1300 }
1301
1302 static NodeVrmlCut *vrmlCut = NULL;
1303
searchVrmlCut(Node * node,void * data)1304 static bool searchVrmlCut(Node *node, void *data)
1305 {
1306 if (node == NULL)
1307 return true;
1308 if (node->getType() == DUNE_VRML_CUT)
1309 vrmlCut = (NodeVrmlCut *)node;
1310
1311 return true;
1312 }
1313
1314 static NodeVrmlScene *vrmlScene = NULL;
1315
searchVrmlScene(Node * node,void * data)1316 static bool searchVrmlScene(Node *node, void *data)
1317 {
1318 if (node == NULL)
1319 return true;
1320 if (node->getType() == DUNE_VRML_SCENE) {
1321 vrmlScene = (NodeVrmlScene *)node;;
1322 return false;
1323 }
1324 return true;
1325 }
1326
write(int f,const char * url,int writeFlags,char * wrlFile)1327 int Scene::write(int f, const char *url, int writeFlags, char *wrlFile)
1328 {
1329 if (!(writeFlags & SKIP_SAVED_TEST)) {
1330 if (writeFlags & X3DV)
1331 if (m_saved_x3dv == true)
1332 return 0;
1333 if (writeFlags & X3D_XML)
1334 if (m_saved_x3dxml == true)
1335 return 0;
1336 }
1337
1338 if (getStoreAsHtml())
1339 writeFlags |= (X3DOM | X3D_XML);
1340
1341 TheApp->setWriteUrl(url);
1342 ProtoMap::Chain::Iterator *j;
1343 for (int i = 0; i < m_protos.width(); i++)
1344 for (j = m_protos.chain(i).first(); j != NULL; j = j->next())
1345 if (j->item()->getData() != NULL)
1346 j->item()->getData()->setInUse(false);
1347 m_root->doWithBranch(markUsedProto, this);
1348
1349 int oldWriteFlags = m_writeFlags;
1350 m_writeFlags = writeFlags;
1351 bool done = false;
1352 int ret = 0;
1353 bool x3dv = ::isX3dv(writeFlags);
1354 // if (writeFlags & (TRIANGULATE | (C_SOURCE | CC_SOURCE | JAVA_SOURCE))) {
1355 if (writeFlags & (TRIANGULATE | (C_SOURCE | CC_SOURCE))) {
1356 m_root->doWithBranch(generateConvertedNodes, &writeFlags);
1357 }
1358 if (writeFlags & (C_SOURCE | CC_SOURCE | JAVA_SOURCE))
1359 if (isX3d())
1360 x3dv = true;
1361 writeFlags = writeFlags & (~(TRIANGULATE));
1362 bool oldXml = isX3dXml();
1363 if (x3dv)
1364 setX3dv();
1365 else if (::isX3dXml(writeFlags))
1366 setX3dXml();
1367 else
1368 setVrml();
1369 /*
1370 if (writeFlags & (C_SOURCE | CC_SOURCE | JAVA_SOURCE)) {
1371 m_root->doWithBranch(getVariableNames, &writeFlags);
1372 }
1373 */
1374 if (writeFlags & OFF) {
1375 ret = writeOff(f);
1376 done = true;
1377 } else if (writeFlags & AC3D) {
1378 ret = writeAc3d(f, writeFlags & AC3D_4_RAVEN);
1379 done = true;
1380 } else if (writeFlags & RIB) {
1381 ret = writeRib(f, url);
1382 done = true;
1383 } else if (writeFlags & POVRAY) {
1384 ret = writePovray(f, url);
1385 done = true;
1386 } else if (writeFlags & KANIM) {
1387 ret = writeKanim(f, url);
1388 done = true;
1389 } else if (writeFlags & LDRAW_DAT) {
1390 ret = writeLdrawDat(f, url);
1391 done = true;
1392 } else if (writeFlags & C_SOURCE) {
1393 ret = writeC(f, writeFlags);
1394 done = true;
1395 } else if (writeFlags & CC_SOURCE) {
1396 ret = writeC(f, writeFlags);
1397 done = true;
1398 } else if (writeFlags & JAVA_SOURCE) {
1399 ret = writeC(f, writeFlags);
1400 done = true;
1401 }
1402 if (done) {
1403 m_writeFlags = oldWriteFlags;
1404 m_root->doWithBranch(convertBackAndDeleteConvertedNodes, this);
1405 return ret;
1406 }
1407 TheApp->disableEFloatWriteFormat(writeFlags);
1408 m_newURL = url;
1409
1410 bool convertFromXml = false;
1411 if (oldXml && !::isX3dXml(writeFlags))
1412 convertFromXml=true;
1413 bool convertToXml = false;
1414 if (!oldXml && ::isX3dXml(writeFlags))
1415 convertToXml=true;
1416 m_writeFlags = writeFlags;
1417 if (convertToXml)
1418 m_writeFlags |= CONVERT_TO_XML;
1419 if (convertFromXml)
1420 m_writeFlags |= CONVERT_FROM_XML;
1421
1422 getNodes()->clearFlag(NODE_FLAG_DEFED);
1423 getNodes()->clearFlag(NODE_FLAG_TOUCHED);
1424
1425 // remove multiple identical ProtoDefinitions smuggled in by Inline nodes
1426 for (int i = 0;i < m_numProtoDefinitions;i++) {
1427 for (int j = 0;j < m_numProtoDefinitions;j++)
1428 if (i != j)
1429 if (strcmp((const char*)m_protoDefinitions[i],
1430 (const char*)m_protoDefinitions[j]) == 0)
1431 m_protoDefinitions[j] = "";
1432 }
1433
1434 int indent = 0;
1435 if (writeFlags & X3DOM) {
1436 RET_RESET_FLAGS_ONERROR( mywritestr(f,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n") )
1437 RET_RESET_FLAGS_ONERROR( mywritestr(f," \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n") )
1438 RET_RESET_FLAGS_ONERROR( mywritestr(f,"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n") )
1439 RET_RESET_FLAGS_ONERROR( mywritestr(f," <head>\n") )
1440 RET_RESET_FLAGS_ONERROR( mywritestr(f," <title></title>\n") )
1441 RET_RESET_FLAGS_ONERROR( mywritef(f,
1442 " <link rel=\"stylesheet\" type=\"text/css\" href=\"%sx3dom.css\" />\n",
1443 TheApp->GetX3domPath()) )
1444 RET_RESET_FLAGS_ONERROR( mywritef(f,
1445 " <script type=\"text/javascript\" src=\"%sx3dom-full.js\"></script>\n",
1446 TheApp->GetX3domPath()) )
1447 RET_RESET_FLAGS_ONERROR( writeHead(f, writeFlags) )
1448 RET_RESET_FLAGS_ONERROR( mywritestr(f," </head>\n") )
1449 RET_RESET_FLAGS_ONERROR( mywritestr(f," <body>\n") )
1450 vrmlCut = NULL;
1451 getRoot()->doWithBranch(searchVrmlCut, NULL, false);
1452 if (vrmlCut)
1453 RET_ONERROR( vrmlCut->writeX3domScript(f, 4) )
1454 for (int i = 0; i < m_htmlFirstPart.size(); i++)
1455 if (m_htmlFirstPart[i]) {
1456 RET_RESET_FLAGS_ONERROR( mywritef(f,"%s",
1457 (const char *)m_htmlBegin[i])
1458 )
1459 RET_RESET_FLAGS_ONERROR( mywritef(f,"%s",
1460 (const char *)m_htmlData[i]) )
1461 RET_RESET_FLAGS_ONERROR( mywritef(f,"%s\n",
1462 (const char *)m_htmlEnd[i]) )
1463 }
1464 RET_RESET_FLAGS_ONERROR( mywritef(f," <x3d %s>\n",
1465 TheApp->GetX3domParameter()) )
1466 RET_RESET_FLAGS_ONERROR( mywritestr(f ," <Scene>\n") )
1467 indent = 2 * TheApp->GetIndent();
1468 } else if (writeFlags & XITE) {
1469 RET_RESET_FLAGS_ONERROR( mywritestr(f,"<!DOCTYPE html>\n") )
1470 RET_RESET_FLAGS_ONERROR( mywritestr(f,"<html>\n") )
1471 RET_RESET_FLAGS_ONERROR( mywritestr(f," <head>\n") )
1472 RET_RESET_FLAGS_ONERROR( mywritestr(f," <title></title>\n") )
1473 RET_RESET_FLAGS_ONERROR( mywritef(f,
1474 " <link rel=\"stylesheet\" type=\"text/css\" href=\"%sx_ite.css\" />\n",
1475 TheApp->GetXitePath()) )
1476 RET_RESET_FLAGS_ONERROR( mywritef(f,
1477 " <script type=\"text/javascript\" src=\"%sx_ite.min.js\"></script>\n",
1478 TheApp->GetXitePath()) )
1479 RET_RESET_FLAGS_ONERROR( mywritestr(f," <style>\n") )
1480 RET_RESET_FLAGS_ONERROR( mywritestr(f,"X3DCanvas {\n") )
1481 RET_RESET_FLAGS_ONERROR( mywritestr(f," width: 100%;\n") )
1482 RET_RESET_FLAGS_ONERROR( mywritestr(f," height: 432px;\n") )
1483 RET_RESET_FLAGS_ONERROR( mywritestr(f,"}\n") )
1484 RET_RESET_FLAGS_ONERROR( mywritestr(f," </style>\n") )
1485 RET_RESET_FLAGS_ONERROR( mywritestr(f," \n") )
1486 RET_RESET_FLAGS_ONERROR( mywritestr(f," </head>\n") )
1487 RET_RESET_FLAGS_ONERROR( mywritestr(f," <body>\n") )
1488 RET_RESET_FLAGS_ONERROR( mywritestr(f," <p margin: 1px 0;>") )
1489 RET_RESET_FLAGS_ONERROR( mywritef(f,"<X3DCanvas url='\"%s\"'/></p>\n",
1490 wrlFile ? wrlFile : url) )
1491 RET_RESET_FLAGS_ONERROR( mywritestr(f," </body>\n") )
1492 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"</html>\n") )
1493 return 0;
1494 } else if (::isX3d(writeFlags)) {
1495 if (::isX3dXml(writeFlags)) {
1496 RET_RESET_FLAGS_ONERROR( mywritestr(f,
1497 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") )
1498 TheApp->incSelectionLinenumber();
1499 RET_RESET_FLAGS_ONERROR( mywritestr(f,"<!DOCTYPE X3D PUBLIC ") )
1500 RET_RESET_FLAGS_ONERROR( mywritestr(f,"\"ISO//Web3D//DTD ") )
1501 RET_RESET_FLAGS_ONERROR( mywritef(f,"X3D 3.%d//EN\" ",
1502 getX3dVersion() ) )
1503 RET_RESET_FLAGS_ONERROR( mywritef(f,
1504 "\"http://www.web3d.org/specifications/x3d-3.%d.dtd\">\n",
1505 getX3dVersion()) )
1506 TheApp->incSelectionLinenumber();
1507 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"<X3D profile='") )
1508 } else {
1509 RET_RESET_FLAGS_ONERROR( mywritef(f ,"#X3D V3.%d utf8\n",
1510 getX3dVersion()) )
1511 TheApp->incSelectionLinenumber();
1512 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"PROFILE ") )
1513 }
1514 int profile = PROFILE_CORE;
1515 getRoot()->doWithBranch(getProfileCallback, &profile);
1516 switch (profile) {
1517 case PROFILE_CORE:
1518 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"Core") )
1519 break;
1520 case PROFILE_INTERCHANGE:
1521 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"Interchange") )
1522 break;
1523 case PROFILE_INTERACTIVE:
1524 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"Interactive") )
1525 break;
1526 case PROFILE_MPEG4_INTERACTIVE:
1527 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"MPEG-4 interactive") )
1528 break;
1529 case PROFILE_IMMERSIVE:
1530 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"Immersive") )
1531 break;
1532 default: // PROFILE_FULL
1533 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"Full") )
1534 break;
1535 }
1536 if (::isX3dXml(writeFlags)) {
1537 RET_RESET_FLAGS_ONERROR( mywritef(f ,"' Version='3.%d>",
1538 getX3dVersion()) )
1539 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"'>") )
1540 }
1541 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"\n") )
1542 TheApp->incSelectionLinenumber();
1543
1544 if (::isX3dXml(writeFlags)) {
1545 RET_ONERROR( mywritestr(f, "<head>\n") )
1546 TheApp->incSelectionLinenumber();
1547 }
1548 RET_RESET_FLAGS_ONERROR( writeComponents(f) )
1549 TheApp->incSelectionLinenumber();
1550 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"\n") )
1551 TheApp->incSelectionLinenumber();
1552
1553 RET_RESET_FLAGS_ONERROR( writeHead(f, writeFlags) )
1554
1555 if (::isX3dXml(writeFlags)) {
1556 RET_ONERROR( mywritestr(f, "</head>\n") )
1557 TheApp->incSelectionLinenumber();
1558 }
1559 } else {
1560 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"#VRML V2.0 utf8\n\n") )
1561 TheApp->incSelectionLinenumber(2);
1562 }
1563 if (isX3dXml()) {
1564 }
1565 if (::isX3dXml(m_writeFlags) && !(writeFlags & X3DOM)) {
1566 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"<Scene>\n") )
1567 TheApp->incSelectionLinenumber();
1568 }
1569 if (writeFlags & (PURE_VRML97 | PURE_X3DV | X3DOM)) {
1570 if (TheApp->getCoverMode())
1571 writeExtensionProtos(f, FF_COVER_ONLY);
1572 if (TheApp->getKambiMode())
1573 writeExtensionProtos(f, FF_KAMBI_ONLY);
1574 }
1575 for (int i = 0;i < m_numProtoNames;i++) {
1576 MyString protoName = m_protoNames[i];
1577 if ((isPureVRML() && avoidProtoOnPureVrml(protoName)) ||
1578 (isX3d() && avoidProtoOnX3d(protoName)) ||
1579 ((writeFlags & X3DOM) && avoidProtoOnX3dom(protoName))) {
1580 if (belongsToNodeWithExternProto(protoName))
1581 continue;
1582 }
1583 bool writeProto = true;
1584 // avoid writing of Protos, which are forced written via ExternProto
1585 for (long j = 0; j < m_nodesForceExternProtoWrite.size(); j++)
1586 if (strcmp(m_nodesForceExternProtoWrite[j], protoName) == 0)
1587 writeProto = false;
1588 if (!writeProto)
1589 continue;
1590
1591 if (TheApp->getPrefix() != NULL) {
1592 MyString prefix = TheApp->getPrefix();
1593 bool isPrefixProto = false;
1594 for (int j = 0; j < m_numProtoNames; j++) {
1595 if (strncmp(m_protoNames[j], prefix, prefix.length()) == 0)
1596 if (strcmp(m_protoNames[j], protoName) == 0)
1597 isPrefixProto = true;
1598 }
1599 if (!isPrefixProto) {
1600 for (int j = 0; j < m_numProtoNames; j++) {
1601 if (strncmp(m_protoNames[j], prefix, prefix.length()) == 0)
1602 m_protoDefinitions[i].gsubOnce(
1603 m_protoNames[j] + prefix.length(),
1604 m_protoNames[j]);
1605 }
1606 }
1607 }
1608 // avoid PROTOs from Proto Library, which are not used
1609 if (m_protos[protoName] != NULL)
1610 if (m_protos[protoName]->fromProtoLibrary() &&
1611 !m_protos[protoName]->isInUse())
1612 continue;
1613 if (m_isNestedProto[i]) {
1614 if (isX3dXml()) {
1615 static char format[256];
1616 swLoadString(IDS_X3D_NESTED_PROTO_NOT_SUPPORTED, format, 255);
1617 errorf(format, (const char *)protoName);
1618 }
1619 RET_RESET_FLAGS_ONERROR( m_protos[protoName]->write(f, 0,
1620 writeFlags) )
1621 // count end of line characters in protodefinitions
1622 const char* string = m_protoDefinitions[i];
1623 while ((string = strchr(string, '\n')) !=NULL) {
1624 TheApp->incSelectionLinenumber();
1625 string++;
1626 }
1627 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"\n\n") )
1628 TheApp->incSelectionLinenumber(2);
1629 } else if (strlen(m_protoNames[i]) > 0) {
1630 RET_RESET_FLAGS_ONERROR( m_protos[protoName]->write(f, indent,
1631 m_writeFlags) )
1632 }
1633 }
1634
1635 for (long k = 0; k < m_nodesWithExternProto.size(); k++) {
1636 // do not write EXTERN PROTOs for some (e.g. Nurbs Nodes) when using
1637 // pureVRML97 cause this nodes are written converted to pure VRML97
1638 bool doWriteExternProto = true;
1639 if (isPureVRML() && avoidProtoOnPureVrml(m_nodesWithExternProto[k]))
1640 doWriteExternProto = false;
1641 if (isX3d() && avoidProtoOnX3d(m_nodesWithExternProto[k]))
1642 doWriteExternProto = false;
1643 if (doWriteExternProto)
1644 RET_RESET_FLAGS_ONERROR(
1645 writeExternProto(f, m_nodesWithExternProto[k])
1646 )
1647 }
1648
1649 vrmlScene = NULL;
1650 getRoot()->doWithBranch(searchVrmlScene, NULL, false);
1651 if (vrmlScene)
1652 vrmlScene->writeProto(f);
1653
1654 getNodes()->clearFlag(NODE_FLAG_TOUCHED);
1655
1656 if (!TheApp->getX3dv() && ::isX3d(m_writeFlags)) {
1657 NodeList *childList = ((NodeGroup *)getRoot())->children()->getValues();
1658 if (childList)
1659 for (long i = 0; i < childList->size(); i++)
1660 childList->get(i)->convert2X3d();
1661 }
1662
1663 NodeList *childList = ((NodeGroup *)getRoot())->children()->getValues();
1664 if (childList)
1665 for (long i = 0; i < childList->size(); i++) {
1666 if (::isX3dXml(m_writeFlags)) {
1667 int rootIndent = indent + TheApp->GetIndent();
1668 RET_RESET_FLAGS_ONERROR( childList->get(i)->
1669 writeXml(f, rootIndent))
1670 } else
1671 RET_RESET_FLAGS_ONERROR( childList->get(i)->write(f, 0) )
1672 }
1673
1674 if ((!isTempSave()) && (!isPureVRML())) {
1675 m_unmodified = m_undoStack.empty() ? (Command *) NULL : m_undoStack.peek();
1676 m_extraModifiedFlag = false;
1677 MyString newURL = "";
1678 newURL += url;
1679 TheApp->setImportURL(newURL);
1680 m_URL = newURL;
1681 }
1682
1683 RET_RESET_FLAGS_ONERROR( writeRouteStrings(f, indent + TheApp->GetIndent(),
1684 true) )
1685
1686 if (::isX3dXml(m_writeFlags)) {
1687 RET_RESET_FLAGS_ONERROR( indentf(f, indent) )
1688 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"</Scene>\n") )
1689 TheApp->incSelectionLinenumber();
1690 RET_RESET_FLAGS_ONERROR( indentf(f, indent) )
1691 if (writeFlags & X3DOM)
1692 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"</x3d>\n") )
1693 else
1694 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"</X3D>\n") )
1695 TheApp->incSelectionLinenumber();
1696 }
1697 if (writeFlags & X3DOM) {
1698 RET_RESET_FLAGS_ONERROR( indentf(f, indent > 0 ? 2 : 0) )
1699 TheApp->incSelectionLinenumber();
1700 for (int i = 0; i < m_htmlFirstPart.size(); i++)
1701 if (!(m_htmlFirstPart[i])) {
1702 RET_RESET_FLAGS_ONERROR( mywritef(f,"%s",
1703 (const char *)m_htmlBegin[i])
1704 )
1705 RET_RESET_FLAGS_ONERROR( mywritef(f,"%s",
1706 (const char *)m_htmlData[i]) )
1707 RET_RESET_FLAGS_ONERROR( mywritef(f,"%s\n",
1708 (const char *)m_htmlEnd[i]) )
1709 TheApp->incSelectionLinenumber();
1710 }
1711 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"</body>\n") )
1712 TheApp->incSelectionLinenumber();
1713 RET_RESET_FLAGS_ONERROR( mywritestr(f ,"</html>\n") )
1714 TheApp->incSelectionLinenumber();
1715 }
1716
1717 if (writeFlags & (PURE_VRML97 | PURE_X3DV | X3DOM))
1718 if (TheApp->getCoverMode())
1719 deleteExtensionProtos();
1720 TheApp->enableEFloatWriteFormat(writeFlags);
1721 if ((oldWriteFlags & (TEMP_EXPORT | TEMP_SAVE)) ||
1722 (writeFlags & (TEMP_EXPORT | TEMP_SAVE))) {
1723 resetWriteFlags(oldWriteFlags);
1724 }
1725
1726 if (writeFlags & X3DV)
1727 m_saved_x3dv = true;
1728 else if (writeFlags & X3D_XML)
1729 m_saved_x3dxml = true;
1730
1731 return 0;
1732 }
1733
writeHead(int f,int writeFlags)1734 int Scene::writeHead(int f, int writeFlags)
1735 {
1736 int oldWriteFlags = m_writeFlags;
1737 long maxMetas = m_metaKeys.size();
1738 if (m_metaValues.size() < maxMetas)
1739 maxMetas = m_metaValues.size();
1740 if (::isX3dXml(writeFlags))
1741 for (long i = 0; i < maxMetas; i++) {
1742 RET_RESET_FLAGS_ONERROR( indentf(f, TheApp->GetIndent()) )
1743 RET_RESET_FLAGS_ONERROR( mywritestr(f , "<meta name='") )
1744 RET_RESET_FLAGS_ONERROR( mywritestr(f , m_metaKeys[i]) )
1745 RET_RESET_FLAGS_ONERROR( mywritestr(f , "' content='") )
1746 RET_RESET_FLAGS_ONERROR( mywritestr(f , m_metaValues[i]) )
1747 RET_RESET_FLAGS_ONERROR( mywritestr(f , "' />\n") )
1748 TheApp->incSelectionLinenumber();
1749 }
1750 else
1751 for (long i = 0; i < maxMetas; i++) {
1752 RET_RESET_FLAGS_ONERROR( mywritestr(f , "META \"") )
1753 RET_RESET_FLAGS_ONERROR( mywritestr(f , m_metaKeys[i]) )
1754 RET_RESET_FLAGS_ONERROR( mywritestr(f , "\" \"") )
1755 RET_RESET_FLAGS_ONERROR( mywritestr(f , m_metaValues[i]) )
1756 RET_RESET_FLAGS_ONERROR( mywritestr(f , "\"\n") )
1757 TheApp->incSelectionLinenumber();
1758 }
1759 if (maxMetas > 0) {
1760 RET_RESET_FLAGS_ONERROR( mywritestr(f , "\n") )
1761 TheApp->incSelectionLinenumber(2);
1762 }
1763 long maxUnits = m_unitCategory.size();
1764 if (m_unitName.size() < maxUnits)
1765 maxUnits = m_unitName.size();
1766 if (m_unitConversionFactor.size() < maxUnits)
1767 maxUnits = m_unitConversionFactor.size();
1768 if (::isX3dXml(writeFlags))
1769 for (long i = 0; i < maxUnits; i++) {
1770 RET_RESET_FLAGS_ONERROR( indentf(f, TheApp->GetIndent()) )
1771 RET_RESET_FLAGS_ONERROR( mywritestr(f , "<unit category='") )
1772 RET_RESET_FLAGS_ONERROR( mywritestr(f , m_unitCategory[i]) )
1773 RET_RESET_FLAGS_ONERROR( mywritestr(f , "' name='") )
1774 RET_RESET_FLAGS_ONERROR( mywritestr(f , m_unitName[i]) )
1775 RET_RESET_FLAGS_ONERROR( mywritestr(f , "' conversionFactor='") )
1776 if (strcmp(m_unitCategory[i], "length") == 0)
1777 RET_RESET_FLAGS_ONERROR( mywritef(f , "%f", m_unitLength) )
1778 else if (strcmp(m_unitCategory[i], "angle") == 0)
1779 RET_RESET_FLAGS_ONERROR( mywritef(f , "%f", m_unitAngle) )
1780 else
1781 RET_RESET_FLAGS_ONERROR( mywritef(f , "%f",
1782 m_unitConversionFactor[i]) )
1783 RET_RESET_FLAGS_ONERROR( mywritestr(f , "' />\n") )
1784 TheApp->incSelectionLinenumber();
1785 }
1786 else
1787 for (long i = 0; i < maxUnits; i++) {
1788 RET_RESET_FLAGS_ONERROR( mywritestr(f , "UNIT ") )
1789 RET_RESET_FLAGS_ONERROR( mywritestr(f , m_unitCategory[i]) )
1790 RET_RESET_FLAGS_ONERROR( mywritestr(f , " ") )
1791 RET_RESET_FLAGS_ONERROR( mywritestr(f , m_unitName[i]) )
1792 RET_RESET_FLAGS_ONERROR( mywritestr(f , " ") )
1793 if (strcmp(m_unitCategory[i], "length") == 0)
1794 RET_RESET_FLAGS_ONERROR( mywritef(f , "%f", m_unitLength) )
1795 else if (strcmp(m_unitCategory[i], "angle") == 0)
1796 RET_RESET_FLAGS_ONERROR( mywritef(f , "%f", m_unitAngle) )
1797 else
1798 RET_RESET_FLAGS_ONERROR( mywritef(f , "%f",
1799 m_unitConversionFactor[i]) )
1800 RET_RESET_FLAGS_ONERROR( mywritestr(f , "\n") )
1801 TheApp->incSelectionLinenumber();
1802 }
1803 if (maxUnits > 0) {
1804 RET_RESET_FLAGS_ONERROR( mywritestr(f , "\n") )
1805 TheApp->incSelectionLinenumber(2);
1806 }
1807 return 0;
1808 }
1809
1810 bool
belongsToNodeWithExternProto(const char * protoName)1811 Scene::belongsToNodeWithExternProto(const char *protoName)
1812 {
1813 bool found = false;
1814 for (long i = 0; i < m_nodesWithExternProto.size(); i++)
1815 if (strcmp(protoName, m_nodesWithExternProto[i]) == 0) {
1816 found = true;
1817 break;
1818 }
1819 return found;
1820 }
1821
1822 #define KANIM_RET_ONERROR(x) RET_AND_RESET_ONERROR(x, delete [] name;m_writeKanimNow = false)
1823
1824 int
writeKanim(int f,const char * url)1825 Scene::writeKanim(int f, const char *url)
1826 {
1827 m_writeKanimNow = true;
1828 char* name = new char[strlen(url) + 1 + strlen(".wrl") + 1 + LEN_DEZIMAL_INT_MAX + 1];
1829 strcpy(name, url);
1830 char *nameBaseEnd = strrchr(name, '.');
1831 if (nameBaseEnd == NULL)
1832 nameBaseEnd = name + strlen(url);
1833 FloatArray keyTimes;
1834 bool allInterpolatorsLoop = true;
1835 for (long i = 0; i < m_timeSensors.size(); i++) {
1836 NodeTimeSensor *timer = (NodeTimeSensor *)m_timeSensors[i];
1837 if (!timer->loop()->getValue())
1838 allInterpolatorsLoop = false;
1839 int frac = timer->fraction_changed_Field();
1840 float interval = timer->cycleInterval()->getValue();
1841 for (SocketList::Iterator *j = timer->getOutput(frac).first();
1842 j != NULL; j = j->next()) {
1843 Interpolator *interpolator = (Interpolator *)(j->item().getNode());
1844 MFFloat *keys = interpolator->key();
1845 for (int k = 0; k < keys->getSize(); k++) {
1846 float time = keys->getValue(k) * interval;
1847 if (keyTimes.size() == 0)
1848 keyTimes.append(time);
1849 else if (time > keyTimes[keyTimes.size() - 1])
1850 keyTimes.append(time);
1851 else for (long l = 0 ; l < keyTimes.size(); l++) {
1852 if (time == keyTimes[l])
1853 break;
1854 if (time < keyTimes[l]) {
1855 keyTimes.insert(time, l);
1856 break;
1857 }
1858 }
1859 }
1860 }
1861 }
1862 KANIM_RET_ONERROR( mywritestr(f ,"<?xml version=\"1.0\"?>\n") )
1863 KANIM_RET_ONERROR( mywritestr(f ,"<animation ") )
1864 if (allInterpolatorsLoop)
1865 KANIM_RET_ONERROR( mywritestr(f ,"loop=\"true\"") )
1866 else
1867 KANIM_RET_ONERROR( mywritestr(f ,"loop=\"false\"") )
1868 KANIM_RET_ONERROR( mywritestr(f ,">\n") )
1869 double t = swGetCurrentTime();
1870 m_timeStart = t;
1871 for (long i = 0; i < m_timeSensors.size(); i++)
1872 ((NodeTimeSensor *) m_timeSensors[i])->start(t);
1873 for (long i = 0; i < keyTimes.size(); i++) {
1874 updateTimeAt(t + keyTimes[i]);
1875 #ifdef WIN32
1876 sprintf(nameBaseEnd, "_%zu.wrl", i);
1877 #else
1878 sprintf(nameBaseEnd, "_%lu.wrl", i);
1879 #endif
1880 int filedes = open(name, O_WRONLY | O_CREAT,00666);
1881 if (filedes == -1) {
1882 delete [] name;
1883 m_writeKanimNow = false;
1884 return -1;
1885 }
1886 KANIM_RET_ONERROR( write(filedes, name, PURE_VRML97) )
1887 if (swTruncateClose(filedes)) {
1888 delete [] name;
1889 m_writeKanimNow = false;
1890 return -1;
1891 }
1892 KANIM_RET_ONERROR( mywritestr(f ," <frame file_name=\"") )
1893 URL fileUrl(name);
1894 MyString filename = fileUrl.GetFileName();
1895 if (filename.length() == 0)
1896 filename = name;
1897 KANIM_RET_ONERROR( mywritestr(f, (const char *)filename) )
1898 KANIM_RET_ONERROR( mywritestr(f ,"\" time=\"") )
1899 KANIM_RET_ONERROR( mywritef(f ,"%f", keyTimes[i]) )
1900 KANIM_RET_ONERROR( mywritestr(f ,"\"/>\n") )
1901 }
1902 KANIM_RET_ONERROR( mywritestr(f ,"</animation>\n") )
1903 delete [] name;
1904 if (swTruncateClose(f)) {
1905 m_writeKanimNow = false;
1906 return -1;
1907 }
1908 updateTime();
1909 m_writeKanimNow = false;
1910 return 0;
1911 }
1912
hasEmptyMaterialCallback(Node * node,void * data)1913 static bool hasEmptyMaterialCallback(Node *node, void *data)
1914 {
1915 bool *emptyMaterial = (bool *) data;
1916 if (node->getType() == VRML_SHAPE)
1917 if (((NodeShape *)node)->appearance()->getValue() == NULL)
1918 *emptyMaterial = true;
1919 if (node->getType() == VRML_APPEARANCE)
1920 if (((NodeAppearance *)node)->material()->getValue() == NULL)
1921 *emptyMaterial = true;
1922 return true;
1923 }
1924
hasEmptyMaterial()1925 bool Scene::hasEmptyMaterial()
1926 {
1927 bool emptyMaterial = false;
1928 getRoot()->doWithBranch(hasEmptyMaterialCallback, &emptyMaterial);
1929 return emptyMaterial;
1930 }
1931
1932 void
collectAc3dMaterialInfo(char * name,Node * node)1933 Scene::collectAc3dMaterialInfo(char *name, Node *node)
1934 {
1935 m_ac3dMaterialNameArray.append(name);
1936 m_ac3dMaterialNodeArray.append(node);
1937 int materialIndex = m_ac3dMaterialNodeArray.size() - 1;
1938
1939 StringMap::Chain::Iterator *j;
1940 bool alreadyInMap = false;
1941 for (int i = 0; i < m_ac3dMaterialIndexMap.width(); i++)
1942 for (j = m_ac3dMaterialIndexMap.chain(i).first(); j != NULL; j = j->next())
1943 if (strcmp(name, j->item()->getKey()) == 0)
1944 alreadyInMap = true;
1945 if (alreadyInMap)
1946 TheApp->PrintMessageWindowsString(IDS_AC3D_EXPORT_COLOR_IGNORED, name);
1947 else
1948 m_ac3dMaterialIndexMap[name] = materialIndex;
1949 }
1950
handleMaterial(Scene * scene,char * name,Node * node)1951 static void handleMaterial(Scene *scene, char *name, Node *node)
1952 {
1953 if (name != NULL) {
1954 scene->collectAc3dMaterialInfo(name, node);
1955 //free(name);? later !
1956 }
1957 }
1958
1959 int
writeAc3d(int f,bool raven)1960 Scene::writeAc3d(int f, bool raven)
1961 {
1962 RET_ONERROR( mywritestr(f, "AC3Db\n") )
1963
1964 m_ac3dMaterialNameArray.resize(0);
1965 m_ac3dMaterialNodeArray.resize(0);
1966 m_ac3dMaterialIndexMap.removeAll();
1967
1968 NodeList *childList = ((NodeGroup *)getRoot())->children()->getValues();
1969
1970 for (long i = 0; i < childList->size(); i++)
1971 childList->get(i)->handleAc3dMaterial(handleMaterial ,this);
1972
1973 if (raven) {
1974 int materialIndex = 0;
1975 StringMap::Chain::Iterator *j;
1976 for (int i = 0; i < m_ac3dMaterialIndexMap.width(); i++) {
1977 for (j = m_ac3dMaterialIndexMap.chain(i).first(); j != NULL;
1978 j = j->next()) {
1979 const char *materialName = j->item()->getKey();
1980 Node *materialNode = NULL;
1981 for (long k = 0; k < m_ac3dMaterialNameArray.size(); k++) {
1982 if (strcmp(materialName, m_ac3dMaterialNameArray[k]) == 0) {
1983 materialNode = m_ac3dMaterialNodeArray[k];
1984 materialNode->setAc3dMaterialIndex(materialIndex);
1985 }
1986 }
1987 if (materialNode != NULL) {
1988 materialNode->writeAc3dMaterial(f, 0, materialName);
1989 materialIndex += materialNode->getIncAc3dMaterialIndex();
1990 }
1991 }
1992 }
1993 m_ac3dEmptyMaterial = materialIndex;
1994 } else {
1995 int materialIndex = 0;
1996 for (long i = 0; i < m_ac3dMaterialNameArray.size(); i++) {
1997 const char *materialName = m_ac3dMaterialNameArray[i];
1998 Node *materialNode = m_ac3dMaterialNodeArray[i];
1999 materialNode->setAc3dMaterialIndex(materialIndex);
2000 materialNode->writeAc3dMaterial(f, 0, materialName);
2001 materialIndex += materialNode->getIncAc3dMaterialIndex();
2002 }
2003 m_ac3dEmptyMaterial = materialIndex;
2004 }
2005
2006 // write ac3d equivalent of empty material
2007 RET_ONERROR( mywritestr(f, "MATERIAL \"") )
2008 if (raven)
2009 RET_ONERROR( mywritestr(f, "__") )
2010 RET_ONERROR( mywritestr(f, TheApp->GetDefaultAc3dMaterialName()) )
2011 RET_ONERROR( mywritestr(f, "\" ") )
2012 RET_ONERROR( mywritestr(f, "rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 ") )
2013 RET_ONERROR( mywritestr(f, "spec 0 0 0 shi 2 trans 0\n") )
2014
2015 int kids = 0;
2016 for (long i = 0; i < childList->size(); i++)
2017 if (childList->get(i)->canWriteAc3d())
2018 kids++;
2019 RET_ONERROR( mywritef(f, "OBJECT world\nkids %d\n", kids) )
2020 for (long i = 0; i < childList->size(); i++)
2021 RET_ONERROR( childList->get(i)->writeAc3d(f, 0) )
2022 return(0);
2023 }
2024
getAllNodes(Node * node,void * data)2025 static bool getAllNodes(Node *node, void *data)
2026 {
2027 NodeArray *nodeArray = (NodeArray *) data;
2028 nodeArray->append(node);
2029 return true;
2030 }
2031
2032 struct FaceSetAndNode {
2033 public:
2034 NodeIndexedFaceSet *faceSet;
2035 Node *node;
2036 };
2037
2038 int
writeOff(int f)2039 Scene::writeOff(int f)
2040 {
2041 int sumVerticesPerFace = 0;
2042 int numFaces = 0;
2043 int sumVertices = 0;
2044
2045 Node *selection = getSelection()->getNode();
2046 NodeArray childList;
2047 MyArray<FaceSetAndNode> faces;
2048 getRoot()->doWithBranch(getAllNodes, &childList, false);
2049 for (long i = 0; i < childList.size(); i++) {
2050 Node *node = childList.get(i);
2051 if (node->isMeshBasedNode()) {
2052 MeshBasedNode *mBasedNode = (MeshBasedNode *)node;
2053 NodeIndexedFaceSet *face = (NodeIndexedFaceSet *)
2054 mBasedNode->toIndexedFaceSet();
2055 FaceSetAndNode faceAndNode;
2056 faceAndNode.faceSet = face;
2057 faceAndNode.node = node->getParent();
2058 faces.append(faceAndNode);
2059 face->ref();
2060 face->setFlag(NODE_FLAG_CONVERTED);
2061 MoveCommand *command = new MoveCommand(face, NULL, -1,
2062 getRoot(), getRootField());
2063 command->execute();
2064 face->writeOffInit();
2065 }
2066 }
2067 bool hasColor = false;
2068 for (int i = 0; i < faces.size(); i++) {
2069 NodeIndexedFaceSet *face = faces[i].faceSet;
2070 if (face->colorPerVertex()->getValue())
2071 if (face->color()->getValue())
2072 hasColor = true;
2073 }
2074 if (hasColor)
2075 RET_ONERROR( mywritestr(f, "C") )
2076 RET_ONERROR( mywritestr(f, "OFF\n") )
2077 for (int i = 0; i < faces.size(); i++) {
2078 NodeIndexedFaceSet *face = faces[i].faceSet;
2079 face->accountOffData(f);
2080 sumVerticesPerFace += face->getSumVerticesPerFaces();
2081 sumVertices += face->getSumVertices();
2082 numFaces += face->getMesh()->getNumFaces();
2083 }
2084 mywritef(f, "%d %d %d\n", sumVertices, numFaces, sumVerticesPerFace);
2085 for (int i = 0; i < faces.size(); i++) {
2086 NodeIndexedFaceSet *face = faces[i].faceSet;
2087 face->writeOffVerticesAndColors(f, faces[i].node);
2088 }
2089 int numIndices = 0;
2090 for (int i = 0; i < faces.size(); i++) {
2091 NodeIndexedFaceSet *face = faces[i].faceSet;
2092 face->writeOffIndicesAndColors(f, numIndices, childList.get(i));
2093 numIndices += face->getMesh()->getNumFaces();
2094 }
2095 for (int i = 0; i < faces.size(); i++) {
2096 NodeIndexedFaceSet *face = faces[i].faceSet;
2097 face->writeOffNormals(f, faces[i].node);
2098 }
2099 for (int i = 0; i < faces.size(); i++) {
2100 MoveCommand *command = new MoveCommand(faces[i].faceSet,
2101 getRoot(), getRootField(),
2102 NULL, -1);
2103 command->execute();
2104 }
2105 UpdateViews(NULL, UPDATE_ALL, NULL);
2106 setSelection(selection);
2107 UpdateViews(NULL, UPDATE_SELECTION);
2108 return(0);
2109 }
2110
searchLongestTime(Node * node,void * data)2111 static bool searchLongestTime(Node *node, void *data)
2112 {
2113 double *time = (double *)data;
2114 if (node->getType() == VRML_TIME_SENSOR) {
2115 NodeTimeSensor *sensor = (NodeTimeSensor *)node;
2116 node->getScene()->addTimeSensor(sensor);
2117 if (sensor->cycleInterval()->getValue() > *time)
2118 *time = sensor->cycleInterval()->getValue();
2119 }
2120 if (node->getType() == DUNE_VRML_CUT) {
2121 NodeVrmlCut *cut = (NodeVrmlCut *)node;
2122 float sceneLength = 0;
2123 MFTime *lengths = cut->sceneLengths();
2124 for (int i = 0; i < lengths->getSize(); i++)
2125 sceneLength += lengths->getValue(i);
2126 if (sceneLength > *time)
2127 *time = sceneLength;
2128 }
2129 return true;
2130 }
2131
2132 #define FRAME_RATE 24
2133
2134 int
writeRib(int filedes,const char * file)2135 Scene::writeRib(int filedes, const char *file)
2136 {
2137 const char *url = file;
2138 int f = filedes;
2139
2140 m_ribTexureFiles.removeAll();
2141
2142 double longestTime = 0;
2143 getRoot()->doWithBranch(searchLongestTime, &longestTime);
2144
2145 m_viewpoints.resize(0);
2146
2147 findBindableNodes();
2148
2149 int frames = longestTime * FRAME_RATE;
2150 if (longestTime == 0)
2151 frames = 1;
2152
2153 bool running = isRunning();
2154 start();
2155 m_currentTime = 0;
2156
2157 int framesPerFile = frames / TheApp->getNumExportFiles();
2158 if (framesPerFile == 0) {
2159 fprintf(stderr, "Warning: only %d frames, not all files are written\n",
2160 frames);
2161 framesPerFile = 1;
2162 }
2163
2164 char filename[4096];
2165 snprintf(filename, 4095, "%s", url);
2166 int numFramesPerFile = 0;
2167 int currentfile = 0;
2168 for (int j = 0; j < frames; j++) {
2169 if (((numFramesPerFile >= framesPerFile) && (framesPerFile > 0)) ||
2170 (((currentfile == 0) && (frames > 1)) &&
2171 (TheApp->getNumExportFiles() > 1))) {
2172 URL file(url);
2173 snprintf(filename, 4095, "%s%d.rib",
2174 file.GetFileNameWithoutExtension(), ++currentfile);
2175 if ((TheApp->getNumExportFiles() > 1) ||
2176 ((TheApp->getNumExportFiles() == 1) && (f != 1))) {
2177 swTruncateClose(f);
2178 f = open(filename, O_WRONLY | O_CREAT,00666);
2179 }
2180
2181 RET_ONERROR( mywritestr(f, "##RenderMan RIB-Structure 1.0\n") )
2182 RET_ONERROR( mywritestr(f, "version 3.03\n\n") )
2183 numFramesPerFile = 0;
2184 }
2185 if (frames == 1) {
2186 f = open(file, O_WRONLY | O_CREAT,00666);
2187
2188 RET_ONERROR( mywritestr(f, "##RenderMan RIB-Structure 1.0\n") )
2189 RET_ONERROR( mywritestr(f, "version 3.03\n\n") )
2190 }
2191 RET_ONERROR( writeRibNextFrame(f, file, j) )
2192 numFramesPerFile++;
2193 }
2194
2195 swTruncateClose(f);
2196
2197 if (!running)
2198 stop();
2199 updateTime();
2200
2201 return(0);
2202 }
2203
2204 int
writeRibNextFrame(int f,const char * url,int frame)2205 Scene::writeRibNextFrame(int f, const char *url, int frame)
2206 {
2207 glMatrixMode(GL_MODELVIEW);
2208 glLoadIdentity();
2209
2210 updateTimeAt(m_currentTime);
2211
2212 RET_ONERROR( mywritef(f, "FrameBegin %d\n", frame) )
2213 URL file(url);
2214 RET_ONERROR( mywritef(f, "Display \"%s%06d.tif\" \"file\" \"rgba\"\n",
2215 file.GetFileNameWithoutExtension(), frame + 1) )
2216 // png2yuv begins to count at 1
2217
2218 float fov = 30;
2219 if (m_currentViewpoint)
2220 fov = m_currentViewpoint->fov()->getValue() * 360.0 / (2 * M_PI);
2221
2222 RET_ONERROR( mywritestr(f, "ShadingRate 1\n") )
2223 RET_ONERROR( mywritef(f, "Projection \"perspective\" \"fov\" [%f]\n",
2224 fov) )
2225 RET_ONERROR( mywritestr(f, "Identity\n") )
2226
2227 if (m_currentNavigationInfo &&
2228 m_currentNavigationInfo->headlight()->getValue()) {
2229 RET_ONERROR( mywritestr(f, "LightSource \"distantlight\" 1 ") )
2230 RET_ONERROR( mywritestr(f, "\"intensity\" [1] ") )
2231 RET_ONERROR( mywritestr(f, "\"from\" [200 300 100] ") ) //light 0,0,10?
2232 RET_ONERROR( mywritestr(f, "\"to\" [0 0 0]\n") )
2233 }
2234
2235 RET_ONERROR( mywritef(f, "Rotate 0 0 1 0\n") )
2236 RET_ONERROR( mywritef(f ,"Translate 0 0 0\n") )
2237
2238 RET_ONERROR( mywritef(f, "\n") )
2239
2240 RET_ONERROR( mywritestr(f, "WorldBegin\n\n") )
2241 RET_ONERROR( mywritestr(f, "Identity\n\n") )
2242
2243 NodeList *childList = ((NodeGroup *)getRoot())->children()->getValues();
2244
2245 for (long i = 0; i < childList->size(); i++)
2246 RET_ONERROR( childList->get(i)->writeRib(f, 0) )
2247
2248 RET_ONERROR( mywritestr(f, "WorldEnd\n\n") )
2249
2250 RET_ONERROR( mywritestr(f, "FrameEnd\n") )
2251
2252 m_currentTime = (double)frame / FRAME_RATE;
2253
2254 return(0);
2255 }
2256
2257
2258 int
writePovray(int filedes,const char * file)2259 Scene::writePovray(int filedes, const char *file)
2260 {
2261 const char *url = file;
2262 int f = filedes;
2263
2264 m_povrayTexureFiles.removeAll();
2265
2266 double longestTime = 0;
2267 getRoot()->doWithBranch(searchLongestTime, &longestTime);
2268
2269 m_viewpoints.resize(0);
2270
2271 findBindableNodes();
2272
2273 int frames = longestTime * FRAME_RATE;
2274 if (longestTime == 0)
2275 frames = 1;
2276
2277 bool running = isRunning();
2278 start();
2279 m_currentTime = 0;
2280
2281 int framesPerFile = frames / TheApp->getNumExportFiles();
2282 if (framesPerFile == 0) {
2283 fprintf(stderr, "Warning: only %d frames, not all files are written\n",
2284 frames);
2285 framesPerFile = 1;
2286 }
2287
2288 char filename[4096];
2289 snprintf(filename, 4095, "%s", url);
2290 int numFramesPerFile = 0;
2291 int currentfile = 0;
2292 for (int j = 0; j < frames; j++) {
2293 if (((numFramesPerFile >= framesPerFile) && (framesPerFile > 0)) ||
2294 (((currentfile == 0) && (frames > 1)) &&
2295 (TheApp->getNumExportFiles() > 1))) {
2296 URL file(url);
2297 snprintf(filename, 4095, "%s%d.pov",
2298 file.GetFileNameWithoutExtension(), ++currentfile);
2299 if ((TheApp->getNumExportFiles() > 1) ||
2300 ((TheApp->getNumExportFiles() == 1) && (f != 1))) {
2301 swTruncateClose(f);
2302 f = open(filename, O_WRONLY | O_CREAT,00666);
2303 }
2304 numFramesPerFile = 0;
2305 }
2306 if (numFramesPerFile == 0) {
2307 RET_ONERROR( mywritestr(f, "// Povray output of white_dune\n") )
2308 RET_ONERROR( mywritestr(f, "#version 3.7;\n\n") )
2309 RET_ONERROR( mywritef(f, "// number_of_frames %d\n\n", frames) )
2310 RET_ONERROR( mywritestr(f,
2311 "global_settings { assumed_gamma 1.0}\n\n") )
2312 RET_ONERROR( mywritef(f, "light_source{ <0, 0, -10> %s",
2313 "color rgb<1,1,1> }\n\n") )
2314 }
2315 RET_ONERROR( writePovrayNextFrame(f, file, j) )
2316 numFramesPerFile++;
2317 }
2318
2319 swTruncateClose(f);
2320
2321 if (!running)
2322 stop();
2323 updateTime();
2324
2325 return(0);
2326 }
2327
2328 int
writePovrayNextFrame(int f,const char * url,int frame)2329 Scene::writePovrayNextFrame(int f, const char *url, int frame)
2330 {
2331 RET_ONERROR( mywritef(f, "#if(frame_number=%d)\n", frame) )
2332
2333 m_currentTime = (double)frame / FRAME_RATE;
2334
2335 updateTimeAt(m_currentTime);
2336
2337 NodeList *childList = ((NodeGroup *)getRoot())->children()->getValues();
2338
2339 for (long i = 0; i < childList->size(); i++)
2340 RET_ONERROR( childList->get(i)->writePovray(f, 0) )
2341
2342 RET_ONERROR( mywritef(f, "#end\n") )
2343 return(0);
2344 }
2345
collectCattExportRecNodes(Node * node,void * data)2346 static bool collectCattExportRecNodes(Node *node, void *data)
2347 {
2348 if (node->getType() == DUNE_CATT_EXPORT_REC) {
2349 NodeArray *array = (NodeArray *)data;
2350 array->append(node);
2351 }
2352 return true;
2353 }
2354
2355 int
writeCattGeo(void)2356 Scene::writeCattGeo(void)
2357 {
2358 m_cattGeoFileCounter = 0;
2359 m_cattGeoCornerCounter = 1;
2360 m_cattGeoPlaneCounter = 1;
2361 m_cattRecIsWritten = false;
2362 m_cattSrcIsWritten = false;
2363
2364 MyArray<NodeCattExportRec *> cattExportRecNodes;
2365 getRoot()->doWithBranch(collectCattExportRecNodes, &cattExportRecNodes);
2366
2367 for (long i = 0; i < cattExportRecNodes.size(); i++)
2368 for (long j = 0; j < i; j++)
2369 if (cattExportRecNodes[i]->id()->getValue() ==
2370 cattExportRecNodes[j]->id()->getValue()) {
2371 char message[1024];
2372 mysnprintf(message, 1023, "Warning: id %d is used %s\n",
2373 cattExportRecNodes[i]->id()->getValue(),
2374 "in more than one CattExportRec nodes\n");
2375 if (TheApp->mainWnd() == NULL)
2376 swDebugf(message);
2377 else {
2378 TheApp->MessageBox(message);
2379 setSelection(cattExportRecNodes[j]);
2380 UpdateViews(NULL, UPDATE_SELECTION);
2381 }
2382 break;
2383 }
2384 if (m_root->writeCattGeo(0,0))
2385 return -1;
2386
2387 return(0);
2388 }
2389
2390 bool
validateLdrawExport()2391 Scene::validateLdrawExport()
2392 {
2393 NodeList *list = searchNodeType(DUNE_LDRAW_DAT_EXPORT);
2394 if (list->size() == 0) {
2395 TheApp->MessageBoxId(IDS_LDRAW_DAT_EXPORT_NODE_CREATED, SW_MB_WARNING);
2396 Node *node = createNode("LdrawDatExport");
2397 execute(new MoveCommand(node, NULL, -1, m_root, m_rootField));
2398 UpdateViews(NULL, UPDATE_SELECTION);
2399 return false;
2400 }
2401 if (list->size() > 1) {
2402 TheApp->MessageBoxId(IDS_TO_MUCH_LDRAW_DAT_EXPORT_NODES);
2403 return false;
2404 }
2405 NodeLdrawDatExport *node = (NodeLdrawDatExport *)list->get(0);
2406 return node->validate();
2407 }
2408
2409 int
writeLdrawDat(int filedes,const char * path)2410 Scene::writeLdrawDat(int filedes, const char *path)
2411 {
2412 m_currentLdrawColor = -1;
2413 NodeList *list = searchNodeType(DUNE_LDRAW_DAT_EXPORT);
2414 const char *filename = strrchr(path, swGetPathSeperator());
2415 if (filename == NULL)
2416 filename = path;
2417 else
2418 filename++;
2419 if (list->size() == 1) {
2420 NodeLdrawDatExport *node = (NodeLdrawDatExport *)list->get(0);
2421 if (node->writeLdrawDatHeader(filedes, filename) != 0)
2422 return 0;
2423 };
2424 m_root->writeLdrawDat(filedes, 0);
2425 return 0;
2426 }
2427
writeCDynamicNodeDeclaration(Node * node,void * data)2428 static bool writeCDynamicNodeDeclaration(Node *node, void *data)
2429 {
2430 WriteCDynamicNodeData *parameters = (WriteCDynamicNodeData *)data;
2431 Proto *proto = node->getProto();
2432 if (proto->isDynamicProto())
2433 parameters->result = proto->writeCDeclaration(parameters->filedes,
2434 parameters->languageFlag);
2435 if (parameters->result != 0)
2436 return false;
2437
2438 return true;
2439 }
2440
2441 int
writeCDeclaration(int f,int languageFlag)2442 Scene::writeCDeclaration(int f, int languageFlag)
2443 {
2444 ProtoMap::Chain::Iterator *j;
2445 for (int i = 0; i < m_protos.width(); i++)
2446 for (j = m_protos.chain(i).first(); j != NULL; j = j->next()) {
2447 Proto *proto = j->item()->getData();
2448 if (proto == NULL)
2449 continue;
2450 proto->setIsInScene(false);
2451 proto->setWriteCDeclarationWritten(false);
2452 proto->setInUse(false);
2453 if (proto->getType() == VRML_POSITION_INTERPOLATOR)
2454 proto->setInUse(true);
2455 if (proto->getType() == VRML_ORIENTATION_INTERPOLATOR)
2456 proto->setInUse(true);
2457 if (proto->isDeclaredInRwd_h())
2458 proto->setInUse(true);
2459 }
2460 m_root->doWithBranch(markUsedProto, this);
2461 for (int i = 0; i < m_protos.width(); i++)
2462 for (j = m_protos.chain(i).first(); j != NULL; j = j->next()) {
2463 Proto *proto = j->item()->getData();
2464 if (proto == NULL)
2465 continue;
2466 if (proto->getType() == VRML_COMMENT)
2467 continue;
2468 if (proto->isMesh() && !proto->isExportTargetMesh())
2469 continue;
2470 if (proto->isMismatchingProto())
2471 continue;
2472 if (proto->isInUse())
2473 if (proto->writeCDeclaration(f, languageFlag) != 0)
2474 return -1;
2475 }
2476 WriteCDynamicNodeData parameters;
2477 parameters.result = 0;
2478 parameters.filedes = f;
2479 parameters.languageFlag = languageFlag;
2480 m_root->doWithBranch(writeCDynamicNodeDeclaration, ¶meters);
2481 return parameters.result;
2482 }
2483
2484 int
writeCDataFunctionsCalls(int f,int languageFlag)2485 Scene::writeCDataFunctionsCalls(int f, int languageFlag)
2486 {
2487 if (languageFlag & MANY_JAVA_CLASSES) {
2488 RET_ONERROR( mywritef(f, " }\n") )
2489 RET_ONERROR( mywritef(f, "}\n") )
2490 RET_ONERROR( mywritef(f, "class Data%sFunctionClass_%d {\n",
2491 TheApp->getCPrefix(), getNumDataClasses()) )
2492 }
2493 RET_ONERROR( mywritef(f,
2494 " public static void data%sFunction%d() {\n",
2495 TheApp->getCPrefix(), getNumDataClasses()) )
2496 increaseNumDataClasses();
2497
2498 return(0);
2499 }
2500
2501 struct WriteCStruct {
2502 int filedes;
2503 int ret;
2504 int languageFlag;
2505 bool outsideJavaClass;
2506 bool writeBracket;
2507 };
2508
2509 bool writeCVariableNameLine(Node *node, const char *variableName,
2510 struct WriteCStruct *cWrite, bool extraJavaClass);
2511
writeCSetWrittenFalse(Node * node,void * data)2512 bool writeCSetWrittenFalse(Node *node, void *data)
2513 {
2514 if (node == NULL)
2515 return true;
2516
2517 node->setWritten(false);
2518
2519 return true;
2520 }
2521
2522 class WriteData {
2523 public:
2524 int languageFlag;
2525 int filedes;
2526 };
2527
writeCCoordinateFirst(Node * node,void * data)2528 bool writeCCoordinateFirst(Node *node, void *data)
2529 {
2530 if (node == NULL)
2531 return true;
2532
2533 WriteData *wdata = (WriteData *)data;
2534 if (node->getType() == VRML_COORDINATE) {
2535 node->writeCDataFunction(wdata->filedes, wdata->languageFlag,
2536 true, true);
2537 }
2538 return true;
2539 }
2540
writeCIndexedFaceSetFirst(Node * node,void * data)2541 bool writeCIndexedFaceSetFirst(Node *node, void *data)
2542 {
2543 if (node == NULL)
2544 return true;
2545
2546 WriteData *wdata = (WriteData *)data;
2547 if (node->getType() == VRML_INDEXED_FACE_SET) {
2548 node->writeCDataFunction(wdata->filedes, wdata->languageFlag,
2549 true, true);
2550 }
2551 return true;
2552 }
2553
writeCShapeFirst(Node * node,void * data)2554 bool writeCShapeFirst(Node *node, void *data)
2555 {
2556 if (node == NULL)
2557 return true;
2558
2559 WriteData *wdata = (WriteData *)data;
2560 if (node->getType() == VRML_SHAPE) {
2561 node->writeCDataFunction(wdata->filedes, wdata->languageFlag,
2562 true, true);
2563 }
2564 return true;
2565 }
2566
writeCHAnimJointFirst(Node * node,void * data)2567 bool writeCHAnimJointFirst(Node *node, void *data)
2568 {
2569 if (node == NULL)
2570 return true;
2571
2572 WriteData *wdata = (WriteData *)data;
2573 if (node->getType() == X3D_HANIM_JOINT) {
2574 node->writeCDataFunction(wdata->filedes, wdata->languageFlag,
2575 true, true);
2576 }
2577 return true;
2578 }
2579
2580 static MyArray<const char *> variableNames;
2581
writeCNodeData(Node * node,void * data)2582 bool writeCNodeData(Node *node, void *data)
2583 {
2584 if (node == NULL)
2585 return true;
2586
2587 struct WriteCStruct *cWrite = (struct WriteCStruct *)data;
2588
2589 bool writeBracket = cWrite->writeBracket;
2590
2591 node->addToConvertedNodes(node->getScene()->getWriteFlags());
2592
2593 if (node->getNumConvertedNodes() > 0) {
2594 for (int i = 0; i < node->getNumConvertedNodes(); i++) {
2595 node->getConvertedNode(i)->doWithBranch(writeCNodeData, data,
2596 false);
2597 }
2598 writeBracket = false;
2599 }
2600
2601 if (!node->isCWriteable())
2602 return true;
2603
2604 Proto *proto = node->getProto();
2605 if (proto->getType() == VRML_COMMENT)
2606 return true;
2607 if (proto->isMismatchingProto())
2608 return true;
2609
2610 // do not write multiple declarations for USE'd nodes
2611 if (node->getFlag(NODE_FLAG_TOUCHED))
2612 return true;
2613 node->setFlag(NODE_FLAG_TOUCHED);
2614
2615 if (node->hasProtoNodes()) {
2616 NodePROTO *protoNode = (NodePROTO *)node;
2617 for (int i = 0; i < protoNode->getNumProtoNodes(); i++)
2618 protoNode->getProtoNode(i)->doWithBranch(writeCNodeData, data);
2619 if (cWrite->ret == -1)
2620 return false;
2621 }
2622
2623 bool extraJavaClass = false;
2624 if (node->needExtraJavaClass())
2625 extraJavaClass = true;
2626
2627 if (cWrite->languageFlag & MANY_JAVA_CLASSES) {
2628 if (cWrite->outsideJavaClass) {
2629 if (!extraJavaClass)
2630 return true;
2631 } else {
2632 if (extraJavaClass)
2633 return true;
2634 }
2635 }
2636 bool writeName = true;
2637 if (node->getType() != DUNE_CURVE_ANIMATION) {
2638 for (int i = 0; i < variableNames.size(); i++)
2639 if (strcmp(variableNames[i], node->getVariableName()) == 0) {
2640 writeName = false;
2641 break;
2642 }
2643 if (writeName) {
2644 writeCVariableNameLine(node, node->getVariableName(), cWrite,
2645 extraJavaClass);
2646 if (cWrite->ret != 0)
2647 return false;
2648 variableNames.append(node->getVariableName());
2649 }
2650 } else {
2651 NodeCurveAnimation *curve = (NodeCurveAnimation *)node;
2652 Node *inter = curve->getPositionInterpolator();
2653 const char *variableName = inter->getVariableName();
2654 bool writeName = true;
2655 for (int i = 0; i < variableNames.size(); i++)
2656 if (strcmp(variableNames[i], variableName) == 0) {
2657 writeName = false;
2658 break;
2659 }
2660 if (writeName) {
2661 writeCVariableNameLine(inter, variableName, cWrite, extraJavaClass);
2662 if (cWrite->ret != 0)
2663 return false;
2664 variableNames.append(variableName);
2665 }
2666 inter = curve->getOrientationInterpolator();
2667 variableName = inter->getVariableName();
2668 writeName = true;
2669 for (int i = 0; i < variableNames.size(); i++)
2670 if (strcmp(variableNames[i], node->getVariableName()) == 0) {
2671 writeName = false;
2672 break;
2673 }
2674 if (writeName) {
2675 writeCVariableNameLine(inter, variableName, cWrite, extraJavaClass);
2676 if (cWrite->ret != 0)
2677 return false;
2678 variableNames.append(variableName);
2679 }
2680 }
2681
2682 if (node->isMeshBasedNode())
2683 if (node->getType() != VRML_INDEXED_FACE_SET)
2684 if (writeName)
2685 writeBracket = true;
2686
2687 int f = cWrite->filedes;
2688 if (cWrite->languageFlag & MANY_JAVA_CLASSES)
2689 if (extraJavaClass && writeBracket) {
2690 RET_ONERROR( mywritestr(f, "}\n") )
2691 }
2692
2693 return true;
2694 }
2695
writeCVariableNameLine(Node * node,const char * variableName,struct WriteCStruct * cWrite,bool extraJavaClass)2696 bool writeCVariableNameLine(Node *node, const char *variableName,
2697 struct WriteCStruct *cWrite, bool extraJavaClass)
2698 {
2699 int f = cWrite->filedes;
2700 int error = 0;
2701 if (!(extraJavaClass && (cWrite->languageFlag & MANY_JAVA_CLASSES)))
2702 if (mywritestr(f, " ") != 0) {
2703 cWrite->ret = -1;
2704 return false;
2705 }
2706 if (cWrite->languageFlag & C_SOURCE)
2707 if (mywritestr(f, "struct ") != 0) {
2708 cWrite->ret = -1;
2709 return false;
2710 }
2711
2712 if (cWrite->languageFlag & MANY_JAVA_CLASSES) {
2713 if (extraJavaClass)
2714 RET_ONERROR( mywritef(f, "class %s%s {\n ",
2715 TheApp->getCPrefix(),
2716 node->getVariableName()) )
2717 RET_ONERROR( mywritestr(f, "public static ") )
2718 }
2719
2720 bool written = false;
2721 if (node->isDynamicFieldsNode() && !node->isPROTO()) {
2722 if (mywritestr(f, (const char *)node->getClassName()) != 0)
2723 error = -1;
2724 else
2725 written = true;
2726 } else if ((cWrite->languageFlag & C_SOURCE) && node->isPROTO() &&
2727 (!written)) {
2728 if (mywritef(f, "%s%s_%s", TheApp->getCPrefix(), (const char *)
2729 node->getProto()->getName(true),
2730 variableName) != 0)
2731 error = -1;
2732 else
2733 written = true;
2734 } if ((!written) && mywritef(f, "%s%s", TheApp->getCPrefix(), (const char *)
2735 node->getProto()->getName(true)) != 0)
2736 error = -1;
2737 if (mywritestr(f, " ") != 0)
2738 error = -1;
2739 else if (mywritestr(f, variableName) != 0)
2740 error = -1;
2741 else if (mywritestr(f, ";\n") != 0)
2742 error = -1;
2743 if (error != 0) {
2744 cWrite->ret = -1;
2745 }
2746 return true;
2747 }
2748
writeCDynamicNodeCallback(Node * node,void * data)2749 static bool writeCDynamicNodeCallback(Node *node, void *data)
2750 {
2751 WriteCDynamicNodeData *parameters = (WriteCDynamicNodeData *)data;
2752 Proto *proto = node->getProto();
2753 if (proto->isDynamicProto())
2754 parameters->result = node->writeCDynamicNodeCallback(
2755 parameters->filedes, parameters->languageFlag);
2756 if (parameters->result != 0)
2757 return false;
2758 return true;
2759 }
2760
writeCParentCallback(Node * node,void * data)2761 static bool writeCParentCallback(Node *node, void *data)
2762 {
2763 WriteCDynamicNodeData *parameters = (WriteCDynamicNodeData *)data;
2764 if (!node->isCWriteable())
2765 return true;
2766 parameters->result = node->writeCGetParent(parameters->filedes, parameters->languageFlag);
2767 if (parameters->result != 0)
2768 return false;
2769 return true;
2770 }
2771
writeCInstallDynamicNodeCallback(Node * node,void * data)2772 static bool writeCInstallDynamicNodeCallback(Node *node, void *data)
2773 {
2774 WriteCDynamicNodeData *parameters = (WriteCDynamicNodeData *)data;
2775 Proto *proto = node->getProto();
2776 if (proto->isDynamicProto() && !node->isPROTO())
2777 parameters->result = node->writeCInstallDynamicNodeCallback(
2778 parameters->filedes,
2779 parameters->languageFlag, node->getProto());
2780 if (parameters->result != 0)
2781 return false;
2782 return true;
2783 }
2784
writeCRemoveAlreadyWrittenEventOuts(Node * node,void * data)2785 static bool writeCRemoveAlreadyWrittenEventOuts(Node *node, void *data)
2786 {
2787 node->removeAlreadyWrittenEventOuts();
2788 return true;
2789 }
2790
2791 int
writeC(int f,int languageFlag)2792 Scene::writeC(int f, int languageFlag)
2793 {
2794 dynamicNodeCallbackRemove();
2795 m_root->doWithBranch(writeCRemoveAlreadyWrittenEventOuts, NULL);
2796 m_scriptTypeWritten = false;
2797 if (languageFlag & C_SOURCE)
2798 RET_ONERROR( mywritestr(f, "/*") )
2799 else
2800 RET_ONERROR( mywritestr(f, "//") )
2801 RET_ONERROR( mywritestr(f, " VRML97/X3D file \"") )
2802 URL *url = new URL(getURL());
2803 RET_ONERROR( mywritestr(f, url->GetFileName()) )
2804 delete url;
2805 RET_ONERROR( mywritestr(f, "\" converted to ") )
2806 if (languageFlag & C_SOURCE)
2807 RET_ONERROR( mywritestr(f, "C") )
2808 else if (languageFlag & CC_SOURCE)
2809 RET_ONERROR( mywritestr(f, "C++") )
2810 else if (languageFlag & JAVA_SOURCE)
2811 RET_ONERROR( mywritestr(f, "java") )
2812 RET_ONERROR( mywritestr(f, " with white_dune") )
2813 if (languageFlag & C_SOURCE)
2814 RET_ONERROR( mywritestr(f, "*/") )
2815 RET_ONERROR( mywritestr(f, "\n\n") )
2816 if (languageFlag & C_SOURCE) {
2817 RET_ONERROR( mywritestr(f, "#ifndef NULL\n") )
2818 RET_ONERROR( mywritestr(f, "# define NULL (void *)0\n") )
2819 RET_ONERROR( mywritestr(f, "#endif\n") )
2820 RET_ONERROR( mywritestr(f, "\n") )
2821 RET_ONERROR( mywritestr(f, "struct ") )
2822 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
2823 RET_ONERROR( mywritestr(f, ";\n") )
2824 RET_ONERROR( mywritestr(f, "\n") )
2825 RET_ONERROR( mywritestr(f, "typedef void ") )
2826 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2827 RET_ONERROR( mywritestr(f, ";\n") )
2828 RET_ONERROR( mywritestr(f, "\n") )
2829 RET_ONERROR( mywritestr(f, "struct ") )
2830 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2831 RET_ONERROR( mywritestr(f, "Struct;\n") )
2832 RET_ONERROR( mywritestr(f, "\n") )
2833 RET_ONERROR( mywritestr(f, "typedef void (*") )
2834 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2835 RET_ONERROR( mywritestr(f, "Callback)") )
2836 RET_ONERROR( mywritestr(f, "(") )
2837 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2838 RET_ONERROR( mywritestr(f, " *node, void *data);\n") )
2839 RET_ONERROR( mywritestr(f, "\n") )
2840 RET_ONERROR( mywritestr(f, "void ") )
2841 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2842 RET_ONERROR( mywritestr(f, "TreeRenderCallback(struct ") )
2843 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2844 RET_ONERROR( mywritestr(f, "Struct *node, void *data);\n") )
2845 RET_ONERROR( mywritestr(f, "void ") )
2846 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2847 RET_ONERROR( mywritestr(f, "TreeDoWithDataCallback(struct ") )
2848 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2849 RET_ONERROR( mywritestr(f, "Struct *node, void *data);\n") )
2850 RET_ONERROR( mywritestr(f, "typedef int (*") )
2851 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2852 RET_ONERROR( mywritestr(f, "ProcessEventCallback)") )
2853 RET_ONERROR( mywritestr(f, "(") )
2854 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2855 RET_ONERROR( mywritestr(f, " *node, const char *event, ") )
2856 RET_ONERROR( mywritestr(f, "void *data);\n") )
2857 RET_ONERROR( mywritestr(f, "\n") )
2858 RET_ONERROR( mywritestr(f, "\n\n") )
2859 }
2860 if (languageFlag & CC_SOURCE) {
2861 RET_ONERROR( mywritestr(f, "#include <stddef.h> // for NULL\n") )
2862 RET_ONERROR( mywritestr(f, "\n") )
2863 RET_ONERROR( mywritestr(f, "class ") )
2864 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
2865 RET_ONERROR( mywritestr(f, ";\n") )
2866 RET_ONERROR( mywritestr(f, "\n") )
2867 RET_ONERROR( mywritestr(f, "class ") )
2868 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2869 RET_ONERROR( mywritestr(f, " {\n") )
2870 RET_ONERROR( mywritestr(f, "public:\n") )
2871 RET_ONERROR( mywritestr(f, " ") )
2872 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2873 RET_ONERROR( mywritestr(f, "() {\n") )
2874 RET_ONERROR( mywritestr(f, " m_parent = NULL;\n") )
2875 RET_ONERROR( mywritestr(f, " m_protoRoot = NULL;\n") )
2876 RET_ONERROR( mywritestr(f, " m_data = NULL;\n") )
2877 RET_ONERROR( mywritestr(f, " }\n") )
2878 RET_ONERROR( mywritestr(f, " virtual void treeRender(") )
2879 RET_ONERROR( mywritestr(f, "void *dataptr) {\n") )
2880 RET_ONERROR( mywritestr(f, " if (m_protoRoot != NULL)\n") )
2881 RET_ONERROR( mywritestr(f, " m_protoRoot->") )
2882 RET_ONERROR( mywritestr(f, "treeRender(dataptr);\n") )
2883 RET_ONERROR( mywritestr(f, " }\n") )
2884 RET_ONERROR( mywritestr(f, " virtual void treeDoWithData(") )
2885 RET_ONERROR( mywritestr(f, "void *dataptr) {\n") )
2886 RET_ONERROR( mywritestr(f, " if (m_protoRoot != NULL)\n") )
2887 RET_ONERROR( mywritestr(f, " m_protoRoot->") )
2888 RET_ONERROR( mywritestr(f, "treeDoWithData(dataptr);\n") )
2889 RET_ONERROR( mywritestr(f, " }\n") )
2890 RET_ONERROR( mywritestr(f, " ") )
2891 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2892 RET_ONERROR( mywritestr(f, " *m_parent;\n") )
2893 RET_ONERROR( mywritestr(f, " ") )
2894 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2895 RET_ONERROR( mywritestr(f, " *m_protoRoot;\n") )
2896 RET_ONERROR( mywritestr(f, " void *m_data;\n") )
2897 RET_ONERROR( mywritestr(f, " virtual int getType() const = 0;\n") )
2898 RET_ONERROR( mywritestr(f, "};\n") )
2899 RET_ONERROR( mywritestr(f, "\n") )
2900 RET_ONERROR( mywritestr(f, "typedef void (*") )
2901 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2902 RET_ONERROR( mywritestr(f, "Callback)") )
2903 RET_ONERROR( mywritestr(f, "(") )
2904 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2905 RET_ONERROR( mywritestr(f, " *node, void *dataptr);\n") )
2906 RET_ONERROR( mywritestr(f, "typedef bool (*") )
2907 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2908 RET_ONERROR( mywritestr(f, "ProcessEventCallback)") )
2909 RET_ONERROR( mywritestr(f, "(") )
2910 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2911 RET_ONERROR( mywritestr(f, " *node, const char *event, ") )
2912 RET_ONERROR( mywritestr(f, "void *dataptr);\n") )
2913 RET_ONERROR( mywritestr(f, "\n\n") )
2914 }
2915 if (languageFlag & JAVA_SOURCE) {
2916 RET_ONERROR( mywritestr(f, "abstract class ") )
2917 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2918 RET_ONERROR( mywritestr(f, " {\n") )
2919 RET_ONERROR( mywritestr(f, " void treeRender(") )
2920 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2921 RET_ONERROR( mywritestr(f, "Node dataptr, Object object) {\n") )
2922 RET_ONERROR( mywritestr(f, " if (m_protoRoot != null)\n") )
2923 RET_ONERROR( mywritestr(f, " m_protoRoot.") )
2924 RET_ONERROR( mywritestr(f, "treeRender(dataptr, object);\n") )
2925 RET_ONERROR( mywritestr(f, " }\n") )
2926 RET_ONERROR( mywritestr(f, " void treeDoWithData(") )
2927 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2928 RET_ONERROR( mywritestr(f, "Node dataptr) {\n") )
2929 RET_ONERROR( mywritestr(f, " if (m_protoRoot != null)\n") )
2930 RET_ONERROR( mywritestr(f, " m_protoRoot.") )
2931 RET_ONERROR( mywritestr(f, "treeDoWithData(dataptr);\n") )
2932 RET_ONERROR( mywritestr(f, " }\n") )
2933 RET_ONERROR( mywritestr(f, " ") )
2934 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2935 RET_ONERROR( mywritestr(f, " m_parent;\n") )
2936 RET_ONERROR( mywritestr(f, " Object m_data;\n") )
2937 RET_ONERROR( mywritestr(f, " ") )
2938 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2939 RET_ONERROR( mywritestr(f, " m_protoRoot;\n") )
2940 RET_ONERROR( mywritestr(f, " abstract int getType();\n") )
2941 RET_ONERROR( mywritestr(f, "};\n") )
2942 RET_ONERROR( mywritestr(f, "\n") )
2943
2944 RET_ONERROR( mywritestr(f, "class ") )
2945 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2946 RET_ONERROR( mywritestr(f, "RenderCallback {\n") )
2947 RET_ONERROR( mywritestr(f, " public void render(") )
2948 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2949 RET_ONERROR( mywritestr(f, " node, Object object) {}\n") )
2950 RET_ONERROR( mywritestr(f, "}\n") )
2951
2952 RET_ONERROR( mywritestr(f, "class ") )
2953 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2954 RET_ONERROR( mywritestr(f, "TreeRenderCallback {\n") )
2955 RET_ONERROR( mywritestr(f, " public void treeRender(") )
2956 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2957 RET_ONERROR( mywritestr(f, " node, Object object) {}\n") )
2958 RET_ONERROR( mywritestr(f, "}\n") )
2959 RET_ONERROR( mywritestr(f, "\n") )
2960
2961 RET_ONERROR( mywritestr(f, "class ") )
2962 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2963 RET_ONERROR( mywritestr(f, "DoWithDataCallback {\n") )
2964 RET_ONERROR( mywritestr(f, " public void doWithData(") )
2965 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2966 RET_ONERROR( mywritestr(f, " node) ") )
2967 RET_ONERROR( mywritestr(f, "{}\n") )
2968 RET_ONERROR( mywritestr(f, " public void update(") )
2969 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2970 RET_ONERROR( mywritestr(f, " node) ") )
2971 RET_ONERROR( mywritestr(f, "{}\n") )
2972 RET_ONERROR( mywritestr(f, " public Object getNullOrObject(") )
2973 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2974 RET_ONERROR( mywritestr(f, " node) ") )
2975 RET_ONERROR( mywritestr(f, "{ return null; }\n") )
2976 RET_ONERROR( mywritestr(f, "}\n") )
2977
2978 RET_ONERROR( mywritestr(f, "class ") )
2979 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2980 RET_ONERROR( mywritestr(f, "TreeDoWithDataCallback {\n") )
2981 RET_ONERROR( mywritestr(f, " public void treeDoWithData(") )
2982 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2983 RET_ONERROR( mywritestr(f, " node) ") )
2984 RET_ONERROR( mywritestr(f, "{}\n") )
2985 RET_ONERROR( mywritestr(f, "}\n") )
2986 RET_ONERROR( mywritestr(f, "\n") )
2987
2988 RET_ONERROR( mywritestr(f, "class ") )
2989 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2990 RET_ONERROR( mywritestr(f, "CreateNormalsCallback {\n") )
2991 RET_ONERROR( mywritestr(f, " public void createNormals(") )
2992 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
2993 RET_ONERROR( mywritestr(f, " node, Object data) {}\n") )
2994 RET_ONERROR( mywritestr(f, "}\n") )
2995
2996 RET_ONERROR( mywritestr(f, "class ") )
2997 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
2998 RET_ONERROR( mywritestr(f, "ProcessEventCallback {\n") )
2999 RET_ONERROR( mywritestr(f, " public boolean processEvent(") )
3000 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
3001 RET_ONERROR( mywritestr(f, " node, ") )
3002 RET_ONERROR( mywritestr(f, "String") )
3003 RET_ONERROR( mywritestr(f, " event) ") )
3004 RET_ONERROR( mywritestr(f, "{ return false;}\n") )
3005 RET_ONERROR( mywritestr(f, "}\n") )
3006
3007 RET_ONERROR( mywritestr(f, "\n\n") )
3008 }
3009 RET_ONERROR( writeCDeclaration(f, languageFlag) )
3010 RET_ONERROR( mywritestr(f, "\n") )
3011
3012 int numDataFunctions = 0;
3013 MyArray<int> startFunctions;
3014 MyArray<int> numFunctionsPerClass;
3015
3016 zeroNumDataFunctions();
3017 setStartNumDataFunctions(0);
3018
3019 WriteData data;
3020 data.filedes = f;
3021 data.languageFlag = languageFlag;
3022
3023 if (languageFlag & MANY_JAVA_CLASSES) {
3024 struct WriteCStruct cWrite;
3025 cWrite.filedes = f;
3026 cWrite.ret = 0;
3027 cWrite.languageFlag = languageFlag;
3028 cWrite.outsideJavaClass = true;
3029 cWrite.writeBracket = true;
3030
3031 getNodes()->clearFlag(NODE_FLAG_TOUCHED); // to handle DEF/USE
3032 m_root->doWithBranch(writeCNodeData, &cWrite);
3033 if (cWrite.ret !=0)
3034 return -1;
3035 RET_ONERROR( mywritestr(f, "\n") )
3036
3037 if (m_root->writeC(f, languageFlag | OUTSIDE_JAVA_CLASS))
3038 return -1;
3039
3040 getNodes()->clearFlag(NODE_FLAG_TOUCHED); // to handle DEF/USE
3041
3042 if (m_root->writeCDataAsFunctions(f, languageFlag))
3043 return -1;
3044
3045 if (languageFlag & MANY_JAVA_CLASSES) {
3046 RET_ONERROR( mywritef(f, "class %sScenegraphFunctions%d {\n",
3047 TheApp->getCPrefix(), getNumDataClasses()) )
3048 RET_ONERROR( mywritef(f, " static void data%sFunction0() {",
3049 TheApp->getCPrefix()) )
3050 }
3051
3052 m_root->doWithBranch(writeCSetWrittenFalse, NULL);
3053
3054 m_root->doWithBranch(writeCCoordinateFirst, &data,
3055 true, false, false, true, false, true);
3056 numFunctionsPerClass.append(getNumDataFunctions());
3057 setNumDataFunctionsPerClass(getNumDataFunctions());
3058 setStartNumDataFunctions(numDataFunctions);
3059 startFunctions.append(numDataFunctions);
3060 numDataFunctions += getNumDataFunctions();
3061 RET_ONERROR( writeCDataFunctionsCalls(f, languageFlag) )
3062 RET_ONERROR( mywritestr(f, "\n") )
3063
3064 m_root->doWithBranch(writeCIndexedFaceSetFirst, &data,
3065 true, false, false, true, false, true);
3066 numFunctionsPerClass.append(getNumDataFunctions());
3067 setNumDataFunctionsPerClass(getNumDataFunctions());
3068 startFunctions.append(numDataFunctions);
3069 setStartNumDataFunctions(numDataFunctions);
3070 numDataFunctions += getNumDataFunctions();
3071 RET_ONERROR( writeCDataFunctionsCalls(f, languageFlag) )
3072 RET_ONERROR( mywritestr(f, "\n") )
3073 m_root->doWithBranch(writeCShapeFirst, &data);
3074 numFunctionsPerClass.append(getNumDataFunctions());
3075
3076 setStartNumDataFunctions(getNumDataFunctions());
3077 setNumDataFunctionsPerClass(getNumDataFunctions());
3078 startFunctions.append(numDataFunctions);
3079 setStartNumDataFunctions(numDataFunctions);
3080 numDataFunctions += getNumDataFunctions();
3081 RET_ONERROR( writeCDataFunctionsCalls(f, languageFlag) )
3082 RET_ONERROR( mywritestr(f, "\n") )
3083
3084 m_root->doWithBranch(writeCHAnimJointFirst, &data,
3085 true, false, false, true, false, true);
3086 numFunctionsPerClass.append(getNumDataFunctions());
3087 setNumDataFunctionsPerClass(getNumDataFunctions());
3088 setStartNumDataFunctions(numDataFunctions);
3089 startFunctions.append(numDataFunctions);
3090 numDataFunctions += getNumDataFunctions();
3091 RET_ONERROR( writeCDataFunctionsCalls(f, languageFlag) )
3092 RET_ONERROR( mywritestr(f, " }\n") )
3093 RET_ONERROR( mywritestr(f, "}\n") )
3094 RET_ONERROR( mywritestr(f, "\n") )
3095 }
3096
3097 WriteCDynamicNodeData parameters;
3098 parameters.result = 0;
3099 parameters.filedes = f;
3100 parameters.languageFlag = languageFlag;
3101 m_root->doWithBranch(writeCDynamicNodeCallback, ¶meters);
3102 if (parameters.result != 0)
3103 return -1;
3104
3105 if (languageFlag & C_SOURCE)
3106 RET_ONERROR( mywritestr(f, "struct ") )
3107 else
3108 RET_ONERROR( mywritestr(f, "class ") )
3109 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
3110 RET_ONERROR( mywritestr(f, " {\n") )
3111 if (languageFlag & CC_SOURCE)
3112 RET_ONERROR( mywritestr(f, "public:\n") )
3113 struct WriteCStruct cWrite;
3114 cWrite.filedes = f;
3115 cWrite.ret = 0;
3116 cWrite.languageFlag = languageFlag;
3117 cWrite.outsideJavaClass = false;
3118 cWrite.writeBracket = true;
3119 getNodes()->clearFlag(NODE_FLAG_TOUCHED); // to handle DEF/USE
3120 variableNames.resize(0);;
3121 m_root->doWithBranch(writeCNodeData, &cWrite);
3122 if (cWrite.ret !=0)
3123 return -1;
3124
3125 if (languageFlag & C_SOURCE) {
3126 RET_ONERROR( mywritestr(f, "};\n\n") )
3127
3128 RET_ONERROR( mywritestr(f, "struct ") )
3129 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
3130 RET_ONERROR( mywritestr(f, "Struct {\n") )
3131 RET_ONERROR( mywritestr(f, " ") )
3132 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
3133 RET_ONERROR( mywritestr(f, " *m_parent;\n") )
3134 RET_ONERROR( mywritestr(f, " ") )
3135 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
3136 RET_ONERROR( mywritestr(f, " *m_protoRoot;\n") )
3137 RET_ONERROR( mywritestr(f, " int m_type;\n") )
3138 RET_ONERROR( mywritestr(f, " void *m_data;\n") )
3139 RET_ONERROR( mywritestr(f, "};\n\n") )
3140
3141 RET_ONERROR( mywritestr(f, "void ") )
3142 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
3143 RET_ONERROR( mywritestr(f, "Init(") )
3144 RET_ONERROR( mywritestr(f, "struct ") )
3145 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
3146 RET_ONERROR( mywritestr(f, " *self) {\n") )
3147 if (m_root->writeC(f, languageFlag))
3148 return -1;
3149 parameters.result = 0;
3150 parameters.filedes = f;
3151 parameters.languageFlag = languageFlag;
3152 m_root->doWithBranch(writeCInstallDynamicNodeCallback, ¶meters);
3153 if (parameters.result != 0)
3154 return -1;
3155 RET_ONERROR( mywritestr(f, " }\n\n") )
3156 RET_ONERROR( mywritestr(f, "}\n\n") )
3157 RET_ONERROR( writeCTreeCallback(f, "Render") )
3158 RET_ONERROR( mywritestr(f, "\n") )
3159 RET_ONERROR( writeCTreeCallback(f, "DoWithData") )
3160 RET_ONERROR( mywritestr(f, "\n") )
3161
3162 RET_ONERROR( mywritef(f, "%s%s *", TheApp->getCPrefix(), "Node") )
3163 RET_ONERROR( mywritef(f, "%sGetNodeFromGlName(", TheApp->getCPrefix()) )
3164 RET_ONERROR( mywritef(f, "struct %sSceneGraph *self, int glName) {\n",
3165 TheApp->getCPrefix()) )
3166 RET_ONERROR( mywritestr(f, " switch (glName) {\n") )
3167 for (long i = 0; i < m_glNameData.size(); i++) {
3168 RET_ONERROR( mywritef(f, " case %d:\n",
3169 m_glNameData[i].glName) )
3170 RET_ONERROR( mywritestr(f, " return ") )
3171 RET_ONERROR( mywritef(f, "&self->%s;\n", (const char *)
3172 m_glNameData[i].nodeName) )
3173 }
3174 RET_ONERROR( mywritestr(f, " }\n") )
3175 RET_ONERROR( mywritestr(f, " return NULL;\n") )
3176 RET_ONERROR( mywritestr(f, "}\n") )
3177
3178 for (int i = 0; i < LAST_TYPE; i++) {
3179 FieldValue *value = typeDefaultValue(i);
3180 value->writeCSendEventFunction(f, languageFlag);
3181 }
3182 }
3183 getNodes()->clearFlag(NODE_FLAG_TOUCHED); // to handle DEF/USE
3184 if (languageFlag & CC_SOURCE) {
3185 RET_ONERROR( mywritestr(f, "public:\n") )
3186 RET_ONERROR( mywritestr(f, " ") )
3187 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
3188 RET_ONERROR( mywritestr(f, "();\n") )
3189
3190 RET_ONERROR( mywritestr(f, " ") )
3191 RET_ONERROR( mywritestr(f, "void render(void *data) ") )
3192 RET_ONERROR( mywritestr(f, "{ root.treeRender(data); }\n") )
3193
3194 RET_ONERROR( mywritestr(f, " ") )
3195 RET_ONERROR( mywritestr(f, "void doWithData(void *data) ") )
3196 RET_ONERROR( mywritestr(f, "{ root.treeDoWithData(data); }\n") )
3197
3198 RET_ONERROR( mywritestr(f, " ") )
3199 RET_ONERROR( mywritef(f, "%sNode *", TheApp->getCPrefix()) )
3200 RET_ONERROR( mywritestr(f, "getNodeFromGlName(int glName);\n") )
3201 RET_ONERROR( mywritestr(f, "};\n\n") )
3202
3203 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
3204 RET_ONERROR( mywritestr(f, "::") )
3205 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
3206 RET_ONERROR( mywritestr(f, "() {\n") )
3207 if (m_root->writeC(f, languageFlag))
3208 return -1;
3209 parameters.result = 0;
3210 parameters.filedes = f;
3211 parameters.languageFlag = languageFlag;
3212 m_root->doWithBranch(writeCInstallDynamicNodeCallback, ¶meters);
3213 if (parameters.result != 0)
3214 return -1;
3215
3216 RET_ONERROR( mywritestr(f, "}\n") )
3217
3218 RET_ONERROR( mywritef(f, "%s%s *", TheApp->getCPrefix(), "Node") )
3219 RET_ONERROR( mywritef(f, "%s::",TheApp->getCSceneGraphName()) )
3220 RET_ONERROR( mywritef(f, "getNodeFromGlName(int glName) {\n") )
3221 RET_ONERROR( mywritestr(f, " switch (glName) {\n") )
3222 for (long i = 0; i < m_glNameData.size(); i++) {
3223 RET_ONERROR( mywritef(f, " case %d:\n",
3224 m_glNameData[i].glName) )
3225 RET_ONERROR( mywritestr(f, " return ") )
3226 RET_ONERROR( mywritef(f, "&%s;\n", (const char *)
3227 m_glNameData[i].nodeName) )
3228 }
3229 RET_ONERROR( mywritestr(f, " }\n") )
3230 RET_ONERROR( mywritestr(f, " return NULL;\n") )
3231 RET_ONERROR( mywritestr(f, "}\n") )
3232
3233 for (int i = 0; i < LAST_TYPE; i++) {
3234 FieldValue *value = typeDefaultValue(i);
3235 value->writeCSendEventFunction(f, languageFlag);
3236 }
3237 } else if (languageFlag & JAVA_SOURCE) {
3238 if (!(languageFlag & MANY_JAVA_CLASSES)) {
3239
3240 if (m_root->writeCDataAsFunctions(f, languageFlag, true))
3241 return -1;
3242
3243 numFunctionsPerClass.append(getNumDataFunctions());
3244 setNumDataFunctionsPerClass(getNumDataFunctions());
3245 setStartNumDataFunctions(numDataFunctions);
3246 startFunctions.append(numDataFunctions);
3247 numDataFunctions += getNumDataFunctions();
3248
3249 RET_ONERROR(writeCDataFunctionsCalls(f, languageFlag) )
3250
3251 RET_ONERROR( mywritestr(f, " }\n") )
3252 }
3253
3254 RET_ONERROR( mywritestr(f, " ") )
3255 RET_ONERROR( mywritestr(f, "public static boolean initThings = true;\n"))
3256 RET_ONERROR( mywritestr(f, " ") )
3257 RET_ONERROR( mywritestr(f, TheApp->getCSceneGraphName()) )
3258 RET_ONERROR( mywritestr(f, "() {\n") )
3259
3260 if (m_root->writeC(f, languageFlag))
3261 return -1;
3262 for (int j = 0; j < getNumDataClasses(); j++) {
3263 for (int i = 0; i < 1; i++) {
3264 if (j == getNumDataClasses() - 1) {
3265 RET_ONERROR( mywritestr(f, " if (initThings)\n") )
3266 RET_ONERROR( mywritestr(f, " ") )
3267 RET_ONERROR( mywritestr(f, " ") )
3268 if (languageFlag & MANY_JAVA_CLASSES)
3269 RET_ONERROR( mywritef(f, "%sScenegraphFunctions%d.",
3270 TheApp->getCPrefix(), 0) )
3271 RET_ONERROR( mywritef(f, "data%sFunction%d();\n",
3272 TheApp->getCPrefix(), 0) )
3273 }
3274 if (j == 2) {
3275 RET_ONERROR( mywritestr(f, " if (initThings)\n") )
3276 RET_ONERROR( mywritestr(f, " ") )
3277 }
3278
3279 RET_ONERROR( mywritestr(f, " ") )
3280 if (languageFlag & MANY_JAVA_CLASSES)
3281 RET_ONERROR( mywritef(f, "Data%sFunctionClass_%d.",
3282 TheApp->getCPrefix(), j) )
3283 RET_ONERROR( mywritef(f, "data%sFunction%d();\n",
3284 TheApp->getCPrefix(), j) )
3285
3286 if (j == getNumDataClasses() - 1)
3287 if (languageFlag & MANY_JAVA_CLASSES) {
3288 RET_ONERROR(m_root->writeCDataFunction(f, languageFlag,
3289 true, true) )
3290 }
3291 }
3292 }
3293 RET_ONERROR( mywritestr(f, " setParents();\n") )
3294
3295 RET_ONERROR( mywritestr(f , " }\n") )
3296
3297 parameters.result = 0;
3298 parameters.filedes = f;
3299 parameters.languageFlag = languageFlag;
3300 m_root->doWithBranch(writeCInstallDynamicNodeCallback, ¶meters);
3301 if (parameters.result != 0)
3302 return -1;
3303
3304 RET_ONERROR( mywritestr(f, " ") )
3305 if (languageFlag & MANY_JAVA_CLASSES)
3306 RET_ONERROR( mywritestr(f, "static ") )
3307 RET_ONERROR( mywritestr(f, "void render() ") )
3308 RET_ONERROR( mywritestr(f, "{ root.treeRender(null, null); }\n") )
3309 RET_ONERROR( mywritestr(f, " ") )
3310 if (languageFlag & MANY_JAVA_CLASSES)
3311 RET_ONERROR( mywritestr(f, "static ") )
3312 RET_ONERROR( mywritestr(f, "void doWithData() ") )
3313 RET_ONERROR( mywritestr(f, "{ root.treeDoWithData(null); }\n") )
3314
3315 RET_ONERROR( mywritef(f, " static %s%s ",
3316 TheApp->getCPrefix(), "Node") )
3317 RET_ONERROR( mywritef(f, "getNodeFromGlName(") )
3318 RET_ONERROR( mywritef(f, "int glName) {\n") )
3319 RET_ONERROR( mywritestr(f, " switch (glName) {\n") )
3320 for (long i = 0; i < m_glNameData.size(); i++) {
3321 RET_ONERROR( mywritef(f, " case %d:\n",
3322 m_glNameData[i].glName) )
3323 RET_ONERROR( mywritestr(f, " return ") )
3324 MyString className = "";
3325 /*
3326 if (m_glNameData[i].node->hasName())
3327 className += TheApp->getCSceneGraphName();
3328 else {
3329 */
3330 className += TheApp->getCPrefix();
3331 className += m_glNameData[i].nodeName;
3332 // }
3333 RET_ONERROR( mywritef(f, "%s.%s;\n",
3334 (const char *)className,
3335 (const char *)m_glNameData[i].nodeName
3336 ) )
3337 }
3338 RET_ONERROR( mywritef(f, " }\n") )
3339 RET_ONERROR( mywritef(f, " return null;\n") )
3340 RET_ONERROR( mywritef(f, " }\n") )
3341
3342 RET_ONERROR( mywritestr(f, " public void setParents() {\n") )
3343 parameters.result = 0;
3344 parameters.filedes = f;
3345 parameters.languageFlag = languageFlag;
3346 m_root->doWithBranch(writeCParentCallback, ¶meters);
3347 if (parameters.result != 0)
3348 return -1;
3349 RET_ONERROR( mywritestr(f, " }\n") )
3350
3351 for (int i = 0; i < LAST_TYPE; i++) {
3352 FieldValue *value = typeDefaultValue(i);
3353 value->writeCSendEventFunction(f, languageFlag);
3354 }
3355 }
3356
3357 if (languageFlag & JAVA_SOURCE) {
3358 RET_ONERROR( mywritestr(f, "\n") )
3359 RET_ONERROR( mywritestr(f, " void ") )
3360 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3361 RET_ONERROR( mywritestr(f, "ShowError(Exception e) {\n") )
3362 RET_ONERROR( mywritestr(f, " StackTraceElement stack[] = e.getStackTrace();\n") )
3363 RET_ONERROR( mywritestr(f, " ") )
3364 if (TheApp->isWonderlandModuleExport()) {
3365 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3366 RET_ONERROR( mywritestr(f, "_Util.logger.warning") )
3367 } else
3368 RET_ONERROR( mywritestr(f, "java.lang.System.err.print") )
3369 RET_ONERROR( mywritestr(f, "(\"\\n\" + e.getMessage() + \"\\n\");\n") )
3370 RET_ONERROR( mywritestr(f, " for (int i = 0; i < stack.length; i++)\n") )
3371 RET_ONERROR( mywritestr(f, " ") )
3372 if (TheApp->isWonderlandModuleExport()) {
3373 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3374 RET_ONERROR( mywritestr(f, "_Util.logger.warning") )
3375 } else
3376 RET_ONERROR( mywritestr(f, "java.lang.System.err.print") )
3377 RET_ONERROR( mywritestr(f, "(stack[i].toString() + \"\\n\");\n") )
3378 RET_ONERROR( mywritestr(f, " }\n") )
3379 }
3380 RET_ONERROR( writeCRoutes(f, languageFlag) )
3381 if (languageFlag & JAVA_SOURCE)
3382 RET_ONERROR( mywritestr(f, "};\n\n") )
3383 return(0);
3384 }
3385
3386 int
writeCTreeCallback(int f,const char * functionName,bool callTreeCallback)3387 Scene::writeCTreeCallback(int f, const char *functionName,
3388 bool callTreeCallback)
3389 {
3390 RET_ONERROR( mywritestr(f, "void ") )
3391 RET_ONERROR( mywritestr(f, TheApp->getCPrefix()) )
3392 RET_ONERROR( mywritestr(f, "Tree") )
3393 RET_ONERROR( mywritestr(f, functionName) )
3394 if (callTreeCallback)
3395 RET_ONERROR( mywritestr(f, "Callback") )
3396 RET_ONERROR( mywritestr(f, "(struct ") )
3397 RET_ONERROR( mywritestr(f, TheApp->getCNodeName()) )
3398 RET_ONERROR( mywritestr(f, "Struct *node,") )
3399 RET_ONERROR( mywritestr(f, " void *data) {\n") )
3400 RET_ONERROR( mywritestr(f, " switch(node->") )
3401 RET_ONERROR( mywritestr(f, "m_type) {\n") )
3402 ProtoMap::Chain::Iterator *j;
3403 for (int i = 0; i < m_protos.width(); i++)
3404 for (j = m_protos.chain(i).first(); j != NULL; j = j->next()) {
3405 Proto *proto = j->item()->getData();
3406 if (proto == NULL)
3407 continue;
3408 if ((proto->getType() != VRML_INDEXED_FACE_SET) &&
3409 (!(proto->isInScene())))
3410 continue;
3411 if (proto->getType() == VRML_COMMENT)
3412 continue;
3413 if (proto->isMesh() &&
3414 !(proto->isExportTargetMesh()))
3415 continue;
3416 if (proto->isMismatchingProto())
3417 continue;
3418 RET_ONERROR( mywritestr(f, " case ") )
3419 if (proto->getNumNodes() > 0)
3420 RET_ONERROR( mywritef(f, "%d", getProtoType(proto)) )
3421 else
3422 RET_ONERROR( mywritef(f, "%d", proto->getType()) )
3423 RET_ONERROR( mywritestr(f, ":\n") )
3424 if (callTreeCallback) {
3425 RET_ONERROR( mywritestr(f, " if (") )
3426 RET_ONERROR( mywritestr(f, proto->getClassName()) )
3427 RET_ONERROR( mywritestr(f, "Tree") )
3428 RET_ONERROR( mywritestr(f, functionName) )
3429 RET_ONERROR( mywritestr(f, "Callback)\n") )
3430 RET_ONERROR( mywritestr(f, " ") )
3431 RET_ONERROR( mywritestr(f, proto->getClassName()) )
3432 RET_ONERROR( mywritestr(f, "Tree") )
3433 RET_ONERROR( mywritestr(f, functionName) )
3434 RET_ONERROR( mywritestr(f, "Callback(node, data);\n") )
3435 RET_ONERROR( mywritestr(f, " else\n") )
3436 RET_ONERROR( mywritestr(f, " ") )
3437 }
3438 RET_ONERROR( mywritestr(f, " ") )
3439 RET_ONERROR( mywritestr(f, proto->getClassName()) )
3440 RET_ONERROR( mywritestr(f, "Tree") )
3441 RET_ONERROR( mywritestr(f, functionName) )
3442 RET_ONERROR( mywritestr(f, "(node, data);\n") )
3443 RET_ONERROR( mywritestr(f, " break;\n") )
3444 }
3445 RET_ONERROR( mywritestr(f, " }\n") )
3446 RET_ONERROR( mywritestr(f, "}\n") )
3447 return 0;
3448 }
3449
3450 class WriteCFunctionCallData {
3451 public:
3452 int filedes;
3453 int languageFlag;
3454 int returnValue;
3455 };
3456
searchNodesOnlyOutputAndWriteCRoutes(Node * node,void * data)3457 static bool searchNodesOnlyOutputAndWriteCRoutes(Node *node, void *data)
3458 {
3459 WriteCFunctionCallData *cdata = (WriteCFunctionCallData *)data;
3460 if (node->hasOutputs() && !(node->hasInputs())) {
3461 if (node->writeCAndFollowRoutes(cdata->filedes, 0, cdata->languageFlag,
3462 false, "") != 0) {
3463 cdata->returnValue = -1;
3464 return false;
3465 }
3466 }
3467 return true;
3468 }
3469
3470 int
writeCRoutes(int filedes,int languageFlag)3471 Scene::writeCRoutes(int filedes, int languageFlag)
3472 {
3473 static bool alreadyIn = false;
3474 if (alreadyIn)
3475 return 0;
3476 alreadyIn = true;
3477 // write tempory nodes first
3478 for (long i = 0; i < m_delayedWriteNodes.size(); i++) {
3479 int ret = m_delayedWriteNodes[i]->writeC(filedes, languageFlag);
3480 if (ret < 0) {
3481 alreadyIn = false;
3482 return ret;
3483 }
3484 removeNode(m_delayedWriteNodes[i]);
3485 }
3486 if (m_delayedWriteNodes.size() > 0)
3487 m_delayedWriteNodes.resize(0);
3488 alreadyIn = false;
3489
3490 if (languageFlag & JAVA_SOURCE)
3491 RET_ONERROR( mywritestr(filedes, " ") )
3492 RET_ONERROR( mywritestr(filedes, "void ") )
3493 RET_ONERROR( mywritestr(filedes, TheApp->getCProcessEventsName()) )
3494 RET_ONERROR( mywritestr(filedes, "(") )
3495 if (languageFlag & C_SOURCE)
3496 RET_ONERROR( mywritestr(filedes, "struct ") )
3497 if (languageFlag & (C_SOURCE | CC_SOURCE)) {
3498 RET_ONERROR( mywritestr(filedes, TheApp->getCSceneGraphName()) )
3499 RET_ONERROR( mywritestr(filedes, " *self, void *data") )
3500 }
3501
3502 RET_ONERROR( mywritestr(filedes, ") {\n") )
3503
3504 if (languageFlag & JAVA_SOURCE) {
3505 RET_ONERROR( indentf(filedes, 8) )
3506 RET_ONERROR( mywritestr(filedes, "boolean nextEvent = false;\n") )
3507 } else {
3508 RET_ONERROR( indentf(filedes, 4) )
3509 RET_ONERROR( mywritestr(filedes, "int nextEvent = 0;\n") )
3510 }
3511
3512 WriteCFunctionCallData cdata;
3513 cdata.filedes = filedes;
3514 cdata.languageFlag = languageFlag;
3515 cdata.returnValue = 0;
3516 m_root->doWithBranch(searchNodesOnlyOutputAndWriteCRoutes, &cdata);
3517 for (long i = 0; i < m_sensorNodes.size(); i++) {
3518 if (languageFlag & JAVA_SOURCE)
3519 RET_ONERROR( mywritestr(filedes, " ") )
3520 RET_ONERROR( mywritestr(filedes, " ") )
3521 MyString className = "";
3522 if (languageFlag & JAVA_SOURCE) {
3523 if (m_sensorNodes[i]->hasName())
3524 className += TheApp->getCSceneGraphName();
3525 else {
3526 className += TheApp->getCPrefix();
3527 className += m_sensorNodes[i]->getVariableName();
3528 }
3529 RET_ONERROR( mywritestr(filedes, "Extra.") )
3530 }
3531 RET_ONERROR( mywritestr(filedes, "reInitSensor(") )
3532 if (languageFlag & JAVA_SOURCE) {
3533 RET_ONERROR( mywritef(filedes, "X3d%s.",
3534 m_sensorNodes[i]->getVariableName()) )
3535 } else
3536 RET_ONERROR( mywritestr(filedes, "&(self->") )
3537 RET_ONERROR( mywritestr(filedes, m_sensorNodes[i]->getVariableName()) )
3538 if (!(languageFlag & JAVA_SOURCE))
3539 RET_ONERROR( mywritestr(filedes, ")") )
3540 RET_ONERROR( mywritestr(filedes, ");\n") )
3541 }
3542 removeSensorNodes();
3543 if (languageFlag & JAVA_SOURCE)
3544 RET_ONERROR( mywritestr(filedes, " ") )
3545 RET_ONERROR( mywritestr(filedes, "}\n") )
3546 return cdata.returnValue;
3547
3548 return 0;
3549 }
3550
searchExtensionProto(int extension,Node * node,void * data)3551 static bool searchExtensionProto(int extension, Node *node, void *data)
3552 {
3553 MyArray<Proto *> *protoArrayPtr = (MyArray<Proto *> *) data;
3554 if (!node->hasDefault(extension) /* && !node->hasRoute(extension)*/) {
3555 for (long i = 0; i < (*protoArrayPtr).size(); i++)
3556 if ((*protoArrayPtr)[i] == node->getProto())
3557 return true;
3558 (*protoArrayPtr).append(node->getProto());
3559 }
3560 // Todo: also check if Route to extension event
3561 return true;
3562 }
3563
searchCoverExtensionProto(Node * node,void * data)3564 static bool searchCoverExtensionProto(Node *node, void *data)
3565 {
3566 return searchExtensionProto(FF_COVER_ONLY, node, data);
3567 }
3568
searchKambiExtensionProto(Node * node,void * data)3569 static bool searchKambiExtensionProto(Node *node, void *data)
3570 {
3571 return searchExtensionProto(FF_KAMBI_ONLY, node, data);
3572 }
3573
3574 int
writeExtensionProtos(int f,int flag)3575 Scene::writeExtensionProtos(int f, int flag)
3576 {
3577 int x3d = false;
3578 if (flag == FF_X3D_ONLY)
3579 x3d = true;
3580 MyArray<Proto *> protoArray;
3581 NodeList *nodes = ((NodeGroup *)getRoot())->children()->getValues();
3582 for (long i = 0; i < nodes->size(); i++) {
3583 if (flag == FF_COVER_ONLY)
3584 nodes->get(i)->doWithBranch(searchCoverExtensionProto,
3585 &protoArray, false);
3586 if (flag == FF_KAMBI_ONLY)
3587 nodes->get(i)->doWithBranch(searchKambiExtensionProto,
3588 &protoArray, false);
3589 }
3590 for (long i = 0; i < protoArray.size(); i++) {
3591 addProtoName(protoArray[i]->getName(false));
3592 Proto *newProto = new Proto(this, protoArray[i], flag);
3593 if (newProto->write(f, 0, x3d) != 0) {
3594 deleteExtensionProtos();
3595 return -1;
3596 }
3597 if (mywritestr(f, "\n") != 0) {
3598 deleteExtensionProtos();
3599 return -1;
3600 }
3601
3602 m_writtenExtensionProtos.append(newProto);
3603 }
3604 return 0;
3605 }
3606
3607 void
deleteExtensionProtos(void)3608 Scene::deleteExtensionProtos(void)
3609 {
3610 for (long i = 0; i < m_writtenExtensionProtos.size(); i++) {
3611 deleteProtoName(m_writtenExtensionProtos[i]->getName(false));
3612 deleteProto(m_writtenExtensionProtos[i]->getName(false));
3613 delete(m_writtenExtensionProtos[i]);
3614 }
3615 m_writtenExtensionProtos.resize(0);
3616 }
3617
3618 Proto *
getExtensionProto(Proto * proto)3619 Scene::getExtensionProto(Proto *proto)
3620 {
3621 for (long i = 0; i < m_writtenExtensionProtos.size(); i++)
3622 if (m_writtenExtensionProtos[i]->getNode(0)->getProto() == proto)
3623 return m_writtenExtensionProtos[i];
3624 return NULL;
3625 }
3626
3627
3628 void
addProto(MyString name,Proto * value)3629 Scene::addProto(MyString name, Proto *value)
3630 {
3631 if (belongsToNodeWithExternProto(name))
3632 return;
3633 Proto *proto = m_protos[name];
3634 if (proto && proto->isX3dInternalProto())
3635 return;
3636 m_protos[name] = value;
3637 }
3638
deleteProto(MyString name)3639 void Scene::deleteProto(MyString name)
3640 {
3641 if (m_protos.hasKey(name)) {
3642 m_protos.remove(name);
3643 deleteProtoName(name);
3644 }
3645 }
3646
3647 Proto *
getProto(MyString name)3648 Scene::getProto(MyString name)
3649 {
3650 return m_protos[name];
3651 }
3652
3653 Proto *
getExtensionProto(MyString name)3654 Scene::getExtensionProto(MyString name)
3655 {
3656 Proto *proto = NULL;
3657 MyString protoName = name;
3658 // TODO: handle X3D node names like the following in a better way
3659 if ((strcmp(protoName, "NurbsPatchSurface") == 0) ||
3660 (getStoreAsHtml() &&
3661 (strcasecmp(protoName, "NurbsPatchSurface") == 0))) {
3662 protoName = "";
3663 protoName += "NurbsSurface";
3664 }
3665 if (m_protos.hasKey(protoName))
3666 proto = m_protos[protoName];
3667 else if (getStoreAsHtml()) {
3668 // X3DOM users tend to use low case namenames
3669 ProtoMap::Chain::Iterator *j;
3670 for (int i = 0; i < m_protos.width(); i++)
3671 for (j = m_protos.chain(i).first(); j != NULL; j = j->next())
3672 if (strcasecmp(j->item()->getKey(), protoName) == 0) {
3673 proto = m_protos[j->item()->getKey()];
3674 break;
3675 }
3676 if (proto == NULL)
3677 return NULL;
3678 } else
3679 return NULL;
3680 if (TheApp->getCoverMode() && proto->isExtensionProto(FF_COVER_ONLY)) {
3681 proto = proto->getNode(0)->getProto();
3682 proto->setScene(this);
3683 }
3684 if (TheApp->getKambiMode() && proto->isExtensionProto(FF_KAMBI_ONLY)) {
3685 proto = proto->getNode(0)->getProto();
3686 proto->setScene(this);
3687 }
3688 if (TheApp->getX3domMode() && proto->isExtensionProto(FF_X3DOM_ONLY)) {
3689 proto = proto->getNode(0)->getProto();
3690 proto->setScene(this);
3691 }
3692 return proto;
3693 }
3694
3695 bool
validRoute(Node * src,int eventOut,Node * dst,int eventIn)3696 Scene::validRoute(Node *src, int eventOut, Node *dst, int eventIn)
3697 {
3698 if ((src == NULL) || (dst == NULL))
3699 return false;
3700
3701 bool onlyOneConnectAnything = false;
3702 // "connect anything" route of Script/ShaderNode (eventOut will be created)
3703 if (src->isNodeWithAdditionalEvents())
3704 if (eventOut == src->getProto()->getNumEventOuts())
3705 onlyOneConnectAnything = true;
3706
3707 // "connect anything" route of Script/ShaderNode (eventIn will be created)
3708 if (dst->isNodeWithAdditionalEvents())
3709 if (eventIn == dst->getProto()->getNumEventIns()) {
3710 if (onlyOneConnectAnything)
3711 onlyOneConnectAnything = false;
3712 else
3713 onlyOneConnectAnything = true;
3714 }
3715
3716 if (onlyOneConnectAnything)
3717 return true;
3718
3719 if (eventOut < 0 || eventOut >= src->getProto()->getNumEventOuts())
3720 return false;
3721
3722 if (eventIn < 0 || eventIn >= dst->getProto()->getNumEventIns())
3723 return false;
3724
3725 if (src->getProto()->getEventOut(eventOut)->getType() !=
3726 dst->getProto()->getEventIn(eventIn)->getType())
3727 return false;
3728
3729 return true;
3730 }
3731
3732 bool
addRoute(Node * src,int eventOut,Node * dst,int eventIn,SceneView * sender)3733 Scene::addRoute(Node *src, int eventOut, Node *dst, int eventIn,
3734 SceneView *sender)
3735 {
3736 if (eventIn == -1)
3737 return true;
3738 bool x3d = isX3d();
3739
3740 RouteUpdate hint(src, eventOut, dst, eventIn);
3741
3742 src->addOutput(eventOut, dst, eventIn);
3743 dst->addInput(eventIn, src, eventOut);
3744
3745 bool ret = true;
3746 if (!validRoute(src, eventOut, dst, eventIn))
3747 ret = false;
3748 Proto *srcProto = src->getProto();
3749 if ((eventOut != srcProto->getNumEventOuts()) &&
3750 (isInvalidElement(srcProto->getEventOut(eventOut))))
3751 ret = false;
3752 Proto *dstProto = dst->getProto();
3753 if (isInvalidElement(dstProto->getEventIn(eventIn)))
3754 ret = false;
3755 if (!ret) {
3756 swDebugf("invalid ROUTE %s.%s To %s.%s\n",
3757 (const char *)src->getProto()->getName(x3d),
3758 (const char *)src->getProto()->getEventOut(eventOut)->getName(x3d),
3759 (const char *)dst->getProto()->getName(x3d),
3760 (const char *)dst->getProto()->getEventIn(eventIn)->getName(x3d));
3761 return false;
3762 }
3763
3764 // try to copy a exposedField value or field of a eventIn
3765 // to the first value of a Interpolator
3766
3767 int field = -1;
3768 bool isFlag = false;
3769
3770 // is this dst field an ExposedField?
3771 ExposedField *e = dst->getProto()->getEventIn(eventIn)->getExposedField();
3772 if (e) {
3773 field = e->getFieldIndex();
3774 isFlag = e->getFlags() & FF_IS;
3775 } else {
3776 // is this dst field an EventIn connected to a Field ?
3777 field = dst->getProto()->getEventIn(eventIn)->getField();
3778 isFlag = dst->getProto()->getEventIn(eventIn)->getFlags() & FF_IS;
3779 }
3780 if ((field != -1) && (!isFlag)) {
3781 Interpolator *interp = findUpstreamInterpolator(dst, field);
3782 if (interp && !((Node *)interp)->isPROTO()) {
3783 bool setValue = false;
3784 if (interp->getNumKeys() == 0)
3785 setValue = true;
3786 if (interp->getNumKeys() == 1)
3787 if (interp->getKey(0) == 0.0f)
3788 setValue = true;
3789 if (setValue) {
3790 FieldValue *value = dst->getField(field);
3791 if (value)
3792 interp->recordKey(value, true);
3793 }
3794 }
3795 }
3796 UpdateViews(sender, UPDATE_ADD_ROUTE, (Hint *) &hint);
3797
3798 return true;
3799 }
3800
3801 void
deleteRoute(Node * src,int eventOut,Node * dst,int eventIn)3802 Scene::deleteRoute(Node *src, int eventOut, Node *dst, int eventIn)
3803 {
3804 if (eventOut < 0 || eventOut >= src->getProto()->getNumEventOuts())
3805 return;
3806
3807 if (eventIn < 0 || eventIn >= dst->getProto()->getNumEventIns())
3808 return;
3809
3810 RouteUpdate hint(src, eventOut, dst, eventIn);
3811
3812 src->removeOutput(eventOut, dst, eventIn);
3813 dst->removeInput(eventIn, src, eventOut);
3814 UpdateViews(NULL, UPDATE_DELETE_ROUTE, (Hint *) &hint);
3815 }
3816
3817 void
errorf(const char * fmt,...)3818 Scene::errorf(const char *fmt, ...)
3819 {
3820 va_list ap;
3821 char buf[1024], buf2[1024];
3822 const char *url = "";
3823
3824 va_start(ap, fmt);
3825 myvsnprintf(buf, 1024, fmt, ap);
3826 if (TheApp->getImportFile() != NULL)
3827 url = TheApp->getImportFile();
3828 mysnprintf(buf2, 1024, "%s %d: %s", url, lineno, buf);
3829 #ifndef _WIN32
3830 fprintf(stderr, "%s", buf2);
3831 fflush(stderr);
3832 #endif
3833 m_errors += buf2;
3834 }
3835
3836 void
invalidNode(const char * name)3837 Scene::invalidNode(const char *name)
3838 {
3839 errorf("invalid DEF name \"%s\"\n", name);
3840 }
3841
3842 void
invalidField(const char * node,const char * field)3843 Scene::invalidField(const char *node, const char *field)
3844 {
3845 errorf("node \"%s\" has no field \"%s\"\n", node, field);
3846 }
3847
3848 #ifdef NURBS_CURVE_ANIMATION_COMPATIBILTY
replaceNurbsCurveAnimation(Node * node,void * data)3849 static bool replaceNurbsCurveAnimation(Node *node, void *data)
3850 {
3851 if (node == NULL)
3852 return true;
3853 Proto *proto = node->getProto();
3854 if (proto == NULL)
3855 return true;
3856 Scene *scene = node->getScene();
3857 if (scene == NULL)
3858 return true;
3859 bool x3d = scene->isX3d();
3860 int nurbsCurveField;
3861 if (strcmp(proto->getName(x3d), "NurbsCurveAnimation") == 0) {
3862 if ((proto->lookupField("rotationAxesInterpolator", x3d) != -1) &&
3863 (proto->lookupField("timeWarpScalarInterpolator", x3d) != -1) &&
3864 (nurbsCurveField = proto->lookupField("nurbsCurve", x3d) != -1)) {
3865 FieldValue *value = node->getField(nurbsCurveField);
3866 if (value == NULL)
3867 return true;
3868 NodeNurbsCurve *curve = (NodeNurbsCurve *)
3869 ((SFNode *)value)->getValue();
3870 if (curve == NULL)
3871 return true;
3872 Node *curveAnimation = curve->toCurveAnimation();
3873 if (curveAnimation != NULL) {
3874 Node *fromNode = node;
3875 Node *toNode = curveAnimation;
3876 Proto *fromProto = fromNode->getProto();
3877 Proto *toProto = toNode->getProto();
3878 int fromFractionEvent = fromProto->lookupEventIn("set_fraction",
3879 x3d);
3880 int toFractionEvent = toProto->lookupEventIn("set_fraction",
3881 x3d);
3882 if ((fromFractionEvent == -1) || (toFractionEvent == -1))
3883 return true;
3884 SocketList::Iterator *i = NULL;
3885 CommandList *list = NULL;
3886
3887 for (i = fromNode->getInput(fromFractionEvent).first();
3888 i != NULL; i = i->next()) {
3889 if (list == NULL)
3890 list = new CommandList();
3891 list->append(new RouteCommand(i->item().getNode(),
3892 i->item().getField(), toNode,
3893 toFractionEvent));
3894 }
3895
3896 int fromPosEvent = fromProto->lookupEventOut("position_changed",
3897 x3d);
3898 int toPosEvent = toProto->lookupEventOut("position_changed",
3899 x3d);
3900 if ((fromPosEvent == -1) || (toPosEvent == -1))
3901 return true;
3902 for (i = fromNode->getOutput(fromPosEvent).first(); i != NULL;
3903 i = i->next()) {
3904 if (list == NULL)
3905 list = new CommandList();
3906 list->append(new RouteCommand(toNode, toPosEvent,
3907 i->item().getNode(),
3908 i->item().getField()));
3909 }
3910
3911 int fromOriEvent = fromProto->lookupEventOut("orientation_changed",
3912 x3d);
3913 int toOriEvent = toProto->lookupEventOut("orientation_changed",
3914 x3d);
3915 if ((fromOriEvent == -1) || (toOriEvent == -1))
3916 return true;
3917 for (i = fromNode->getOutput(fromOriEvent).first(); i != NULL;
3918 i = i->next()) {
3919 if (list == NULL)
3920 list = new CommandList();
3921 list->append(new RouteCommand(toNode, toOriEvent,
3922 i->item().getNode(),
3923 i->item().getField()));
3924 }
3925
3926 if (list) scene->execute(list);
3927
3928 MyString oldName = node->getName();
3929 if (oldName.length() > 0) {
3930 scene->undef(oldName);
3931 scene->def(oldName, curveAnimation);
3932 }
3933 Node *parent = node->getParent();
3934 int parentField = node->getParentField();
3935 MoveCommand *command;
3936 command = new MoveCommand(node, parent, parentField, NULL, -1);
3937 command->execute();
3938 command = new MoveCommand(curveAnimation, NULL, -1,
3939 parent, parentField);
3940 command->execute();
3941 }
3942 }
3943 }
3944 return true;
3945 }
3946 #endif
3947
3948 const char *
parse(FILE * f,Node * target,int field,int scan)3949 Scene::parse(FILE *f, Node* target, int field, int scan)
3950 {
3951 bool canRewind = true;
3952 if (isatty(fileno(f)))
3953 canRewind = false;
3954 #ifdef HAVE_LIBZ
3955 inputFile = gzdopen(fileno(f),"rb");
3956 #else
3957 inputFile = f;
3958 #endif
3959 scene = this;
3960 targetNode = target;
3961 targetField = field;
3962 scanFor = scan;
3963 lineno = 1;
3964 m_errors = "";
3965 m_isParsing = true;
3966 m_writeFlags = m_writeFlags & ~(X3DV | X3D_XML);
3967 bool isXml = false;
3968 bool isOther = false;
3969 if (canRewind) {
3970 int firstChar = -1;
3971 int end;
3972 do {
3973 #ifdef HAVE_LIBZ
3974 end = -1;
3975 firstChar = gzgetc(inputFile);
3976 #else
3977 end = EOF;
3978 firstChar = getc(inputFile);
3979 #endif
3980 if (firstChar == '<')
3981 isXml = true;
3982 else if (!isspace(firstChar))
3983 isOther = true;
3984 } while (isspace(firstChar) && (firstChar != end));
3985 #ifdef HAVE_LIBZ
3986 gzrewind(inputFile);
3987 #else
3988 rewind(inputFile);
3989 #endif
3990 } else {
3991 // no rewind possible, check current mode
3992 isXml = isX3dXml();
3993 isOther = !isXml;
3994 }
3995 #ifdef HAVE_LIBEXPAT
3996 if (isXml)
3997 parseX3d();
3998 if (isOther)
3999 #endif
4000 yyparse();
4001 #ifdef NURBS_CURVE_ANIMATION_COMPATIBILTY
4002 if (targetNode)
4003 targetNode->doWithBranch(replaceNurbsCurveAnimation, NULL);
4004 else if (getRoot())
4005 getRoot()->doWithBranch(replaceNurbsCurveAnimation, NULL);
4006 #endif
4007 m_isParsing = false;
4008 updateViewpoint();
4009 return m_errors;
4010 }
4011
4012 void
add(Command * cmd)4013 Scene::add(Command *cmd)
4014 {
4015 m_undoStack.push(cmd);
4016
4017 while (!m_redoStack.empty()) {
4018 delete m_redoStack.pop();
4019 }
4020 }
4021
4022
4023 void
addNextCommand(void)4024 Scene::addNextCommand(void)
4025 {
4026 m_undoStack.push(new NextCommand());
4027 }
4028
4029 void
execute(Command * cmd,SceneView * sender)4030 Scene::execute(Command *cmd, SceneView *sender)
4031 {
4032 cmd->execute(sender);
4033 add(cmd);
4034 }
4035
4036 void
backupFieldsStart(void)4037 Scene::backupFieldsStart(void)
4038 {
4039 // check for forbidden recursive usage or not missing backupFieldsDone()
4040 assert(m_backupCommandList == NULL);
4041 m_backupCommandList = new CommandList();
4042 }
4043
4044 void
backupFieldsAppend(Node * node,int field)4045 Scene::backupFieldsAppend(Node *node, int field)
4046 {
4047 if (isRecording()) {
4048 Interpolator *interp = findUpstreamInterpolator(node, field);
4049
4050 if (interp) {
4051 interp->backup(m_backupCommandList);
4052 }
4053 }
4054 m_backupCommandList->append(new FieldCommand(node, field));
4055 }
4056
4057 void
backupFieldsDone(void)4058 Scene::backupFieldsDone(void)
4059 {
4060 add(m_backupCommandList);
4061 m_backupCommandList = NULL;
4062 }
4063
4064 void
backupField(Node * node,int field)4065 Scene::backupField(Node *node, int field)
4066 {
4067 backupFieldsStart();
4068 backupFieldsAppend(node, field);
4069 backupFieldsDone();
4070 }
4071
4072 Interpolator *
findUpstreamInterpolator(const Node * node,int field) const4073 Scene::findUpstreamInterpolator(const Node *node, int field) const
4074 {
4075 // is this field an ExposedField?
4076 int eventIn = -1;
4077 Field *f = node->getProto()->getField(field);
4078 ExposedField *e = f->getExposedField();
4079 if (e)
4080 eventIn = e->getEventIn();
4081 else if (f->getEventIn() != -1)
4082 eventIn = f->getEventIn();
4083 if (eventIn != -1) {
4084 const SocketList::Iterator *i;
4085
4086 // check for interpolator routed to the corresponding EventIn;
4087
4088 for (i = node->getInput(eventIn).first(); i != NULL; i = i->next()) {
4089 if ((i->item().getNode()->getMaskedNodeClass() ==
4090 INTERPOLATOR_NODE) && i->item().getNode()->isInterpolator())
4091 return ((Interpolator *)i->item().getNode());
4092 }
4093 }
4094 return NULL;
4095
4096 }
4097
4098 void
setField(Node * node,int field,FieldValue * value)4099 Scene::setField(Node *node, int field, FieldValue *value)
4100 {
4101 if (isRecording()) {
4102 Interpolator *interp = findUpstreamInterpolator(node, field);
4103
4104 if (interp) {
4105 interp->recordKey(value, isRunning());
4106 }
4107 }
4108 node->setField(field, value);
4109 if (TheApp->is4Catt()) {
4110 if ((field != -1) && (node->getSolidField() == field)) {
4111 node->generateTreeLabel();
4112 NodeUpdate *hint= new NodeUpdate(node, NULL, 0);
4113 UpdateViews(NULL, UPDATE_SOLID_CHANGED, (Hint*) hint);
4114 }
4115 }
4116 if (node->getType() == VRML_TIME_SENSOR) {
4117 NodeTimeSensor *nodeTimeSensor = (NodeTimeSensor *) node;
4118 nodeTimeSensor->updateStart(field, value, m_currentTime);
4119 }
4120 if (!TheApp->getDrawAvoided())
4121 OnFieldChange(node, field);
4122 }
4123
4124 void
deleteLastNextCommand(void)4125 Scene::deleteLastNextCommand(void)
4126 {
4127 if (m_undoStack.empty())
4128 return;
4129 Command *command = m_undoStack.peek();
4130 if (command->getType() == NEXT_COMMAND)
4131 command = m_undoStack.pop();
4132 }
4133
4134 int
canUndo() const4135 Scene::canUndo() const
4136 {
4137 if (m_undoStack.empty())
4138 return 0;
4139 int top = m_undoStack.getTop();
4140 Command *command = m_undoStack.peek(top);
4141 if (command->getType() == NEXT_COMMAND)
4142 return (top > 1);
4143 return (top > 1);
4144 }
4145
4146 int
canRedo() const4147 Scene::canRedo() const
4148 {
4149 if (m_redoStack.empty())
4150 return 0;
4151 int top = m_redoStack.getTop();
4152 Command *command = m_redoStack.peek(top);
4153 if (command->getType() == NEXT_COMMAND)
4154 return (top > 1);
4155 return (top > 1);
4156 }
4157
4158 void
undo()4159 Scene::undo()
4160 {
4161 if (m_undoStack.empty()) {
4162 assert(0);
4163 return;
4164 }
4165
4166 Command *change = m_undoStack.pop();
4167 if (change->getType() != NEXT_COMMAND) {
4168 change->undo();
4169 m_redoStack.push(change);
4170 } else if (m_undoStack.peek()->getType() == NEXT_COMMAND) {
4171 // ignore second NEXT_COMMAND
4172 change = m_undoStack.pop();
4173 m_redoStack.push(change);
4174 }
4175 while (!m_undoStack.empty()) {
4176 change = m_undoStack.pop();
4177 if (change->getType() == NEXT_COMMAND) {
4178 m_redoStack.push(change);
4179 break;
4180 } else {
4181 change->undo();
4182 m_redoStack.push(change);
4183 }
4184 }
4185 }
4186
4187 void
redo()4188 Scene::redo()
4189 {
4190 if (m_redoStack.empty()) {
4191 assert(0);
4192 return;
4193 }
4194
4195 Command *change = m_redoStack.pop();
4196 if (change->getType() != NEXT_COMMAND) {
4197 change->execute();
4198 m_undoStack.push(change);
4199 } else if (m_redoStack.peek()->getType() == NEXT_COMMAND) {
4200 // ignore second NEXT_COMMAND
4201 change = m_redoStack.pop();
4202 m_undoStack.push(change);
4203 }
4204
4205 while (!m_redoStack.empty()) {
4206 change = m_redoStack.pop();
4207 if (change->getType() == NEXT_COMMAND) {
4208 m_undoStack.push(change);
4209 break;
4210 } else {
4211 change->execute();
4212 m_undoStack.push(change);
4213 }
4214 }
4215 }
4216
4217 void
drawScene(bool pick,int x,int y,double width,double height,Node * root,bool useUpdate,float scaleX,float scaleY)4218 Scene::drawScene(bool pick, int x, int y, double width, double height,
4219 Node *root, bool useUpdate, float scaleX, float scaleY)
4220 {
4221 m_width = width;
4222 m_height = height;
4223
4224 m_drawViewPorts = (root != getRoot());
4225 if (root == NULL) {
4226 root = getRoot();
4227 m_drawViewPorts = false;
4228 }
4229 GLint v[4];
4230 float aspect;
4231
4232 glGetIntegerv(GL_VIEWPORT, v);
4233
4234 if (v[3])
4235 aspect = (GLfloat)v[2]/v[3];
4236 else // don't divide by zero, not that we should ever run into that...
4237 aspect = 1.0f;
4238
4239 m_numLights = 0;
4240 m_numClipPlanes = 0;
4241 m_headlight = true;
4242
4243 glMatrixMode(GL_PROJECTION);
4244 glLoadIdentity();
4245 if (pick)
4246 gluPickMatrix(x, y, width, height, v);
4247 float fieldOfView = getCamera()->fov() ?
4248 RAD2DEG(getCamera()->fov()->getValue() *
4249 getUnitAngle()) : TheApp->getFixFieldOfView();
4250 if (TheApp->hasFixFieldOfView())
4251 fieldOfView = TheApp->getFixFieldOfView();
4252 gluPerspective(fieldOfView, aspect, TheApp->GetNearClippingPlaneDist(),
4253 TheApp->GetFarClippingPlaneDist());
4254
4255 if (getSelection()->getNode() &&
4256 getSelection()->getNode()->getType() == X3D_ORTHO_VIEWPOINT) {
4257 glMatrixMode(GL_PROJECTION);
4258 glLoadIdentity();
4259 float dim = 4; // ???
4260 glOrtho(-dim * aspect, dim * aspect, -dim, dim,
4261 TheApp->GetNearClippingPlaneDist(),
4262 TheApp->GetFarClippingPlaneDist());
4263 }
4264
4265 glMatrixMode(GL_MODELVIEW);
4266 glLoadIdentity();
4267
4268 if (!m_drawViewPorts) {
4269 glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
4270 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
4271 }
4272
4273 glEnable(GL_LIGHTING);
4274 glEnable(GL_NORMALIZE);
4275 glEnable(GL_DEPTH_TEST);
4276 glDepthFunc(GL_LEQUAL);
4277 if (TheApp->getRenderFaster()) {
4278 glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
4279 glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
4280 glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
4281 } else {
4282 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
4283 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
4284 glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
4285 }
4286
4287 // no scene ambient light, please
4288 GLint zero[4] = { 0, 0, 0, 0 };
4289 glLightModeliv(GL_LIGHT_MODEL_AMBIENT, zero);
4290
4291 double scale = getUnitLength();
4292 if (scale > 0)
4293 glScaled(1 / scale, 1 / scale, 1 / scale);
4294
4295 glScalef(scaleX, scaleY, 1.0f);
4296
4297 // first pass: pre-draw traversal
4298 // enable PointLights and SpotLights; pick up ViewPoints, Fogs.
4299 // Backgrounds and TimeSensors
4300
4301 glPushMatrix();
4302
4303 bool viewpointFlag = getViewpointUpdated();
4304
4305 applyCamera();
4306
4307 m_viewpointUpdated = viewpointFlag;
4308
4309 glPopMatrix();
4310
4311 m_timeSensors.resize(0);
4312
4313 m_headlightIsSet = false;
4314 m_defaultViewpoint->preDraw();
4315 root->preDraw();
4316
4317 if (m_currentFog)
4318 m_currentFog->apply();
4319
4320 if (useUpdate)
4321 updateTime();
4322
4323 // second pass: main drawing traversal
4324
4325 glPushMatrix();
4326 if (m_headlight)
4327 enableHeadlight();
4328 glPushName(PICKED_NODE);
4329 if (m_backgrounds.size() > 0) {
4330 // glPushName(NO_HANDLE); // FIXME: can't pick backgrounds, yet
4331 if (m_currentBackground)
4332 ((NodeBackground *) m_currentBackground)->apply();
4333 // glPopName();
4334 }
4335 applyCamera();
4336 if (m_xrayRendering)
4337 glDepthMask(GL_FALSE);
4338 else
4339 glDepthMask(GL_TRUE);
4340 glDepthFunc(GL_LESS);
4341 root->draw(RENDER_PASS_NON_TRANSPARENT);
4342 glEnable(GL_BLEND);
4343 glDepthFunc(GL_LEQUAL);
4344 root->draw(RENDER_PASS_TRANSPARENT);
4345
4346 for (int i = 0; i < m_numLights; i++) {
4347 glDisable((GLenum) (GL_LIGHT0 + i));
4348 }
4349 m_numLights = 0;
4350
4351 for (int i = 0; i < m_numClipPlanes; i++) {
4352 glDisable((GLenum) (GL_CLIP_PLANE0 + i));
4353 }
4354 m_numClipPlanes = 0;
4355
4356 glDisable(GL_FOG);
4357 glPopMatrix();
4358
4359 // post-draw phase
4360 // draw handles
4361
4362 if (m_headlight)
4363 enableHeadlight();
4364
4365 if (getSelection()->getNode() &&
4366 getSelection()->getNode()->getType() != X3D_ORTHO_VIEWPOINT) {
4367 glPushMatrix();
4368 applyCamera();
4369 glLoadName(PICKED_RIGID_BODY_HANDLE);
4370 drawHandles(root, true);
4371 glPopMatrix();
4372
4373 glPushMatrix();
4374 applyCamera();
4375 glLoadName(PICKED_HANDLE);
4376 drawHandles(root, false);
4377 glPopMatrix();
4378 }
4379 glDisable(GL_LIGHT0);
4380 glPopName();
4381 TheApp->printRenderErrors();
4382
4383 m_numDraw++;
4384 }
4385
4386 void
resetPerspective(void)4387 Scene::resetPerspective(void)
4388 {
4389 GLint v[4];
4390 float aspect;
4391
4392 glGetIntegerv(GL_VIEWPORT, v);
4393
4394 if (v[3])
4395 aspect = (GLfloat)v[2]/v[3];
4396 else // don't divide by zero, not that we should ever run into that...
4397 aspect = 1.0f;
4398
4399 glMatrixMode(GL_PROJECTION);
4400 glLoadIdentity();
4401 float fieldOfView = RAD2DEG(getCamera()->fov()->getValue() *
4402 getUnitAngle());
4403 if (TheApp->hasFixFieldOfView())
4404 fieldOfView = TheApp->getFixFieldOfView();
4405 gluPerspective(fieldOfView, aspect, TheApp->GetNearClippingPlaneDist(),
4406 TheApp->GetFarClippingPlaneDist());
4407 }
4408
4409 void
draw3dCursor(int x,int y)4410 Scene::draw3dCursor(int x, int y)
4411 {
4412 if (!use3dCursor())
4413 return;
4414
4415 float objX;
4416 float objY;
4417 float objZ;
4418
4419 float eyeposition=0;
4420 float eyeangle=0;
4421 float nearPlane=TheApp->GetNearClippingPlaneDist();
4422
4423 glPushMatrix();
4424
4425 if (TheApp->useStereo())
4426 {
4427 // inexact "toe in" stereo method
4428 if (TheApp->getEyeMode()==EM_RIGHT)
4429 {
4430 eyeposition= - TheApp->getEyeHalfDist();
4431 eyeangle= - TheApp->getEyeAngle();
4432 }
4433 else if (TheApp->getEyeMode()==EM_LEFT)
4434 {
4435 eyeposition= + TheApp->getEyeHalfDist();
4436 eyeangle= + TheApp->getEyeAngle();
4437 }
4438 }
4439 glTranslatef(eyeposition, 0, 0);
4440 glRotatef(eyeangle, 0,1,0);
4441
4442 GLint viewport[4];
4443 glGetIntegerv(GL_VIEWPORT, viewport);
4444
4445 float xSize = (viewport[2] - viewport[0]) * TheApp->GetEyeAngleFactor() *
4446 (viewport[3] - viewport[1]) / (viewport[2] - viewport[0]);
4447
4448 unProjectPoint(x - eyeposition * xSize, y, nearPlane, &objX, &objY, &objZ);
4449
4450 glPushAttrib(GL_ENABLE_BIT);
4451 glDisable(GL_LIGHTING);
4452 glDisable(GL_TEXTURE_2D);
4453 glEnable(GL_LINE_SMOOTH);
4454 glDisable(GL_BLEND);
4455 glLineWidth(TheApp->Get3dCursorWidth());
4456
4457 if (TheApp->isAnaglyphStereo())
4458 Util::myGlColor3f(1, 1, 1);
4459 else
4460 Util::myGlColor3f(0, 1, 0);
4461 glBegin(GL_LINE_STRIP);
4462 glVertex3f(objX + TheApp->Get3dCursorLength(), -objY, objZ);
4463 glVertex3f(objX - TheApp->Get3dCursorLength(), -objY, objZ);
4464 glEnd();
4465 glBegin(GL_LINE_STRIP);
4466 glVertex3f(objX, -objY + TheApp->Get3dCursorLength(), objZ);
4467 glVertex3f(objX, -objY - TheApp->Get3dCursorLength(), objZ);
4468 glEnd();
4469 glEnable(GL_LIGHTING);
4470 glLineWidth(1);
4471 glPopAttrib();
4472
4473 glPopMatrix();
4474 }
4475
4476 bool
isVerticesOrNurbs(void)4477 Scene::isVerticesOrNurbs(void)
4478 {
4479 Node *selection = NULL;
4480 if (getSelection())
4481 selection = getSelection()->getNode();
4482 bool isNurbs = selection && ((selection->getType() == VRML_NURBS_SURFACE) ||
4483 (selection->getType() == VRML_NURBS_CURVE) ||
4484 (selection->getType() == VRML_NURBS_CURVE_2D) ||
4485 (selection->getType() == DUNE_CURVE_ANIMATION));
4486 if ((getSelectionMode() == SELECTION_MODE_VERTICES) || isNurbs)
4487 return true;
4488 return false;
4489 }
4490
4491 void
draw3dBoundingBox(int xfrom,int yfrom,int xto,int yto)4492 Scene::draw3dBoundingBox(int xfrom, int yfrom, int xto, int yto)
4493 {
4494 float objXfrom;
4495 float objYfrom;
4496 float objZfrom;
4497
4498 float objXto;
4499 float objYto;
4500 float objZto;
4501
4502 float eyeposition = 0;
4503 float eyeangle = 0;
4504 float nearPlane=TheApp->GetNearClippingPlaneDist();
4505
4506 glPushMatrix();
4507
4508 if (TheApp->useStereo()) {
4509 // inexact "toe in" stereo method
4510 if (TheApp->getEyeMode()==EM_RIGHT)
4511 {
4512 eyeposition= - TheApp->getEyeHalfDist();
4513 eyeangle= - TheApp->getEyeAngle();
4514 }
4515 else if (TheApp->getEyeMode()==EM_LEFT)
4516 {
4517 eyeposition= + TheApp->getEyeHalfDist();
4518 eyeangle= + TheApp->getEyeAngle();
4519 }
4520 }
4521 glTranslatef(eyeposition, 0, 0);
4522 glRotatef(eyeangle, 0,1,0);
4523
4524 GLint viewport[4];
4525 glGetIntegerv(GL_VIEWPORT, viewport);
4526
4527 float xSize = (viewport[2] - viewport[0]) * TheApp->GetEyeAngleFactor() *
4528 (viewport[3] - viewport[1]) / (viewport[2] - viewport[0]);
4529
4530 unProjectPoint(xfrom - eyeposition * xSize, yfrom, nearPlane,
4531 &objXfrom, &objYfrom, &objZfrom);
4532 unProjectPoint(xto - eyeposition * xSize, yto, nearPlane,
4533 &objXto, &objYto, &objZto);
4534
4535 glPushAttrib(GL_ENABLE_BIT);
4536 glDisable(GL_LIGHTING);
4537 glDisable(GL_TEXTURE_2D);
4538 glEnable(GL_LINE_SMOOTH);
4539 glDisable(GL_BLEND);
4540 glLineWidth(TheApp->Get3dCursorWidth());
4541
4542 if (TheApp->isAnaglyphStereo())
4543 Util::myGlColor3f(1, 1, 1);
4544 else
4545 Util::myGlColor3f(0, 1, 0);
4546
4547 glBegin(GL_LINE_STRIP);
4548 glVertex3f(objXfrom, -objYfrom, objZfrom);
4549 glVertex3f(objXto, -objYfrom, objZfrom);
4550 glEnd();
4551 glBegin(GL_LINE_STRIP);
4552 glVertex3f(objXto, -objYfrom, objZfrom);
4553 glVertex3f(objXto, -objYto, objZfrom);
4554 glEnd();
4555 glBegin(GL_LINE_STRIP);
4556 glVertex3f(objXto, -objYto, objZfrom);
4557 glVertex3f(objXfrom, -objYto, objZfrom);
4558 glEnd();
4559 glBegin(GL_LINE_STRIP);
4560 glVertex3f(objXfrom, -objYto, objZfrom);
4561 glVertex3f(objXfrom, -objYfrom, objZfrom);
4562 glEnd();
4563
4564 glEnable(GL_LIGHTING);
4565 glLineWidth(1);
4566 glPopAttrib();
4567
4568 glPopMatrix();
4569 }
4570
4571 Path *
pick(int x,int y,float width,float height)4572 Scene::pick(int x, int y, float width, float height)
4573 {
4574 float xwidth = PICK_REGION_SIZE * TheApp->GetHandleSize();
4575 if (width != 0)
4576 xwidth = width;
4577 float yheight = PICK_REGION_SIZE * TheApp->GetHandleSize();
4578 if (height != 0)
4579 yheight = height;
4580 GLuint pickBuffer[PICK_BUFFER_SIZE];
4581 #ifdef DEBUG
4582 for (GLuint i = 0; i < PICK_BUFFER_SIZE; i++)
4583 pickBuffer[i] = 0;
4584 #endif
4585 glSelectBuffer(PICK_BUFFER_SIZE, pickBuffer);
4586 glRenderMode(GL_SELECT);
4587 glInitNames();
4588
4589 TheApp->setEyeMode(EM_NONE);
4590 drawScene(true, x, y, xwidth, yheight);
4591
4592 GLint hits = glRenderMode(GL_RENDER);
4593 Path *path = NULL;
4594 if (hits < 0) // overflow flag has been set, ignore
4595 hits = - hits;
4596 if (hits)
4597 path = processHits(hits, pickBuffer, (width != 0) && (height != 0));
4598 if (path != NULL) {
4599 return path;
4600 } else {
4601 return new Path(NULL, 0, this);
4602 }
4603 }
4604
4605 Path *
processHits(GLint hits,GLuint * pickBuffer,bool selectMultipleHandles)4606 Scene::processHits(GLint hits, GLuint *pickBuffer, bool selectMultipleHandles)
4607 {
4608 GLuint *glPath = NULL;
4609 int glPathLen = 0;
4610 unsigned depth = UINT_MAX;
4611 unsigned handleDepth = 0;
4612 bool pickedNode = false;
4613 int handle = -1;
4614
4615 for (int i = 0; i < hits; i++) {
4616 unsigned numNames = *pickBuffer++;
4617 /* unsigned minDepth = * */ pickBuffer++;
4618 unsigned maxDepth = *pickBuffer++;
4619 if (*pickBuffer == PICKED_NODE) {
4620 if (depth >= maxDepth) {
4621 pickedNode = true;
4622 glPath = pickBuffer + 1;
4623 glPathLen = numNames - 1;
4624 depth = maxDepth;
4625 }
4626 } else if (*pickBuffer == PICKED_RIGID_BODY_HANDLE) {
4627 if (m_rigidBodyHandleNode == NULL)
4628 return NULL;
4629 handle = pickBuffer[numNames - 1];
4630 return m_rigidBodyHandleNode->getPath();
4631 } else if (*pickBuffer == PICKED_HANDLE) {
4632 bool isCoord = COORDINATE_NODE ==
4633 getSelection()->getNode()->getProto()->getNodeClass();
4634
4635 bool isVertices = getSelectionMode() == SELECTION_MODE_VERTICES ||
4636 getSelectionMode() ==
4637 SELECTION_HANIM_JOINT_WEIGHT;
4638 if ((!isCoord) || isVertices || (handleDepth <= maxDepth)) {
4639 if (pickBuffer[numNames - 1] != NO_HANDLE) {
4640 pickedNode = false;
4641 glPath = pickBuffer + 1;
4642 glPathLen = numNames - 2;
4643 handle = pickBuffer[numNames - 1];
4644 handleDepth = maxDepth;
4645 }
4646 if (selectMultipleHandles) {
4647 if (m_deselect)
4648 removeSelectedHandle(handle);
4649 else
4650 addSelectedHandle(handle);
4651 }
4652 depth = maxDepth;
4653 }
4654 } else if (*pickBuffer == PICKED_3DCURSOR) {
4655 return NULL;
4656 } else {
4657 return NULL;
4658 }
4659 pickBuffer += numNames;
4660 }
4661 if (pickedNode)
4662 m_lastSelectedHandle = -1;
4663 else if (handle != -1)
4664 if (!selectMultipleHandles) {
4665 if (m_deselect)
4666 removeSelectedHandle(handle);
4667 else
4668 setSelectedHandle(handle);
4669 }
4670
4671 if (glPath == NULL)
4672 return NULL;
4673
4674 bool insideProto = false;
4675 Path *path = new Path((int *) glPath, glPathLen, this, true,
4676 true);
4677 if (path->getNode()->isDeepInsideProto()) {
4678 insideProto = true;
4679 delete path;
4680 }
4681 return new Path((int *) glPath, glPathLen, this, insideProto);
4682 }
4683
4684 void
transform(const Path * path)4685 Scene::transform(const Path *path)
4686 {
4687 assert(path != NULL);
4688 applyCamera();
4689 const NodeList *nodes = path->getNodes();
4690 for (long i = 0; i < nodes->size() - 1; i++) {
4691 nodes->get(i)->transform();
4692 }
4693 }
4694
searchTransform(void)4695 Path* Scene::searchTransform(void)
4696 {
4697 Path* transform = new Path(*m_selection);
4698 Node *trans = transform->getNode();
4699 while (trans->getType() != VRML_TRANSFORM && trans->hasParent()) {
4700 trans = trans->getParent();
4701 if (trans == getRoot())
4702 return NULL;
4703 }
4704 return searchTransform(trans->getPath());
4705 }
4706
4707 // search for a Transform node in a path
4708 // return new path to Transform node or NULL if not found
4709
searchTransform(Path * transform)4710 Path* Scene::searchTransform(Path *transform)
4711 {
4712 if (transform != NULL) {
4713 if (transform->getNode()->getType() == VRML_TRANSFORM)
4714 return transform;
4715 while (transform->getNode() != m_root &&
4716 transform->getNode()->hasParent()) {
4717 transform = new Path(*(transform->getNode()->getParent()->getPath()));
4718 if (transform->getNode()->getType() == VRML_TRANSFORM)
4719 break;
4720 // delete old_transform; // bug: deleting a path cause a crash
4721 }
4722 if (transform->getNode()==m_root)
4723 transform = NULL;
4724 }
4725 return transform;
4726 }
4727
checkHandleParentsForRigidBody(Node * node,void * data)4728 static bool checkHandleParentsForRigidBody(Node *node, void *data) {
4729 Scene *scene = (Scene *)data;
4730 if (node == NULL)
4731 return true;
4732 if (node->getType() == X3D_RIGID_BODY)
4733 if (node->isInScene(scene))
4734 scene->setRigidBodyHandleNode(node);
4735 return true;
4736 }
4737
4738 void
finishDrawHandles(void)4739 Scene::finishDrawHandles(void)
4740 {
4741 int glPushCount = 0;
4742 glGetIntegerv(GL_NAME_STACK_DEPTH, &glPushCount);
4743 glPushCount--;
4744 for (int i = 0; i < glPushCount; i++)
4745 glPopName();
4746 }
4747
4748 void
drawHandles(Node * root,bool drawRigidBodyHandles)4749 Scene::drawHandles(Node *root, bool drawRigidBodyHandles)
4750 {
4751 if (root != getRoot())
4752 return;
4753 glDisable(GL_DEPTH_TEST);
4754 switch (TheApp->GetHandleMode()) {
4755 case HM_NONE:
4756 break;
4757 case HM_TREE:
4758 // draw handles for all nodes in the current selection path
4759 if ((m_selection != NULL) && (!drawRigidBodyHandles)) {
4760 glPushMatrix();
4761 int len = m_selection->getPathLen();
4762 const int *path = m_selection->getPath();
4763 Node *node = root;
4764 for (int i = 0; i < len;) {
4765 int field = path[i++];
4766 if (i >= len)
4767 break;
4768 node = m_selection->getNextNode(node, field, i);
4769 if (node == NULL)
4770 break;
4771 glPushName(field);
4772 glPushName(path[i++]);
4773 node->drawHandles();
4774 node->transform();
4775 }
4776 glPopMatrix();
4777 }
4778 break;
4779 case HM_SELECTED:
4780 if (m_selection != NULL) {
4781 glPushMatrix();
4782 int len = m_selection->getPathLen();
4783 const int *path = m_selection->getPath();
4784 Node *node = root;
4785 Node *handlenode = root;
4786 Node *lastnode = root;
4787 m_rigidBodyHandleNode = NULL;
4788 for (int i = 0; i < len;) {
4789 int field = path[i++];
4790 if (i >= len) {
4791 break;
4792 }
4793 Node *newNode = m_selection->getNextNode(node, field, i++);
4794 if (newNode == NULL) {
4795 finishDrawHandles();
4796 break;
4797 } else
4798 node = newNode;
4799 /* search last transform node in path */
4800 if (node->getType() == VRML_TRANSFORM)
4801 handlenode = node;
4802 // search for a RigidBody node in the Parents of a
4803 // X3DNBodyCollidableNode
4804 if (node->matchNodeClass(BODY_COLLIDABLE_NODE)) {
4805 m_rigidBodyHandleNode = NULL;
4806 node->doWithParents(checkHandleParentsForRigidBody, this);
4807 if (m_rigidBodyHandleNode != NULL)
4808 handlenode = node;
4809 }
4810 }
4811 lastnode = node;
4812 node = root;
4813 for (int i = 0; i < len;) {
4814 int field = path[i++];
4815 if (i >= len)
4816 break;
4817 node = m_selection->getNextNode(node, field, i);
4818 if (node == NULL) {
4819 finishDrawHandles();
4820 break;
4821 }
4822 glPushName(field);
4823 glPushName(path[i++]);
4824 /* display last transform node in path */
4825 if ((node == handlenode) || (node == lastnode)) {
4826 if ((node == handlenode) &&
4827 (m_rigidBodyHandleNode != NULL)) {
4828 if (drawRigidBodyHandles)
4829 m_rigidBodyHandleNode->drawHandles();
4830 } else {
4831 if (!drawRigidBodyHandles)
4832 node->drawHandles();
4833 }
4834 }
4835 if (node->getType() != X3D_RIGID_BODY)
4836 if (node->getType() != X3D_HANIM_JOINT)
4837 node->transform();
4838 }
4839 glPopMatrix();
4840 }
4841 break;
4842 case HM_ALL:
4843 if (!drawRigidBodyHandles)
4844 drawHandlesRec(root);
4845 break;
4846 }
4847 finishDrawHandles();
4848 }
4849
4850 void
drawHandlesRec(Node * node,bool drawOnlyJoints) const4851 Scene::drawHandlesRec(Node *node, bool drawOnlyJoints) const
4852 {
4853 int numFields = node->getProto()->getNumFields();
4854
4855 glPushMatrix();
4856 bool draw = true;
4857 if (drawOnlyJoints)
4858 if (!node->isJoint())
4859 draw = false;
4860 if (draw)
4861 if (node->isJoint() && !node->isFirstUSE())
4862 draw = false;
4863 if (draw)
4864 node->drawHandles();
4865 node->transform();
4866 for (int i = 0; i < numFields; i++) {
4867 FieldValue *value = node->getField(i);
4868 if (value->getType() == SFNODE) {
4869 Node *child = ((SFNode *) value)->getValue();
4870 if (child) {
4871 glPushName(i);
4872 glPushName(0);
4873 drawHandlesRec(child, drawOnlyJoints);
4874 glPopName();
4875 glPopName();
4876 }
4877 } else if (value->getType() == MFNODE) {
4878 glPushName(i);
4879 glPushName(0);
4880 MFNode *v = (MFNode *) value;
4881 int n = v->getSize();
4882 for (int j = 0; j < n; j++) {
4883 glLoadName(j);
4884 drawHandlesRec(v->getValue(j), drawOnlyJoints);
4885 }
4886 glPopName();
4887 glPopName();
4888 }
4889 }
4890 glPopMatrix();
4891 }
4892
4893 void
enableHeadlight()4894 Scene::enableHeadlight()
4895 {
4896 GLenum light = (GLenum) allocateLight();
4897 static float pos[4] = {0.0f, 0.0f, 1.0f, 0.0f};
4898 static float ambientColor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
4899 static float diffuseColor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
4900
4901 glLightfv(light, GL_AMBIENT, ambientColor);
4902 glLightfv(light, GL_DIFFUSE, diffuseColor);
4903 glLightfv(light, GL_POSITION, pos);
4904 glLightfv(light, GL_SPECULAR, diffuseColor);
4905 glLightf(light, GL_SPOT_CUTOFF, 180.0f);
4906 glLightf(light, GL_SPOT_EXPONENT, 0.0f);
4907 glLightf(light, GL_CONSTANT_ATTENUATION, 1.0f);
4908 glLightf(light, GL_LINEAR_ATTENUATION, 0.0f);
4909 glLightf(light, GL_QUADRATIC_ATTENUATION, 0.0f);
4910 glEnable(light);
4911 }
4912
4913 // allocateLight()
4914 //
4915 // reserve an openGL light
4916
4917 int
allocateLight()4918 Scene::allocateLight()
4919 {
4920 GLint maxLights;
4921 glGetIntegerv(GL_MAX_LIGHTS, &maxLights);
4922
4923 if (m_numLights >= maxLights) {
4924 errorf("too many lights!\n");
4925 return GL_LIGHT0;
4926 }
4927
4928 return (GL_LIGHT0 + m_numLights++);
4929 }
4930
4931 int
freeLight()4932 Scene::freeLight()
4933 {
4934 return GL_LIGHT0 + --m_numLights;
4935 }
4936
4937 int
allocateClipPlane()4938 Scene::allocateClipPlane()
4939 {
4940 GLint maxClipPlanes;
4941 glGetIntegerv(GL_MAX_CLIP_PLANES, &maxClipPlanes);
4942
4943 if (m_numClipPlanes >= maxClipPlanes) {
4944 errorf("too many ClipPlanes!\n");
4945 return GL_CLIP_PLANE0;
4946 }
4947
4948 return (GL_CLIP_PLANE0 + m_numClipPlanes++);
4949 }
4950
4951 int
freeClipPlane()4952 Scene::freeClipPlane()
4953 {
4954 return GL_CLIP_PLANE0 + --m_numClipPlanes;
4955 }
4956
4957 void
projectPoint(float x,float y,float z,float * wx,float * wy,float * wz)4958 Scene::projectPoint(float x, float y, float z, float *wx, float *wy, float *wz)
4959 {
4960 GLdouble mmat[16], pmat[16];
4961 GLdouble winx, winy, winz;
4962 GLint viewport[4];
4963
4964 glGetDoublev(GL_MODELVIEW_MATRIX, mmat);
4965 glGetDoublev(GL_PROJECTION_MATRIX, pmat);
4966 glGetIntegerv(GL_VIEWPORT, viewport);
4967
4968 gluProject(x, y, z, mmat, pmat, viewport, &winx, &winy, &winz);
4969
4970 *wx = (float) winx;
4971 *wy = (float) winy;
4972 *wz = (float) winz;
4973 }
4974
4975 void
unProjectPoint(float wx,float wy,float wz,float * x,float * y,float * z)4976 Scene::unProjectPoint(float wx, float wy, float wz, float *x, float *y, float *z)
4977 {
4978 GLdouble mmat[16], pmat[16];
4979 GLdouble objx, objy, objz;
4980 GLint viewport[4];
4981
4982 glGetDoublev(GL_MODELVIEW_MATRIX, mmat);
4983 glGetDoublev(GL_PROJECTION_MATRIX, pmat);
4984 glGetIntegerv(GL_VIEWPORT, viewport);
4985
4986 gluUnProject(wx, wy, wz, mmat, pmat, viewport, &objx, &objy, &objz);
4987
4988 *x = (float) objx;
4989 *y = (float) objy;
4990 *z = (float) objz;
4991 }
4992
4993 void
addViewpoint(Node * viewpoint)4994 Scene::addViewpoint(Node *viewpoint)
4995 {
4996 m_viewpoints.append(viewpoint);
4997 }
4998
4999 void
addNavigationInfo(Node * navigationInfo)5000 Scene::addNavigationInfo(Node *navigationInfo)
5001 {
5002 m_navigationinfos.append(navigationInfo);
5003 }
5004
5005 void
addFog(Node * fog)5006 Scene::addFog(Node *fog)
5007 {
5008 m_fogs.append(fog);
5009 setFog(fog);
5010 }
5011
5012 void
setFog(Node * fog)5013 Scene::setFog(Node *fog)
5014 {
5015 m_currentFog = (NodeFog *)fog;
5016 }
5017
5018 void
addBackground(Node * background)5019 Scene::addBackground(Node *background)
5020 {
5021 m_backgrounds.append(background);
5022 setBackground(background);
5023 }
5024
5025 void
setBackground(Node * background)5026 Scene::setBackground(Node *background)
5027 {
5028 m_currentBackground = (NodeBackground *)background;
5029 }
5030
5031 void
addTimeSensor(Node * timeSensor)5032 Scene::addTimeSensor(Node *timeSensor)
5033 {
5034 for (long i = 0; i < m_timeSensors.size(); i++)
5035 if (m_timeSensors[i] == timeSensor)
5036 return;
5037 m_timeSensors.append(timeSensor);
5038 }
5039
5040 void
startWalking()5041 Scene::startWalking()
5042 {
5043 m_oldWalkTime = swGetCurrentTime();
5044 }
5045
5046 void
walkCamera(Vec3f walk,bool forward)5047 Scene::walkCamera(Vec3f walk, bool forward)
5048 {
5049 Vec3d pos(m_currentViewpoint->getPosition());
5050 Quaternion rot(m_currentViewpoint->getOrientation());
5051 float fspeed = m_currentNavigationInfo->speed()->getValue();
5052 double dt = swGetCurrentTime() - m_oldWalkTime;
5053
5054 if (forward || dt > 0) {
5055 Quaternion around(Vec3f(0.0f, 1.0f, 0.0f), -DEG2RAD(walk.x * 2.0f));
5056 Quaternion newRot(around * rot);
5057 newRot.normalize();
5058 rot.normalize();
5059 m_currentViewpoint->setOrientation(newRot);
5060 float z = dt * walk.z * 2.0f;
5061 m_currentViewpoint->setPosition(pos + rot * fspeed * Vec3d(0, 0, z));
5062 UpdateViews(NULL, UPDATE_REDRAW_3D);
5063 } else {
5064 Vec3f vec(dt * fspeed * walk.x * 2.0f, dt * fspeed * walk.y * 2.0f, 0);
5065 m_currentViewpoint->setPosition(pos + rot * vec);
5066 }
5067 m_viewpointUpdated = true;
5068 }
5069
5070 void
changeTurnPointDistance(float factor)5071 Scene::changeTurnPointDistance(float factor)
5072 {
5073 if (m_currentNavigationInfo) {
5074 MFFloat *mfAvatarSize = m_currentNavigationInfo->avatarSize();
5075 float fdist = m_currentNavigationInfo->speed()->getValue() * 10;
5076 if (mfAvatarSize->getSize() > 3)
5077 fdist = mfAvatarSize->getValue(3) * factor;
5078 MFFloat *newAvatarSize = new MFFloat();
5079 for (int i = 0; i < mfAvatarSize->getSize(); i++)
5080 newAvatarSize->setValue(i, mfAvatarSize->getValue(i));
5081 float values[] = { 0.25f, 1.6f, 0.75f };
5082 if (newAvatarSize->getSize() < 3)
5083 for (int i = newAvatarSize->getSize() - 1; i < 3; i++)
5084 newAvatarSize->setValue(i, values[i]);
5085 newAvatarSize->setValue(3, fdist);
5086 setField(m_currentNavigationInfo,
5087 m_currentNavigationInfo->avatarSize_Field(), newAvatarSize);
5088 TheApp->PrintMessageWindowsFloat(IDS_TURN_POINT_DISTANCE, fdist);
5089 }
5090 }
5091
5092 void
moveCamera(float dx,float dy,float dz)5093 Scene::moveCamera(float dx, float dy, float dz)
5094 {
5095 Vec3d pos = m_currentViewpoint->getPosition();
5096 Quaternion rot = m_currentViewpoint->getOrientation();
5097
5098 float fspeed = m_currentNavigationInfo->speed()->getValue();
5099 m_currentViewpoint->setPosition(pos + rot * fspeed * Vec3f(dx, dy, dz));
5100
5101 m_viewpointUpdated = true;
5102 }
5103
5104 void
turnCamera(float x,float y,float z,float ang)5105 Scene::turnCamera(float x, float y, float z, float ang)
5106 {
5107 Quaternion rot = m_currentViewpoint->getOrientation();
5108 Quaternion r(Vec3f(x, y, z), ang);
5109
5110 m_currentViewpoint->setOrientation(r * rot);
5111
5112 m_viewpointUpdated = true;
5113 }
5114
5115 Quaternion oldRot;
5116
5117 void
setTurnPoint(void)5118 Scene::setTurnPoint(void)
5119 {
5120 m_turnPointPos = m_currentViewpoint->getPosition();
5121 m_turnPointRot = m_currentViewpoint->getOrientation();
5122 }
5123
5124 void
orbitCamera(float dtheta,float dphi)5125 Scene::orbitCamera(float dtheta, float dphi)
5126 {
5127 Vec3d pos(m_currentViewpoint->getPosition());
5128 Quaternion rot(m_currentViewpoint->getOrientation());
5129 Quaternion up(Vec3f(0.0f, 1.0f, 0.0f), dtheta);
5130 Quaternion around(Vec3f(1.0f, 0.0f, 0.0f), dphi);
5131 Quaternion newRot(up * around * rot);
5132
5133 Vec3f zAxis(0, 0, 10);
5134 Vec3f dist(m_turnPointRot * zAxis);
5135 dist.normalize();
5136 float fdist = 10;
5137 MFFloat *mfAvatarSize = m_currentNavigationInfo->avatarSize();
5138 if (mfAvatarSize->getSize() > 3)
5139 fdist = mfAvatarSize->getValue(3);
5140 else
5141 fdist = m_currentNavigationInfo->speed()->getValue() * 10;
5142
5143 dist = dist * fdist;
5144
5145 Vec3d newPos = m_turnPointPos - dist + dist * m_turnPointRot.conj() *
5146 newRot;
5147 if (TheApp->GetMouseMode() == MOUSE_EXAMINE)
5148 m_currentViewpoint->setPosition(newPos);
5149
5150 m_currentViewpoint->setOrientation(newRot);
5151
5152 m_viewpointUpdated = true;
5153 }
5154
5155 void
rollCamera(float dtheta)5156 Scene::rollCamera(float dtheta)
5157 {
5158 Vec3d pos(m_currentViewpoint->getPosition());
5159 Quaternion rot(m_currentViewpoint->getOrientation());
5160 Quaternion roll(Vec3f(0.0f, 0.0f, -1.0f), dtheta);
5161 Quaternion newRot(roll * rot);
5162 newRot.normalize();
5163 rot.normalize();
5164
5165 Vec3d newPos(rot.conj() * pos * newRot);
5166
5167 if (TheApp->GetMouseMode() == MOUSE_EXAMINE) {
5168 m_currentViewpoint->setPosition(newPos);
5169 }
5170 m_currentViewpoint->setOrientation(newRot);
5171 applyCamera();
5172
5173 m_viewpointUpdated = true;
5174 }
5175
5176 void
standUpCamera(void)5177 Scene::standUpCamera(void)
5178 {
5179 Quaternion rot(m_currentViewpoint->getOrientation());
5180 rot.x = 0;
5181 rot.z = 0;
5182 m_currentViewpoint->setOrientation(rot);
5183 UpdateViews(NULL, UPDATE_PREVIEW);
5184
5185 m_viewpointUpdated = true;
5186 }
5187
5188 Node *
createNode(const char * nodeType,int flags)5189 Scene::createNode(const char *nodeType, int flags)
5190 {
5191 Proto *def = NULL;
5192 if (isX3d() && strcmp(nodeType, "NurbsPatchSurface") == 0)
5193 def = m_protos["NurbsSurface"];
5194 else
5195 def = m_protos[nodeType];
5196
5197 Node *node = def ? def->create(this) : (Node *) NULL;
5198 if (node != NULL)
5199 node->setFlag(flags);
5200 return node;
5201 }
5202
5203 Node *
createNode(int nodeType)5204 Scene::createNode(int nodeType)
5205 {
5206 ProtoMap::Chain::Iterator *j;
5207 // search for proto with correct nodeType
5208 for (int i = 0; i < m_protos.width(); i++) {
5209 for ( j = m_protos.chain(i).first(); j != NULL; j = j->next()) {
5210 if (j->item()->getData()->getType() == nodeType)
5211 return createNode(j->item()->getKey());
5212 }
5213 }
5214 return (Node *) NULL;
5215 }
5216
5217 DynamicFieldsNode *
createDynamicFieldsNode(const char * nodeType,int flags)5218 Scene::createDynamicFieldsNode(const char *nodeType, int flags)
5219 {
5220 Proto *def = NULL;
5221 if (isX3d() && strcmp(nodeType, "NurbsPatchSurface") == 0)
5222 def = m_protos["NurbsSurface"];
5223 else
5224 def = m_protos[nodeType];
5225
5226 DynamicFieldsNode *node = def ? (DynamicFieldsNode *)def->create(this) :
5227 (DynamicFieldsNode *) NULL;
5228 if (node != NULL)
5229 node->setFlag(flags);
5230 return node;
5231 }
5232
5233 void
addNode(Node * node)5234 Scene::addNode(Node *node)
5235 {
5236 m_nodes.append(node);
5237
5238 }
5239
5240 MyString
getUniqueNodeName(const char * name)5241 Scene::getUniqueNodeName(const char *name)
5242 {
5243 static char buf[512];
5244 for (int i = 1; ; i++) {
5245 mysnprintf(buf, 512, "%s%d", name, i);
5246 if (!hasAlreadyName(buf)) break;
5247 }
5248 MyString ret = "";
5249 ret += buf;
5250 return ret;
5251 }
5252
5253 MyString
getUniqueNodeName(Node * node)5254 Scene::getUniqueNodeName(Node *node)
5255 {
5256 const char *name = node->getProto()->getName(isX3d());
5257
5258 return getUniqueNodeName(name);
5259 }
5260
5261
5262 MyString
generateUniqueNodeName(Node * node,const char * name)5263 Scene::generateUniqueNodeName(Node *node, const char *name)
5264 {
5265 int i;
5266 static char buf[512];
5267
5268 mysnprintf(buf, 512, "%s%d", name, 1);
5269 for (i = 1; hasAlreadyName(buf); i++) {
5270 mysnprintf(buf, 512, "%s%d", name, i);
5271 }
5272 MyString ret = "";
5273 ret += buf;
5274 def(ret, node);
5275 return ret;
5276 }
5277
5278 MyString
generateUniqueNodeName(Node * node)5279 Scene::generateUniqueNodeName(Node *node)
5280 {
5281 MyString name = mystrdup(getUniqueNodeName(node));
5282 def(name, node);
5283 return name;
5284 }
5285
generateVariableName(Node * node)5286 MyString Scene::generateVariableName(Node *node)
5287 {
5288 MyString ret = "";
5289 ret += node->getProto()->getName(isX3d());
5290 m_variableCounter++;
5291 char number[1024];
5292 mysnprintf(number, 1023, "%d", m_variableCounter);
5293 ret += "_";
5294 ret += number;
5295 return ret;
5296 }
5297
5298 void
removeNode(Node * node)5299 Scene::removeNode(Node *node)
5300 {
5301 long index = m_nodes.findBackward(node);
5302 if ((index >= 0) && (index < (long)m_nodes.size()))
5303 m_nodes.remove(index);
5304 }
5305
5306 void
setSelection(Path * path)5307 Scene::setSelection(Path *path)
5308 {
5309 m_selection_is_in_scene = true;
5310 m_viewOfLastSelection = NULL;
5311 if (m_selection != path) {
5312 if (m_selection)
5313 m_oldSelection = m_selection->getNode();
5314 else
5315 m_oldSelection = NULL;
5316 delete m_selection;
5317 m_selection = path;
5318 Node *node = m_selection->getNode();
5319 if (node == NULL) {
5320 return;
5321 }
5322 if (node->getType() == VRML_VIEWPOINT) {
5323 m_currentViewpoint = (NodeViewpoint *)node;
5324 applyCamera();
5325 }
5326 if (node->getType() == VRML_GEO_VIEWPOINT) {
5327 m_currentViewpoint = (NodeGeoViewpoint *)node;
5328 applyCamera();
5329 }
5330 if (node->getType() == VRML_NAVIGATION_INFO) {
5331 m_currentNavigationInfo = (NodeNavigationInfo *)node;
5332 applyNavigationInfo();
5333 }
5334 if (node->getType() == X3D_HANIM_JOINT) {
5335 m_lastSelectedHAnimJoint = node;
5336 }
5337 if (node->getType() == X3D_HANIM_HUMANOID) {
5338 m_lastSelectedHAnimJoint = NULL;
5339 }
5340 if (node == getRoot()) {
5341 m_lastSelectedHAnimJoint = NULL;
5342 m_firstSelectionRangeHandle = -1;
5343 removeSelectedHandles();
5344 }
5345 MFNode *children = ((NodeGroup *)getRoot())->children();
5346 for (int i = 0; i < children->getSize(); i++)
5347 if (children->getValue(i)->getType() == DUNE_VRML_CUT) {
5348 NodeVrmlCut *cut = (NodeVrmlCut *)children->getValue(i);
5349 cut->updateSelection();
5350 break;
5351 }
5352 }
5353 }
5354
5355 void
getProtoList(MyArray<int> * protoList,const Node * node)5356 Scene::getProtoList(MyArray<int> *protoList, const Node *node)
5357 {
5358 if (node != getRoot())
5359 for (int i = 0; (i < getNumProtos()) && (protoList->size() == 0); i++) {
5360 Proto *proto = getProto(i);
5361 for (int j = 0; j < proto->getNumNodes(); j++)
5362 if ((proto->getNode(j)->isEqualCopy((Node *)node)) ||
5363 (proto->getNode(j)->isEqual((Node *)node))) {
5364 protoList->append(-i - 1);
5365 protoList->append(j);
5366 break;
5367 }
5368 }
5369 }
5370
5371 Path*
newPath(Node * node)5372 Scene::newPath(Node *node)
5373 {
5374 Path* ret;
5375 int len = 0;
5376 Node *n;
5377
5378 for (n = node; n->hasParent() ; n = n->getParent()) {
5379 len += 2;
5380 }
5381
5382 MyArray<int> protoList;
5383 getProtoList(&protoList, n);
5384 if (protoList.size() > 0)
5385 len += 4;
5386
5387 if (len > 0) {
5388 int *list = new int[len];
5389
5390 int i = len-1;
5391
5392 for (n = node; n->hasParentOrProtoParent();
5393 n = n->getParentOrProtoParent()) {
5394 Node *parent = n->getParent();
5395
5396 int field = n->getParentFieldOrProtoParentField();
5397 list[i--] = parent->findChild(n, field);
5398 list[i--] = field;
5399 }
5400 if (protoList.size() > 0) {
5401 list[i--] = 0;
5402 list[i--] = 0;
5403 list[i--] = protoList[1];
5404 list[i--] = protoList[0];
5405 }
5406 ret=new Path(list, len, this);
5407 delete [] list;
5408 } else {
5409 // select root node
5410 ret=new Path(NULL, 0, this);
5411 }
5412 return ret;
5413 }
5414
5415 void
setSelection(Node * node)5416 Scene::setSelection(Node *node)
5417 {
5418 if (node != NULL)
5419 setSelection(node->getPath());
5420 }
5421
5422 void
setSelection(Proto * proto)5423 Scene::setSelection(Proto *proto)
5424 {
5425 Path* path = NULL;
5426 int len = 3;
5427 if (len > 0) {
5428 int *list = new int[len];
5429 for (int i = 0; i < getNumProtos(); i++) {
5430 if (proto == getProto(i)) {
5431 list[0] = -i - 1;
5432 list[1] = -1;
5433 list[2] = 0;
5434 path = new Path(list, len, this);
5435 delete [] list;
5436 setSelection(path);
5437 break;
5438 }
5439 }
5440 }
5441 }
5442
5443 bool
isModified() const5444 Scene::isModified() const
5445 {
5446 if (!canUndo()) {
5447 if (m_unmodified != NULL)
5448 return TRUE;
5449 else
5450 return m_extraModifiedFlag;
5451 } else {
5452 return m_unmodified != m_undoStack.peek();
5453 }
5454 }
5455
5456 void
applyCamera()5457 Scene::applyCamera()
5458 {
5459 if (getSelection()->getNode() &&
5460 getSelection()->getNode()->getType() == X3D_ORTHO_VIEWPOINT)
5461 ((NodeOrthoViewpoint *)getSelection()->getNode())->apply();
5462 else if (m_currentViewpoint->getType() == VRML_GEO_VIEWPOINT)
5463 ((NodeGeoViewpoint *)m_currentViewpoint)->apply();
5464 else if (m_currentViewpoint->getType() == VRML_VIEWPOINT) {
5465 glPushMatrix();
5466 glMatrixMode(GL_MODELVIEW);
5467 glLoadIdentity();
5468 Matrix matrix = Matrix::identity();;
5469 Path *trans = searchTransform(m_currentViewpoint->getPath());
5470 if (trans)
5471 ((NodeTransform *)trans->getNode())->getMatrix(matrix);
5472 glLoadMatrixf(matrix);
5473 ((NodeViewpoint *)m_currentViewpoint)->preDraw();
5474 glPopMatrix();
5475
5476 ((NodeViewpoint *)m_currentViewpoint)->apply(TheApp->useStereo(),
5477 Vec3d(), SFRotation());
5478 }
5479 m_viewpointUpdated = false;
5480 }
5481
5482 void
setCamera(Node * camera)5483 Scene::setCamera(Node *camera)
5484 {
5485 m_currentViewpoint = camera;
5486
5487 m_viewpointUpdated = true;
5488 }
5489
5490 void
applyNavigationInfo(void)5491 Scene::applyNavigationInfo(void)
5492 {
5493 m_currentNavigationInfo->apply();
5494 }
5495
5496 void
setFirstNavigationInfo(void)5497 Scene::setFirstNavigationInfo(void)
5498 {
5499 if (!m_setNavigationInfo) {
5500 m_setNavigationInfo = true;
5501 if (m_navigationinfos.size() > 0) {
5502 m_currentNavigationInfo = (NodeNavigationInfo *) m_navigationinfos[0];
5503 } else {
5504 m_currentNavigationInfo = m_defaultNavigationInfo;
5505 }
5506 }
5507 applyNavigationInfo();
5508 }
5509
5510 void
start()5511 Scene::start()
5512 {
5513 m_running = true;
5514 if (!m_setViewpoint) {
5515 m_setViewpoint = true;
5516 if (m_viewpoints.size() > 0) {
5517 m_currentViewpoint = (NodeViewpoint *) m_viewpoints[0];
5518 } else {
5519 m_currentViewpoint = m_defaultViewpoint;
5520 }
5521 }
5522
5523 double t = swGetCurrentTime();
5524 updateTimeAt(t);
5525 }
5526
5527 void
stop()5528 Scene::stop()
5529 {
5530 m_running = false;
5531 }
5532
5533 double
timeSinceStart(void)5534 Scene::timeSinceStart(void)
5535 {
5536 return m_currentTime - m_timeStart;
5537 }
5538
5539 void
updateTimeAt(double t)5540 Scene::updateTimeAt(double t)
5541 {
5542 for (long i = 0; i < m_timeSensors.size(); i++)
5543 ((NodeTimeSensor *) m_timeSensors[i])->setTime(t);
5544 }
5545
timeUpdateNodePROTO(Node * node,void * data)5546 static bool timeUpdateNodePROTO(Node *node, void *data)
5547 {
5548 #ifdef HAVE_PROTO_INITIALIZATION_OPTIMIZATION
5549 if (node->isPROTO()) {
5550 NodePROTO *protoNode = (NodePROTO *)node;
5551 if (protoNode->getProto()->hasTimeSensor() ||
5552 protoNode->getProto()->specialInit()) {
5553 protoNode->handleIs();
5554 protoNode->createPROTO();
5555 protoNode->reInit();
5556 }
5557 }
5558 #else
5559 if (node->isPROTO()) {
5560 NodePROTO *protoNode = (NodePROTO *)node;
5561 protoNode->handleIs();
5562 protoNode->createPROTO();
5563 protoNode->reInit();
5564 }
5565 #endif
5566 return true;
5567 }
5568
5569 class TimeStep {
5570 public:
5571 double currentTime;
5572 double oldTime;
5573 };
5574
timeUpdateInterpolator(Node * node,void * data)5575 static bool timeUpdateInterpolator(Node *node, void *data)
5576 {
5577 TimeStep *step = (TimeStep *)data;
5578 if (node->isInterpolator()) {
5579 ((Interpolator *)node)->removeOldKeys(step->currentTime, step->oldTime);
5580 }
5581 return true;
5582 }
5583
5584 void
updateTime()5585 Scene::updateTime()
5586 {
5587 m_oldTime = m_currentTime;
5588 m_currentTime = swGetCurrentTime();
5589 updateTimeAt(m_currentTime);
5590 getRoot()->doWithBranch(timeUpdateNodePROTO, NULL,
5591 false, false, false, true, false);
5592 if (isRunning() && isRecording()) {
5593 TimeStep timeStep;
5594 timeStep.currentTime = m_currentTime;
5595 timeStep.oldTime = m_oldTime;
5596 getRoot()->doWithBranch(timeUpdateInterpolator, &timeStep,
5597 false, false, false, true, false);
5598 }
5599 UpdateViews(NULL, UPDATE_TIME);
5600 UpdateViews(NULL, UPDATE_TOOLBARS);
5601 }
5602
5603 Node *
getCamera() const5604 Scene::getCamera() const
5605 {
5606 return m_currentViewpoint;
5607 }
5608
5609 NodeNavigationInfo *
getNavigationInfoNode() const5610 Scene::getNavigationInfoNode() const
5611 {
5612 return m_currentNavigationInfo;
5613 }
5614
5615 void
AddView(SceneView * view)5616 Scene::AddView(SceneView *view)
5617 {
5618 m_views.append(view);
5619 }
5620
5621 void
RemoveView(SceneView * view)5622 Scene::RemoveView(SceneView *view)
5623 {
5624 m_views.remove(m_views.find(view));
5625 }
5626
updateNodePROTO(Node * node,void * data)5627 static bool updateNodePROTO(Node *node, void *data)
5628 {
5629 Proto *proto = (Proto *)data;
5630 if (node->getProto() == proto) {
5631 ((NodePROTO *)node)->handleIs();
5632 ((NodePROTO *)node)->createPROTO();
5633 ((NodePROTO *)node)->reInit();
5634 }
5635 return true;
5636 }
5637
updateNodePROTOs(Proto * protoToUpdate)5638 void Scene::updateNodePROTOs(Proto *protoToUpdate)
5639 {
5640 if (protoToUpdate != NULL) {
5641 getRoot()->doWithBranch(updateNodePROTO, protoToUpdate,
5642 false, false, false, true, false);
5643 UpdateViews(NULL, UPDATE_REDRAW_3D);
5644 }
5645 }
5646
5647 void
OnFieldChange(Node * node,int field,int index)5648 Scene::OnFieldChange(Node *node, int field, int index)
5649 {
5650 static double time = 0;
5651 if ((node->getType() == VRML_VIEWPOINT) ||
5652 (node->getType() == VRML_GEO_VIEWPOINT))
5653 if (node != getSelection()->getNode())
5654 return;
5655
5656 time = m_currentTime;
5657
5658 FieldUpdate hint(node, field, index);
5659 UpdateViews(NULL, UPDATE_FIELD, (Hint *) &hint);
5660 }
5661
5662 void
OnAddNode(Node * node,Node * dest,int field)5663 Scene::OnAddNode(Node *node, Node *dest, int field)
5664 {
5665 if (node->getOutsideProto() != NULL) {
5666 Proto *protoToUpdate = node->getOutsideProto();
5667 protoToUpdate->setIsNodeIndex();
5668 getRoot()->doWithBranch(updateNodePROTO, protoToUpdate);
5669 }
5670
5671 NodeUpdate hint(node, dest, field);
5672
5673 UpdateViews(NULL, UPDATE_ADD_NODE, (Hint *) &hint);
5674 }
5675
5676 void
OnAddNodeSceneGraph(Node * node,Node * dest,int field)5677 Scene::OnAddNodeSceneGraph(Node *node, Node *dest, int field)
5678 {
5679 NodeUpdate hint(node, dest, field);
5680
5681 UpdateViews(NULL, UPDATE_ADD_NODE_SCENE_GRAPH_VIEW, (Hint *) &hint);
5682 }
5683
5684 void
OnRemoveNode(Node * node,Node * src,int field)5685 Scene::OnRemoveNode(Node *node, Node *src, int field)
5686 {
5687 NodeUpdate hint(node, src, field);
5688 // a deleted DEF'ed node can not be USE'd
5689 if (node == m_defNode)
5690 m_defNode = NULL;
5691 UpdateViews(NULL, UPDATE_REMOVE_NODE, (Hint *) &hint);
5692 }
5693
5694 void
UpdateViews(SceneView * sender,int type,Hint * hint)5695 Scene::UpdateViews(SceneView *sender, int type, Hint *hint)
5696 {
5697 static bool alreadyInUpdate = false;
5698 if (alreadyInUpdate) // forbid recursive update chains
5699 return;
5700 alreadyInUpdate = true;
5701 UpdateViewsNow(sender, type, hint);
5702 alreadyInUpdate = false;
5703 }
5704
5705
5706 void
UpdateViewsNow(SceneView * sender,int type,Hint * hint)5707 Scene::UpdateViewsNow(SceneView *sender, int type, Hint *hint)
5708 {
5709 if (!m_canUpdateViewsSelection)
5710 if (type == UPDATE_SELECTION)
5711 return;
5712 for (List<SceneView *>::Iterator *i = m_views.first(); i != NULL;
5713 i = i->next()) {
5714 SceneView *view = i->item();
5715 if (view != sender && (!swIsHidden(TheApp->mainWnd())))
5716 view->OnUpdate(sender, type, hint);
5717 }
5718 }
5719
5720 void
BackupRoutesRec(Node * node,CommandList * list)5721 BackupRoutesRec(Node *node, CommandList *list)
5722 {
5723 int i;
5724 SocketList::Iterator *j;
5725
5726 if (!node) return;
5727
5728 if (node->getNumParents() > 1) return;
5729
5730 for (i = 0; i < node->getProto()->getNumEventIns(); i++) {
5731 for (j = node->getInput(i).first(); j != NULL; j = j->next()) {
5732 const RouteSocket &s = j->item();
5733 list->append(new UnRouteCommand(s.getNode(), s.getField(),
5734 node, i));
5735 }
5736 }
5737 for (i = 0; i < node->getProto()->getNumEventOuts(); i++) {
5738 for (j = node->getOutput(i).first(); j != NULL; j = j->next()) {
5739 const RouteSocket &s = j->item();
5740 list->append(new UnRouteCommand(node, i,
5741 s.getNode(), s.getField()));
5742 }
5743 }
5744
5745 for (i = 0; i < node->getProto()->getNumFields(); i++) {
5746 FieldValue *v = node->getField(i);
5747 if (v->getType() == SFNODE) {
5748 BackupRoutesRec(((SFNode *) v)->getValue(), list);
5749 } else if (v->getType() == MFNODE) {
5750 int size = ((MFNode *) v)->getSize();
5751 for (int k = 0; k < size; k++) {
5752 BackupRoutesRec(((MFNode *) v)->getValue(k), list);
5753 }
5754 }
5755 }
5756 }
5757
5758 void
selectNext()5759 Scene::selectNext()
5760 {
5761 Node *node = m_selection->getNode();
5762 int newIndex = node->getNextSiblingIndex();
5763 if (newIndex == -1)
5764 newIndex = node->getPrevSiblingIndex();
5765 Node *parent = m_selection->getParent();
5766 Node *newSelection = parent;
5767 if (parent == NULL)
5768 newSelection = m_root;
5769 else {
5770 int parentField = m_selection->getParentField();
5771 newSelection = parent;
5772 if (newIndex != -1) {
5773 MFNode *mfnode = (MFNode *)parent->getField(parentField);
5774 if (newIndex < mfnode->getSize())
5775 newSelection = mfnode->getValue(newIndex);
5776 }
5777 }
5778 setSelection(newSelection);
5779 }
5780
5781 void
deleteSelected()5782 Scene::deleteSelected()
5783 {
5784 Proto *proto = m_selection->getProto(this);
5785 Node *node = m_selection->getNode();
5786 if (node->getIsUse())
5787 return;
5788 if (proto != NULL) {
5789 for (int i = 0; i < proto->getNumNodes(); i++)
5790 if (node->isEqual(proto->getNode(i))) {
5791 proto->removeNode(i);
5792 proto->setIsNodeIndex();
5793 updateNodePROTOs(proto);
5794 UpdateViews(NULL, UPDATE_ALL);
5795 if (i > 0)
5796 setSelection(newPath(proto->getNode(i - 1)));
5797 else
5798 setSelection(getRoot());
5799 UpdateViews(NULL, UPDATE_SELECTION);
5800 return;
5801 }
5802 }
5803 Node *parent = m_selection->getParent();
5804 int parentField = m_selection->getParentField();
5805 if ((parent != NULL) && (parentField != -1)) {
5806 CommandList *list = new CommandList();
5807 deleteSelectedAppend(list);
5808 execute(list);
5809 }
5810 }
5811
5812 void
deleteAll()5813 Scene::deleteAll()
5814 {
5815 NodeGroup *parent = (NodeGroup *)getRoot();
5816 int parentField = parent->children_Field();
5817
5818 CommandList *list = new CommandList();
5819 if ((parent != NULL) && (parentField != -1)) {
5820 for (int i = parent->children()->getSize() - 1; i >= 0; i--) {
5821 Node *node = parent->children()->getValue(i);
5822 BackupRoutesRec(node, list);
5823 list->append(new MoveCommand(node, parent, parentField, NULL, -1));
5824 execute(list);
5825 }
5826 }
5827 UpdateViews(NULL, UPDATE_ALL);
5828 }
5829
5830 void
deleteSelectedAppend(CommandList * list)5831 Scene::deleteSelectedAppend(CommandList* list)
5832 {
5833 if (m_selection && (m_selection->getNode() != m_root)) {
5834 if (m_selection->getNode() == m_currentViewpoint) {
5835 m_defaultViewpoint = (NodeViewpoint *)m_currentViewpoint->copy();
5836 m_currentViewpoint = m_defaultViewpoint;
5837 }
5838 if (m_selection->getNode() &&
5839 m_selection->getNode()->getType() == X3D_VIEWPORT) {
5840 m_viewports.remove(m_viewports.find((NodeViewport *)
5841 m_selection->getNode()));
5842 }
5843 Node *node = m_selection->getNode();
5844 Node *parent = m_selection->getParent();
5845 int parentField = m_selection->getParentField();
5846
5847 if ((parent != NULL) && (parentField != -1)) {
5848 if (node->getNumParents() == 1) {
5849 BackupRoutesRec(node, list);
5850 }
5851 list->append(new MoveCommand(node, parent, parentField, NULL, -1));
5852 }
5853 }
5854 }
5855
5856 int
OnDragOver(Node * src,Node * srcParent,int src_field,Node * dest,int dest_field,int modifiers)5857 Scene::OnDragOver(Node *src, Node *srcParent, int src_field,
5858 Node *dest, int dest_field, int modifiers)
5859 {
5860 int rc = 0;
5861
5862 if (src && dest) {
5863 int destField = getDestField(src, dest, dest_field);
5864 if (destField >= 0) {
5865 if ((modifiers & SW_CONTROL) && (modifiers & SW_SHIFT)
5866 && dest != src && !dest->hasAncestor(src)) {
5867 rc = SW_DRAG_LINK;
5868 } else if (modifiers & SW_CONTROL) {
5869 rc = SW_DRAG_COPY;
5870 } else if (dest != src
5871 && !dest->hasAncestor(src)
5872 && dest->findChild(src, destField) == -1) {
5873 rc = SW_DRAG_MOVE;
5874 }
5875 }
5876 }
5877 return rc;
5878 }
5879
5880 int
OnDrop(Node * src,Node * srcParent,int srcField,Node * dest,int destField,int modifiers)5881 Scene::OnDrop(Node *src, Node *srcParent, int srcField,
5882 Node *dest, int destField, int modifiers)
5883 {
5884 int effect = OnDragOver(src, srcParent, srcField, dest, destField, modifiers);
5885 NodeUpdate *hint = NULL;
5886 if (src && dest) {
5887 if (destField == -1) destField = dest->findValidField(src);
5888 switch(effect) {
5889 case SW_DRAG_COPY:
5890 execute(new MoveCommand(src->copy(), NULL, -1, dest, destField));
5891 src->reInit();
5892 break;
5893 case SW_DRAG_MOVE:
5894 execute(new MoveCommand(src, srcParent, srcField, dest, destField));
5895 break;
5896 case SW_DRAG_LINK:
5897 execute(new MoveCommand(src, NULL, -1, dest, destField));
5898 hint = new NodeUpdate(src, NULL, 0);
5899 UpdateViews(NULL, UPDATE_NODE_NAME, (Hint*) hint);
5900 break;
5901 }
5902 return 1;
5903 } else {
5904 return 0;
5905 }
5906 }
5907
5908 struct HttpFile {
5909 const char *filename;
5910 FILE *stream;
5911 };
5912
my_fwrite(void * buffer,long size,long nmemb,void * stream)5913 static long my_fwrite(void *buffer, long size, long nmemb, void *stream)
5914 {
5915 struct HttpFile *out = (struct HttpFile *)stream;
5916 if(out && !out->stream) {
5917 /* open file for writing */
5918 out->stream = fopen(out->filename, "wb");
5919 if(!out->stream)
5920 return -1; /* failure, can't open file to write */
5921 }
5922 return fwrite(buffer, size, nmemb, out->stream);
5923 }
5924
5925 class DownloadPathData {
5926 public:
5927 MyString string;
5928 bool isRemote;
5929 };
5930
5931 MyString
downloadPath(const URL & url)5932 Scene::downloadPath(const URL &url)
5933 {
5934 DownloadPathData data = downloadPathIntern(url);
5935 return data.string;
5936 }
5937
5938 DownloadPathData
downloadPathIntern(const URL & url)5939 Scene::downloadPathIntern(const URL &url)
5940 {
5941 DownloadPathData ret;
5942 ret.string = "";
5943 ret.isRemote = false;
5944 if ((strcasecmp(url.getScheme(), "https") == 0) ||
5945 (strcasecmp(url.getScheme(), "http") == 0) ||
5946 (strcasecmp(url.getScheme(), "ftp") == 0)) {
5947 ret.isRemote = true;
5948
5949 const char *myPath = TheApp->getDownloadDirectory();
5950 myPath = replaceHome(myPath);
5951 ret.string += myPath;
5952 free((void *)myPath);
5953 ret.string += swGetPathSeperator();
5954 ret.string += url.getHostname();
5955 ret.string += swGetPathSeperator();
5956 ret.string += '/';
5957 ret.string += url.ToPath();
5958 if (TheApp->getVerbose())
5959 swDebugf("%s\n", (const char *)ret.string);
5960 mkdir_parents4file(ret.string);
5961 setPathIntern(ret.string);
5962 return ret;
5963 } else if (strcasecmp(url.getScheme(), "file") == 0) {
5964 ret.string += url.ToPath();
5965 return ret;
5966 }
5967 ret.string += url.ToPath();
5968 return ret;
5969 }
5970
5971 bool
Download(const URL & url,MyString * path)5972 Scene::Download(const URL &url, MyString *path)
5973 {
5974 #ifdef HAVE_LIBCURL
5975 DownloadPathData data = downloadPathIntern(url);
5976
5977 if (data.isRemote) {
5978 MyString filename = "";
5979 filename += data.string;
5980 CURL *curl;
5981 CURLcode res;
5982 struct HttpFile httpfile = {
5983 filename, /* name to store the file as if successful */
5984 NULL
5985 };
5986
5987 curl_global_init(CURL_GLOBAL_DEFAULT);
5988
5989 curl = curl_easy_init();
5990 if (curl) {
5991 curl_easy_setopt(curl, CURLOPT_URL, (const char *)url);
5992 // Define our callback to get called when there's data to be written
5993 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
5994 // Set a pointer to our struct to pass to the callback
5995 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &httpfile);
5996 // disable decompession
5997 curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "identity");
5998 curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
5999
6000 #ifdef DEBUG
6001 /* Switch on full protocol/debug output */
6002 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
6003 #endif
6004
6005 res = curl_easy_perform(curl);
6006
6007 /* always cleanup */
6008 curl_easy_cleanup(curl);
6009
6010 if (CURLE_OK != res) {
6011 /* we failed */
6012 fprintf(stderr, "curl: %s\n", curl_easy_strerror(res));
6013 } else
6014 m_downloaded = true;
6015 } else {
6016 swDebugf("failed download %s\n", (const char *)url);
6017 return false;
6018 }
6019
6020 if (httpfile.stream)
6021 fclose(httpfile.stream); /* close the local file */
6022
6023 curl_global_cleanup();
6024
6025 *path = filename;
6026 } else
6027 *path = data.string;
6028 #endif
6029
6030 return true;
6031 }
6032
6033 FontInfo *
LoadGLFont(const char * fontName,const char * style)6034 Scene::LoadGLFont(const char *fontName, const char *style)
6035 {
6036 int styleId;
6037
6038 // handle "special" font names
6039 if (!strcmp(fontName, "SERIF")) {
6040 fontName = "Times New Roman";
6041 } else if (!strcmp(fontName, "SANS")) {
6042 fontName = "Arial";
6043 } else if (!strcmp(fontName, "TYPEWRITER")) {
6044 fontName = "Courier New";
6045 }
6046
6047 if (!strcmp(style, "BOLD")) {
6048 styleId = SW_BOLD;
6049 } else if (!strcmp(style, "ITALIC")) {
6050 styleId = SW_ITALIC;
6051 } else if (!strcmp(style, "BOLDITALIC")) {
6052 styleId = SW_BOLD | SW_ITALIC;
6053 } else {
6054 styleId = SW_PLAIN;
6055 }
6056
6057 // look for font in cache
6058
6059 for (long i = 0; i < m_fonts.size(); i++) {
6060 if (!strcmp(m_fonts[i]->name, fontName) && m_fonts[i]->style == styleId) {
6061 return m_fonts[i];
6062 }
6063 }
6064
6065 // create some font outlines
6066
6067 FontInfo *info = new FontInfo();
6068
6069 info->displayListBase =
6070 swLoadGLFont(fontName, styleId, info->kernX, info->kernY);
6071
6072 if (info->displayListBase == 0) {
6073 delete info;
6074 return NULL;
6075 } else {
6076 info->name = fontName;
6077 info->style = styleId;
6078 m_fonts.append(info);
6079 return info;
6080 }
6081 }
6082
6083 bool
addProtoName(MyString name)6084 Scene::addProtoName(MyString name)
6085 {
6086 if (belongsToNodeWithExternProto(name))
6087 return true;
6088 for (int i = 0; i < m_numProtoNames; i++)
6089 if (m_protos[m_protoNames[i]] && name == m_protoNames[i]) {
6090 if (m_protos[m_protoNames[i]]->isExternProto())
6091 return true;
6092 return false;
6093 }
6094 m_protoNames[m_numProtoNames++] = name;
6095 return true;
6096 }
6097
6098 void
deleteProtoName(MyString name)6099 Scene::deleteProtoName(MyString name)
6100 {
6101 for (int i = 0; i < m_numProtoNames; i++)
6102 if (name == m_protoNames[i]) {
6103 m_protoNames.remove(i);
6104 m_numProtoNames--;
6105 }
6106 }
6107
6108 void
addProtoDefinition(void)6109 Scene::addProtoDefinition(void)
6110 {
6111 m_protoDefinitions[m_numProtoDefinitions++] = "";
6112 m_isNestedProto[m_numProtoDefinitions - 1] = false;
6113 }
6114
6115 void
addToProtoDefinition(const char * string)6116 Scene::addToProtoDefinition(const char* string)
6117 {
6118 if (m_numProtoDefinitions > 0)
6119 m_protoDefinitions[m_numProtoDefinitions - 1] += string;
6120 }
6121
6122 bool
isNestedProto(const char * protoName)6123 Scene::isNestedProto(const char *protoName)
6124 {
6125 for (int i = 0; i < m_numProtoDefinitions; i++)
6126 if (i < getNumProtos())
6127 if (strcmp(m_protoNames[i], protoName) == 0)
6128 if (m_isNestedProto[i])
6129 return true;
6130 return false;
6131 }
6132
6133 void
setNestedProto(void)6134 Scene::setNestedProto(void)
6135 {
6136 if (m_numProtoDefinitions > 0)
6137 m_isNestedProto[m_numProtoDefinitions - 1] = true;
6138 }
6139
6140 MyString
createRouteString(const char * fromNodeName,const char * fromFieldName,const char * toNodeName,const char * toFieldName)6141 Scene::createRouteString(const char *fromNodeName, const char *fromFieldName,
6142 const char *toNodeName, const char *toFieldName)
6143 {
6144 MyString route = "";
6145 if (::isX3dXml(m_writeFlags)) {
6146 route += "<ROUTE fromNode='";
6147 route += fromNodeName;
6148 route += "' fromField='";
6149 route += fromFieldName;
6150 route += "' toNode='";
6151 route += toNodeName;
6152 route += "' toField='";
6153 route += toFieldName;
6154 route += "'";
6155 if (m_writeFlags & X3DOM) {
6156 // X3DOM do not support <ROUTE />
6157 route += ">";
6158 route += "</ROUTE>";
6159 } else
6160 route += "/>";
6161 } else {
6162 route += "ROUTE ";
6163 route += fromNodeName;
6164 route += ".";
6165 route += fromFieldName;
6166 route += " TO ";
6167 route += toNodeName;
6168 route += ".";
6169 route += toFieldName;
6170 }
6171 return route;
6172 }
6173
6174
6175 void
addRouteString(MyString string)6176 Scene::addRouteString(MyString string)
6177 {
6178 // do not store double route strings
6179 for (List<MyString>::Iterator* routepointer = m_routeList.first();
6180 routepointer != NULL; routepointer = routepointer->next() )
6181 if (strcmp(routepointer->item(),string) == 0)
6182 return;
6183
6184 m_routeList.append(string);
6185 }
6186
6187 void
addEndRouteString(MyString string)6188 Scene::addEndRouteString(MyString string)
6189 {
6190 m_endRouteList.append(string);
6191 }
6192
6193 void
setViewOfLastSelection(SceneView * view)6194 Scene::setViewOfLastSelection(SceneView* view)
6195 {
6196 m_viewOfLastSelection = view;
6197 m_selection_is_in_scene = false;
6198 }
6199
getViewOfLastSelection(void)6200 SceneView* Scene::getViewOfLastSelection(void)
6201 {
6202 return m_viewOfLastSelection;
6203 }
6204
copyLastSelection(void)6205 void Scene::copyLastSelection(void)
6206 {
6207 if (!m_selection_is_in_scene) {
6208 // do copy in View
6209 SceneView* view = getViewOfLastSelection();
6210 if (view != NULL)
6211 view->CopyLastSelection();
6212 }
6213 }
6214
pasteLastSelection(void)6215 void Scene::pasteLastSelection(void)
6216 {
6217 if (!m_selection_is_in_scene) {
6218 // do paste in View
6219 SceneView* view = getViewOfLastSelection();
6220 if (view != NULL)
6221 view->PasteLastSelection();
6222 }
6223 }
6224
pasteSymetricLastSelection(int direction)6225 void Scene::pasteSymetricLastSelection(int direction)
6226 {
6227 if (!m_selection_is_in_scene) {
6228 // do paste in View
6229 SceneView* view = getViewOfLastSelection();
6230 if (view != NULL)
6231 view->PasteSymetricLastSelection(direction);
6232 }
6233 }
6234
deleteLastSelection(void)6235 void Scene::deleteLastSelection(void)
6236 {
6237 if (m_selection_is_in_scene) {
6238 // do delete in scene
6239 deleteSelected();
6240 } else {
6241 // do delete in View
6242 SceneView* view = getViewOfLastSelection();
6243 if (view != NULL)
6244 view->DeleteLastSelection();
6245 }
6246 }
6247
saveProtoStatus(void)6248 void Scene::saveProtoStatus(void)
6249 {
6250 m_statusNumProtoNames=m_numProtoNames;
6251 m_statusNumProtoDefinitions=m_numProtoDefinitions;
6252 }
6253
restoreProtoStatus(void)6254 void Scene::restoreProtoStatus(void)
6255 {
6256 for (int i = m_statusNumProtoNames + 1; i < m_numProtoNames; i++)
6257 m_protoNames.remove(i);
6258 m_numProtoNames=m_statusNumProtoNames;
6259 for (int i = m_statusNumProtoDefinitions + 1; i < m_numProtoDefinitions; i++)
6260 m_protoDefinitions.remove(i);
6261 m_numProtoDefinitions=m_statusNumProtoDefinitions;
6262 }
6263
6264 StringArray *
getAllNodeNames(void)6265 Scene::getAllNodeNames(void)
6266 {
6267 StringArray *ret = new StringArray();
6268 ProtoMap::Chain::Iterator *j;
6269 for (int i = 0; i < m_protos.width(); i++) {
6270 for ( j = m_protos.chain(i).first(); j != NULL; j = j->next()) {
6271 ret->append(j->item()->getKey());
6272 }
6273 }
6274 return ret;
6275 }
6276
6277 bool
use3dCursor(void)6278 Scene::use3dCursor(void)
6279 {
6280 switch (TheApp->Get3dCursorMode()) {
6281 case CM_3DCURSOR_ALWAYS:
6282 return m_use3dCursor;
6283 case CM_3DCURSOR_RECORDING:
6284 if (isRecording())
6285 return m_use3dCursor;
6286 break;
6287 case CM_3DCURSOR_NOT_RUN:
6288 if (!isRunning())
6289 return m_use3dCursor;
6290 break;
6291 case CM_3DCURSOR_NONE:
6292 return false;
6293 }
6294 return false;
6295 }
6296
6297 // the proto PREFIX is also needed for the illegal2vrml program
6298 // undefined nodes named "something" are renamed to "PREFIXsomething"
6299 // when the proto "PREFIXsomething" is defined
6300
6301 bool
setPrefix(char * prefix)6302 Scene::setPrefix(char* prefix)
6303 {
6304 if (prefix != NULL)
6305 TheApp->setPrefix(prefix);
6306 else {
6307 // compare all protonames to find out a common prefix
6308 bool prefixFound = false;
6309 if (getNumProtoNames() > 1) {
6310 MyString prefix = "";
6311 for (int numChar = 0; numChar < m_protoNames[0].length();
6312 numChar++) {
6313 char character = m_protoNames[0][numChar];
6314 bool sameCharacter = true;
6315 for (int i = 1; i < getNumProtoNames(); i++) {
6316 if ((numChar >= m_protoNames[i].length()) ||
6317 (m_protoNames[i][numChar] != character)) {
6318 sameCharacter = false;
6319 break;
6320 }
6321 }
6322 if (sameCharacter) {
6323 prefixFound = true;
6324 prefix += character;
6325 } else
6326 break;
6327 }
6328 if (prefixFound)
6329 TheApp->setPrefix(mystrdup(prefix));
6330 }
6331 if (!prefixFound) {
6332 errorf("can not find out prefix from only one node\n");
6333 errorf("prefix missing, use \"-prefix\" in commandline\n");
6334 return false;
6335 }
6336 }
6337 return true;
6338 }
6339
6340 MyString
getNodeWithPrefix(const MyString & nodeType)6341 Scene::getNodeWithPrefix(const MyString &nodeType)
6342 {
6343 MyString newNodeType = "";
6344 newNodeType += TheApp->getPrefix();
6345 newNodeType += nodeType;
6346 return newNodeType;
6347 }
6348
6349 void
setPathAllURL(const char * path)6350 Scene::setPathAllURL(const char *path)
6351 {
6352 const NodeList *nodes = getNodes();
6353 for (long i = 0; i < nodes->size(); i++) {
6354 Node *node = nodes->get(i);
6355 if (node->isInScene(this))
6356 for (int j = 0; j < node->getProto()->getNumFields(); j++) {
6357 Field *field = node->getProto()->getField(j);
6358 if ((field->getType() == MFSTRING) &&
6359 ((field->getFlags() & FF_URL) != 0)) {
6360 MFString* urls = (MFString *)node->getField(j);
6361 for (int k = 0; k < urls->getSize(); k++) {
6362 const char *urlk = urls->getValue(k);
6363 if (!isSortOfEcmascript(urlk) && notURN(urlk)) {
6364 URL url(getURL(), urlk);
6365 MyString *newURL = new MyString("");
6366 if (strlen(path) != 0) {
6367 *newURL += path;
6368 *newURL += "/";
6369 }
6370 *newURL += url.GetFileName();
6371 urls->setValue(k, *newURL);
6372 }
6373 }
6374 }
6375 }
6376 }
6377 }
6378
6379 Node *
replaceNode(Node * oldNode,Node * newNode)6380 Scene::replaceNode(Node *oldNode, Node* newNode)
6381 {
6382 if (newNode == NULL)
6383 return NULL;
6384 if (oldNode->getParent() == NULL)
6385 return NULL;
6386 int numParents = oldNode->getNumParents();
6387 for (int i = 0; i <= numParents; i++) {
6388 Node *parent = oldNode->getParent(i);
6389 int field = oldNode->getParentField(i);
6390 if ((parent != NULL) && (field != -1)) {
6391 execute(new MoveCommand(oldNode, parent, field, NULL, -1));
6392 execute(new MoveCommand(newNode, NULL, -1, parent, field));
6393 }
6394 }
6395 if (numParents == 0)
6396 return NULL;
6397 return newNode;
6398 }
6399
6400 Node *
convertToIndexedFaceSet(Node * node)6401 Scene::convertToIndexedFaceSet(Node* node)
6402 {
6403 if (!node->canConvertToIndexedFaceSet())
6404 return NULL;
6405
6406 NodeIndexedFaceSet *meshNode = (NodeIndexedFaceSet *)
6407 node->toIndexedFaceSet();
6408
6409 return replaceNode(node, meshNode);
6410 }
6411
6412 int
writeIndexedFaceSet(int f,Node * node)6413 Scene::writeIndexedFaceSet(int f, Node* node)
6414 {
6415 NodeIndexedFaceSet *meshNode = (NodeIndexedFaceSet *)
6416 node->toIndexedFaceSet();
6417
6418 meshNode->setVariableName(strdup(node->getVariableName()));
6419 int ret = meshNode->write(f, m_writeFlags);
6420 meshNode->unref();
6421 return ret;
6422 }
6423
6424 Node *
convertToIndexedLineSet(Node * node)6425 Scene::convertToIndexedLineSet(Node* node)
6426 {
6427 if (!node->canConvertToIndexedLineSet())
6428 return NULL;
6429
6430 NodeIndexedLineSet *chainNode = (NodeIndexedLineSet *)
6431 node->toIndexedLineSet();
6432 return replaceNode(node, chainNode);
6433 }
6434
6435 void
recalibrate(void)6436 Scene::recalibrate(void)
6437 {
6438 TheApp->calibrateInputDevices();
6439 if (m_viewpoints.size() > 0) {
6440 m_currentViewpoint = (NodeViewpoint *) m_viewpoints[0];
6441 } else {
6442 m_currentViewpoint = m_defaultViewpoint;
6443 }
6444 applyCamera();
6445 UpdateViews(NULL, UPDATE_TIME);
6446 }
6447
6448 void
makeSimilarName(Node * node,const char * name)6449 Scene::makeSimilarName(Node *node, const char *name)
6450 {
6451 if (!m_similarNameFlag)
6452 return;
6453 char* reducedName = mystrdup(name);
6454 int i;
6455 // strip _ number (e.g. _0 or _12) constructs at end
6456 for (i = strlen(name) - 1; i > 0; i--)
6457 if ((name[i] == '_') || ((name[i] >= '0') && (name[i] <= '9'))) {
6458 if (name[i] == '_')
6459 reducedName[i] = 0;
6460 } else
6461 break;
6462 int len = strlen(name) + 512;
6463 char* buf = (char*) malloc(len);
6464 while (true) {
6465 mysnprintf(buf, len, "%s_%d", reducedName, i++);
6466 if (!hasAlreadyName(buf)) {
6467 MyString* newName = new MyString(buf);
6468 def(*newName, node);
6469 break;
6470 }
6471 }
6472 free(buf);
6473 free(reducedName);
6474 }
6475
6476 ProtoArray *
getInteractiveProtos(int type)6477 Scene::getInteractiveProtos(int type)
6478 {
6479 switch(type)
6480 {
6481 case SFBOOL:
6482 return &m_interactiveSFBoolProtos;
6483 case SFROTATION:
6484 return &m_interactiveSFRotationProtos;
6485 case SFTIME:
6486 return &m_interactiveSFTimeProtos;
6487 case SFVEC3F:
6488 return &m_interactiveSFVec3fProtos;
6489 }
6490 return &m_emptyProtoArray;
6491 }
6492
6493 void
buildInteractiveProtos(void)6494 Scene::buildInteractiveProtos(void)
6495 {
6496 int i = 0;
6497 m_interactiveSFBoolProtos[i++] = m_protos["CylinderSensor"];
6498 m_interactiveSFBoolProtos[i++] = m_protos["PlaneSensor"];
6499 m_interactiveSFBoolProtos[i++] = m_protos["ProximitySensor"];
6500 m_interactiveSFBoolProtos[i++] = m_protos["SphereSensor"];
6501 m_interactiveSFBoolProtos[i++] = m_protos["TouchSensor"];
6502 m_interactiveSFBoolProtos[i++] = m_protos["VisibilitySensor"];
6503 i = 0;
6504 m_interactiveSFRotationProtos[i++] = m_protos["CylinderSensor"];
6505 m_interactiveSFRotationProtos[i++] = m_protos["ProximitySensor"];
6506 m_interactiveSFRotationProtos[i++] = m_protos["SphereSensor"];
6507 if (TheApp->getCoverMode()) {
6508 m_interactiveSFRotationProtos[i++] = m_protos["COVER"];
6509 m_interactiveSFRotationProtos[i++] = m_protos["SpaceSensor"];
6510 m_interactiveSFRotationProtos[i++] = m_protos["ARSensor"];
6511 }
6512 i = 0;
6513 m_interactiveSFTimeProtos[i++] = m_protos["Collision"];
6514 m_interactiveSFTimeProtos[i++] = m_protos["ProximitySensor"];
6515 m_interactiveSFTimeProtos[i++] = m_protos["TouchSensor"];
6516 m_interactiveSFTimeProtos[i++] = m_protos["VisibilitySensor"];
6517 i = 0;
6518 m_interactiveSFVec3fProtos[i++] = m_protos["CylinderSensor"];
6519 m_interactiveSFVec3fProtos[i++] = m_protos["PlaneSensor"];
6520 m_interactiveSFVec3fProtos[i++] = m_protos["ProximitySensor"];
6521 m_interactiveSFVec3fProtos[i++] = m_protos["SphereSensor"];
6522 m_interactiveSFVec3fProtos[i++] = m_protos["TouchSensor"];
6523 if (TheApp->getCoverMode()) {
6524 m_interactiveSFVec3fProtos[i++] = m_protos["COVER"];
6525 m_interactiveSFVec3fProtos[i++] = m_protos["SpaceSensor"];
6526 m_interactiveSFVec3fProtos[i++] = m_protos["ARSensor"];
6527 }
6528 }
6529
6530 void
setHeadlight(int headlight)6531 Scene::setHeadlight(int headlight)
6532 {
6533 // only use headlight of first NavigationInfo
6534 if (m_headlightIsSet == false) {
6535 m_headlight = headlight;
6536 m_headlightIsSet = true;
6537 }
6538 }
6539
6540 int
getConstrain(void)6541 Scene::getConstrain(void)
6542 {
6543 int ret = CONSTRAIN_NONE;
6544 if (!m_xOnly && !m_yOnly && !m_zOnly)
6545 ret = CONSTRAIN_NONE;
6546 else if (m_xOnly && !m_yOnly && !m_zOnly)
6547 ret = CONSTRAIN_X;
6548 else if (!m_xOnly && m_yOnly && !m_zOnly)
6549 ret = CONSTRAIN_Y;
6550 else if (!m_xOnly && !m_yOnly && m_zOnly)
6551 ret = CONSTRAIN_Z;
6552 else if (m_xOnly && m_yOnly && !m_zOnly)
6553 ret = CONSTRAIN_XY;
6554 else if (m_xOnly && !m_yOnly && m_zOnly)
6555 ret = CONSTRAIN_ZX;
6556 else if (!m_xOnly && m_yOnly && m_zOnly)
6557 ret = CONSTRAIN_YZ;
6558 return ret;
6559 }
6560
6561 Vec3f
constrainVec(Vec3f vec)6562 Scene::constrainVec(Vec3f vec)
6563 {
6564 Vec3f v(vec);
6565 if ((!m_xOnly) && (m_yOnly || m_zOnly))
6566 v.x = 0;
6567 if ((!m_yOnly) && (m_xOnly || m_zOnly))
6568 v.y=0;
6569 if ((!m_zOnly) && (m_xOnly || m_yOnly))
6570 v.z=0;
6571 return v;
6572 }
6573
6574 void
setX3d(void)6575 Scene::setX3d(void)
6576 {
6577 m_writeFlags = m_writeFlags & ~(CONVERT2VRML);
6578 if ((!::isX3d(m_writeFlags)) && (m_root != NULL)) {
6579 getNodes()->clearFlag(NODE_FLAG_CONVERTED);
6580 m_writeFlags |= CONVERT2X3D;
6581 for (int i = 0; i < getNumProtos(); i++)
6582 for (int j = 0; j < getProto(i)->getNumNodes(); j++)
6583 getProto(i)->getNode(j)->convert2X3d();
6584 m_root->convert2X3d();
6585 }
6586 }
6587
6588 void
setX3dv(void)6589 Scene::setX3dv(void)
6590 {
6591 setX3d();
6592 if (!(m_writeFlags & PURE_X3DV))
6593 m_writeFlags |= X3DV;
6594 }
6595
6596 void
setX3dXml(void)6597 Scene::setX3dXml(void)
6598 {
6599 setX3d();
6600 if (!(m_writeFlags & X3D_XML)) {
6601 m_writeFlags |= X3D_XML;
6602 }
6603 }
6604
6605 void
setVrml(void)6606 Scene::setVrml(void)
6607 {
6608 m_writeFlags = m_writeFlags & ~(CONVERT2X3D);
6609 if (::isX3d(m_writeFlags) && (m_root != NULL)) {
6610 getNodes()->clearFlag(NODE_FLAG_CONVERTED);
6611 m_writeFlags |= CONVERT2VRML;
6612 m_writeFlags = m_writeFlags & ~(X3DV | X3D_XML);
6613 for (int i = 0; i < getNumProtos(); i++)
6614 for (int j = 0; j < getProto(i)->getNumNodes(); j++)
6615 getProto(i)->getNode(j)->convert2Vrml();
6616 m_root->convert2Vrml();
6617 }
6618 m_writeFlags = m_writeFlags & ~(X3DV | X3D_XML);
6619 }
6620
6621 void
convertProtos2X3d(void)6622 Scene::convertProtos2X3d(void) {
6623 ProtoMap::Chain::Iterator *j;
6624 for (int i = 0; i < m_protos.width(); i++)
6625 for (j = m_protos.chain(i).first(); j != NULL; j = j->next())
6626 j->item()->getData()->convert2X3d();
6627 }
6628
6629 void
convertProtos2Vrml(void)6630 Scene::convertProtos2Vrml(void) {
6631 ProtoMap::Chain::Iterator *j;
6632 for (int i = 0; i < m_protos.width(); i++)
6633 for (j = m_protos.chain(i).first(); j != NULL; j = j->next())
6634 j->item()->getData()->convert2Vrml();
6635 }
6636
6637 bool
isInvalidElement(Element * element)6638 Scene::isInvalidElement(Element *element)
6639 {
6640 bool x3d = isX3d();
6641 return !isValidElement(element, x3d);
6642 }
6643
6644 bool
isValidElement(Element * element,bool x3d)6645 Scene::isValidElement(Element *element, bool x3d)
6646 {
6647 if (element == NULL)
6648 return false;
6649 int flags = element->getFlags();
6650 if (flags & FF_ALWAYS)
6651 return true;
6652 bool invalidX3d = (flags & FF_X3D_ONLY) && (!x3d);
6653 bool invalidKambi = (flags & FF_KAMBI_ONLY) && (!TheApp->getKambiMode());
6654 bool invalidX3dom = (flags & FF_X3DOM_ONLY) && (!TheApp->getX3domMode());
6655 bool invalidX3dKambi = (flags & (FF_X3D_ONLY | FF_KAMBI_ONLY)) &&
6656 ((!x3d) && (!TheApp->getKambiMode()));
6657 if (
6658 (flags & FF_NEVER) ||
6659 invalidX3d || invalidKambi || invalidX3dKambi || invalidX3dom ||
6660 ((flags & FF_VRML_ONLY) && x3d) ||
6661 ((flags & FF_COVER_ONLY) && (!TheApp->getCoverMode())) ||
6662 ((flags & FF_ROOT_ONLY) && (getSelection()->getNode() != getRoot()))
6663 )
6664 return false;
6665 return true;
6666 }
6667
6668
6669 void
resetWriteFlags(int flags)6670 Scene::resetWriteFlags(int flags)
6671 {
6672 if (::isX3d(m_writeFlags) && (!::isX3d(flags)) && (m_root != NULL)) {
6673 m_writeFlags = flags & ~(CONVERT2X3D);
6674 m_writeFlags |= CONVERT2VRML;
6675 m_root->clearFlagRec(NODE_FLAG_CONVERTED);
6676 m_root->convert2Vrml();
6677 }
6678 if ((!::isX3d(m_writeFlags)) && ::isX3d(flags) && (m_root != NULL)) {
6679 m_writeFlags = flags & ~(CONVERT2VRML);
6680 m_writeFlags |= CONVERT2X3D;
6681 m_root->clearFlagRec(NODE_FLAG_CONVERTED);
6682 m_root->convert2X3d();
6683 }
6684 m_writeFlags = flags & ~(CONVERT2VRML | CONVERT2X3D);
6685 }
6686
6687 void
changeRoutes(Node * toNode,int toField,Node * fromNode,int fromField)6688 Scene::changeRoutes(Node *toNode, int toField,
6689 Node *fromNode, int fromField)
6690 {
6691 changeRoutes(toNode, toField, 0, fromNode, fromField, 0);
6692 }
6693
6694 void
changeRoutes(Node * toNode,int toField,int toOffset,Node * fromNode,int fromField,int fromOffset)6695 Scene::changeRoutes(Node *toNode, int toField, int toOffset,
6696 Node *fromNode, int fromField, int fromOffset)
6697 {
6698 SocketList::Iterator *i = NULL;
6699 CommandList *list = NULL;
6700
6701 bool fromX3d = false;
6702 bool toX3d = false;
6703
6704 Proto *fProto = fromNode->getProto();
6705 Field *fField = fProto->getField(fromField);
6706 int fEventIn = fProto->lookupEventIn(fField->getName(fromX3d), fromX3d);
6707 int fEventOut = fProto->lookupEventOut(fField->getName(fromX3d), fromX3d);
6708
6709 Proto *tProto = toNode->getProto();
6710 Field *tField = tProto->getField(toField);
6711 int tEventIn = tProto->lookupEventIn(tField->getName(toX3d), toX3d);
6712 int tEventOut = tProto->lookupEventOut(tField->getName(toX3d), toX3d);
6713
6714 if (fEventIn != -1)
6715 for (i = fromNode->getInput(fEventIn).first(); i != NULL;
6716 i = i->next()) {
6717 if (list == NULL)
6718 list = new CommandList();
6719 list->append(new UnRouteCommand(i->item().getNode(),
6720 i->item().getField(),
6721 fromNode,
6722 fEventIn + fromOffset));
6723 list->append(new RouteCommand(i->item().getNode(),
6724 i->item().getField(),
6725 toNode, tEventIn + toOffset));
6726 }
6727 if (fEventOut != -1)
6728 for (i = fromNode->getOutput(fEventOut).first(); i != NULL;
6729 i = i->next()) {
6730 if (list == NULL)
6731 list = new CommandList();
6732 list->append(new UnRouteCommand(fromNode, fEventOut + fromOffset,
6733 i->item().getNode(),
6734 i->item().getField()));
6735
6736 list->append(new RouteCommand(toNode, tEventOut + toOffset,
6737 i->item().getNode(),
6738 i->item().getField()));
6739 }
6740 if (list) execute(list);
6741 }
6742
6743 void
copyRoutes(Node * toNode,Node * fromNode)6744 Scene::copyRoutes(Node *toNode, Node *fromNode)
6745 {
6746 int j = -1;
6747 SocketList::Iterator *i = NULL;
6748 SocketList::Iterator *last = NULL;
6749 CommandList *list = NULL;
6750
6751 Proto *fromProto = fromNode->getProto();
6752
6753 for (j = 0; j < fromProto->getNumEventIns(); j++) {
6754 last = fromNode->getInput(j).last();
6755 for (i = fromNode->getInput(j).first(); i != NULL;
6756 i = i->next()) {
6757 if (list == NULL)
6758 list = new CommandList();
6759 list->append(new RouteCommand(i->item().getNode(),
6760 i->item().getField(),
6761 toNode, j));
6762 if (i == last)
6763 break;
6764 }
6765 }
6766
6767 for (j = 0; j < fromProto->getNumEventOuts(); j++) {
6768 last = fromNode->getInput(j).last();
6769 for (i = fromNode->getOutput(j).first(); i != NULL;
6770 i = i->next()) {
6771 if (list == NULL)
6772 list = new CommandList();
6773 list->append(new RouteCommand(toNode, j,
6774 i->item().getNode(),
6775 i->item().getField()));
6776 if (i == last)
6777 break;
6778 }
6779 }
6780 if (list)
6781 execute(list);
6782 }
6783
6784 void
copyRoutesToScene(Node * node)6785 Scene::copyRoutesToScene(Node *node) {
6786 int j = -1;
6787 SocketList::Iterator *i = NULL;
6788 CommandList *list = NULL;
6789
6790 Proto *fromProto = node->getProto();
6791
6792 for (j = 0; j < fromProto->getNumEventIns(); j++)
6793 for (i = node->getInput(j).first(); i != NULL;
6794 i = i->next()) {
6795 if (list == NULL)
6796 list = new CommandList();
6797 list->append(new RouteCommand(i->item().getNode(),
6798 i->item().getField(),
6799 node, j));
6800 }
6801 for (j = 0; j < fromProto->getNumEventOuts(); j++)
6802 for (i = node->getOutput(j).first(); i != NULL;
6803 i = i->next()) {
6804 if (list == NULL)
6805 list = new CommandList();
6806 list->append(new RouteCommand(node, j, i->item().getNode(),
6807 i->item().getField()));
6808 }
6809 if (list)
6810 execute(list);
6811
6812 }
6813
6814
searchBindableNodes(Node * node,void * data)6815 static bool searchBindableNodes(Node *node, void *data)
6816 {
6817 Scene *scene = (Scene *)data;
6818 if (node->getType() == VRML_VIEWPOINT)
6819 scene->addViewpoint(node);
6820 if (node->getType() == VRML_GEO_VIEWPOINT)
6821 scene->addViewpoint(node);
6822 else if (node->getType() == X3D_ORTHO_VIEWPOINT)
6823 scene->addViewpoint(node);
6824 else if (node->getType() == VRML_NAVIGATION_INFO)
6825 scene->addNavigationInfo(node);
6826 else if (node->getType() == VRML_BACKGROUND)
6827 scene->addBackground(node);
6828 else if (node->getType() == VRML_FOG)
6829 scene->addFog(node);
6830 return true;
6831 }
6832
6833 void
findBindableNodes(void)6834 Scene::findBindableNodes(void)
6835 {
6836 if (m_root != NULL)
6837 m_root->doWithBranch(searchBindableNodes, this);
6838 setFirstNavigationInfo();
6839 }
6840
convertToTriangleSet(Node * node,void * data)6841 static bool convertToTriangleSet(Node *node, void *data)
6842 {
6843 Scene *scene = (Scene *)data;
6844 if (node->canConvertToTriangleSet())
6845 scene->convertToTriangleSet(node);
6846 return true;
6847 }
6848
6849 Node *
convertToTriangleSet(Node * node)6850 Scene::convertToTriangleSet(Node* node)
6851 {
6852 if (!node->canConvertToTriangleSet())
6853 return NULL;
6854
6855 NodeTriangleSet *triangleNode = (NodeTriangleSet *)node->toTriangleSet();
6856
6857 return replaceNode(node, triangleNode);
6858 }
6859
branchConvertToTriangleSet(Node * node)6860 void Scene::branchConvertToTriangleSet(Node *node)
6861 {
6862 node->doWithBranch(::convertToTriangleSet, this);
6863 }
6864
6865 Node *
convertToIndexedTriangleSet(Node * node)6866 Scene::convertToIndexedTriangleSet(Node* node)
6867 {
6868 if (!node->canConvertToIndexedTriangleSet())
6869 return NULL;
6870
6871 NodeIndexedTriangleSet *meshNode = (NodeIndexedTriangleSet *)
6872 node->toIndexedTriangleSet();
6873
6874 return replaceNode(node, meshNode);
6875 }
6876
convertToIndexedTriangleSet(Node * node,void * data)6877 static bool convertToIndexedTriangleSet(Node *node, void *data)
6878 {
6879 Scene *scene = (Scene *)data;
6880 if (node->canConvertToIndexedTriangleSet())
6881 scene->convertToIndexedTriangleSet(node);
6882 return true;
6883 }
6884
branchConvertToIndexedTriangleSet(Node * node)6885 void Scene::branchConvertToIndexedTriangleSet(Node *node)
6886 {
6887 node->doWithBranch(::convertToIndexedTriangleSet, this);
6888 }
6889
convertToIndexedFaceSet(Node * node,void * data)6890 static bool convertToIndexedFaceSet(Node *node, void *data)
6891 {
6892 Scene *scene = (Scene *)data;
6893 if (node->canConvertToIndexedFaceSet())
6894 scene->convertToIndexedFaceSet(node);
6895 return true;
6896 }
6897
branchConvertToIndexedFaceSet(Node * node)6898 void Scene::branchConvertToIndexedFaceSet(Node *node)
6899 {
6900 node->doWithBranch(::convertToIndexedFaceSet, this);
6901 }
6902
createNormals(Node * node,void * data)6903 static bool createNormals(Node *node, void *data)
6904 {
6905 int normalField = node->getNormalField();
6906 if (normalField == -1)
6907 return true;
6908 // ignore Nodes with already set normal field
6909 if (((SFNode *)node->getField(normalField))->getValue() == NULL) {
6910 Node *nnormal = node->getScene()->createNode("Normal");
6911 if (nnormal != NULL) {
6912 MoveCommand *command = new MoveCommand(nnormal, NULL, -1,
6913 node, normalField);
6914 command->execute();
6915 node->setNormalFromMesh(nnormal);
6916 }
6917 }
6918 return true;
6919 }
6920
branchCreateNormals(Node * node)6921 void Scene::branchCreateNormals(Node *node)
6922 {
6923 node->doWithBranch(createNormals, NULL);
6924 }
6925
createNormal(Node * node)6926 void Scene::createNormal(Node *node)
6927 {
6928 ::createNormals(node, NULL);
6929 }
6930
createTextureCoordinates(Node * node,void * data)6931 static bool createTextureCoordinates(Node *node, void *data)
6932 {
6933 int texCoordField = node->getTexCoordField();
6934 if (texCoordField == -1)
6935 return true;
6936 // ignore Nodes with already set texCoord field
6937 if (((SFNode *)node->getField(texCoordField))->getValue() == NULL) {
6938 Node *ntexCoord = node->getScene()->createNode("TextureCoordinate");
6939 if (ntexCoord != NULL) {
6940 MoveCommand *command = new MoveCommand(ntexCoord, NULL, -1,
6941 node, texCoordField);
6942 command->execute();
6943 node->setTexCoordFromMesh(ntexCoord);
6944 }
6945 }
6946 return true;
6947 }
6948
6949 void
branchCreateTextureCoordinates(Node * node)6950 Scene::branchCreateTextureCoordinates(Node *node)
6951 {
6952 node->doWithBranch(createTextureCoordinates, NULL);
6953 }
6954
6955 void
createTextureCoordinate(Node * node)6956 Scene::createTextureCoordinate(Node *node)
6957 {
6958 ::createTextureCoordinates(node, NULL);
6959 }
6960
6961 bool
checkXSymetricOrSameHandle(int handle,MFVec3f * points)6962 Scene::checkXSymetricOrSameHandle(int handle, MFVec3f *points)
6963 {
6964 if ((handle >= points->getSFSize()) || (handle < 0))
6965 return true;
6966 Vec3f vIndex = points->getValue(handle);
6967 float epsilon = TheApp->GetHandleEpsilon();
6968 for (int i = 0; i < getSelectedHandlesSize(); i++) {
6969 int checkedHandle = getSelectedHandle(i);
6970 if ((checkedHandle >= points->getSFSize()) || (checkedHandle < 0))
6971 continue;
6972 if (checkedHandle != handle) {
6973 Vec3f vPoint = points->getValue(checkedHandle);
6974 if ( (fabs(vPoint.z - vIndex.z) < epsilon)
6975 && (fabs(vPoint.y - vIndex.y) < epsilon)) {
6976 if (fabs(vPoint.x - vIndex.x) < epsilon) {
6977 if (isSingleSelectedHandle())
6978 return true;
6979 } else
6980 if (fabs(vPoint.x + vIndex.x) < epsilon)
6981 return true;
6982 }
6983 }
6984 }
6985 return false;
6986 }
6987
6988 void
addMeta(const char * metaKey,const char * metaValue)6989 Scene::addMeta(const char *metaKey, const char* metaValue)
6990 {
6991 m_metaKeys.append(metaKey);
6992 m_metaValues.append(metaValue);
6993 }
6994
6995 void
addUnit(const char * category,const char * name,double conversionFactor)6996 Scene::addUnit(const char *category, const char *name,
6997 double conversionFactor)
6998 {
6999 int found = -1;
7000 for (long i = 0; i < m_unitCategory.size(); i++)
7001 if (strcmp(m_unitCategory[i], category) == 0) {
7002 found = i;
7003 break;
7004 }
7005 if (found > -1) {
7006 m_unitName[found] = name;
7007 m_unitConversionFactor[found] = conversionFactor;
7008 } else {
7009 m_unitCategory.append(category);
7010 m_unitName.append(name);
7011 m_unitConversionFactor.append(conversionFactor);
7012 }
7013 setUnitLengthInit();
7014 setUnitAngleInit();
7015 SceneProtoMap::updateProtoMap(&m_protos, this);
7016 }
7017
7018 void
setUnitLength(double f)7019 Scene::setUnitLength(double f)
7020 {
7021 m_unitLength = f;
7022 }
7023
7024 void
setUnitLengthInit(void)7025 Scene::setUnitLengthInit(void)
7026 {
7027 for (long i = 0; i < m_unitCategory.size(); i++)
7028 if (strcmp(m_unitCategory[i], "length") == 0)
7029 m_unitLength = m_unitConversionFactor[i];
7030 }
7031
7032 void
setUnitAngleInit(void)7033 Scene::setUnitAngleInit(void)
7034 {
7035 for (long i = 0; i < m_unitCategory.size(); i++)
7036 if (strcmp(m_unitCategory[i], "angle") == 0)
7037 m_unitAngle = m_unitConversionFactor[i];
7038 }
7039
7040 void
setUnitAngle(double f)7041 Scene::setUnitAngle(double f)
7042 {
7043 m_unitAngle = f;
7044 }
7045
7046 void
pushUnitLength(void)7047 Scene::pushUnitLength(void)
7048 {
7049 m_unitLengthStack.push(getUnitLength());
7050 }
7051
7052 void
popUnitLength(void)7053 Scene::popUnitLength(void)
7054 {
7055 if (m_unitLengthStack.empty())
7056 setUnitLength(1);
7057 else
7058 setUnitLength(m_unitLengthStack.pop());
7059 }
7060
7061 void
pushUnitAngle(void)7062 Scene::pushUnitAngle(void)
7063 {
7064 m_unitAngleStack.push(getUnitAngle());
7065 }
7066
7067 void
popUnitAngle(void)7068 Scene::popUnitAngle(void)
7069 {
7070 if (m_unitAngleStack.empty())
7071 setUnitAngle(1);
7072 else
7073 setUnitAngle(m_unitAngleStack.pop());
7074 }
7075
7076 void
addToSensorNodes(Node * node)7077 Scene::addToSensorNodes(Node *node)
7078 {
7079 for (long i = 0; i < m_sensorNodes.size(); i++)
7080 if (m_sensorNodes.get(i) == node)
7081 return;
7082 m_sensorNodes.append(node);
7083 }
7084
7085 void
restoreSelectedHandles(void)7086 Scene::restoreSelectedHandles(void)
7087 {
7088 m_selectedHandles.resize(0);
7089 if (m_oldSelectedHandles.size() > 0) {
7090 for (long i = 0; i < m_oldSelectedHandles.size(); i++)
7091 m_selectedHandles.append(m_oldSelectedHandles[i]);
7092 m_lastSelectedHandle = m_oldLastSelectedHandle;
7093 m_singleSelectedHandle = m_selectedHandles.size() <= 1;
7094 } else {
7095 m_lastSelectedHandle = -1;
7096 m_singleSelectedHandle = true;
7097 }
7098 m_isNewSelectedHandle = false;
7099 setSelection(m_oldSelection->getPath());
7100 UpdateViews(NULL, UPDATE_SELECTION);
7101 }
7102
7103 int
getX3dVersion(void)7104 Scene::getX3dVersion(void)
7105 {
7106 int ret = m_x3dVersion;
7107 const NodeList *nodes = getNodes();
7108 for (long i = 0; i < nodes->size(); i++) {
7109 Node *node = nodes->get(i);
7110 if (node->getX3dVersion() > ret)
7111 ret = node->getX3dVersion();
7112 }
7113
7114 if (scene != NULL) {
7115 scene->setParsedX3dVersion(ret);
7116 scene->updateSceneMap();
7117 }
7118
7119 return ret;
7120 }
7121
7122 static Node *returnNode;
7123
searchNodeById(Node * node,void * data)7124 static bool searchNodeById(Node *node, void *data)
7125 {
7126 int *id = (int *)data;
7127 if ((node != NULL) && (node->getId() == (*id))) {
7128 returnNode = node;
7129 return false;
7130 }
7131 return true;
7132 }
7133
7134
7135 Node *
searchProtoNodeIdInNode(Node * node,long id)7136 Scene::searchProtoNodeIdInNode(Node *node, long id)
7137 {
7138 returnNode = NULL;
7139 if (node->isPROTO()) {
7140 NodePROTO *nodePROTO = (NodePROTO *)node;
7141 for (int i = 0; i < nodePROTO->getNumIndexedNodes(); i++)
7142 if (nodePROTO->getIndexedNode(i)->getId() == id)
7143 returnNode = nodePROTO->getIndexedNode(i);
7144 }
7145 return returnNode;
7146 }
7147
7148 Node *
searchProtoNodeId(long id)7149 Scene::searchProtoNodeId(long id)
7150 {
7151 returnNode = NULL;
7152 for (long i = 0; i < m_nodes.size(); i++)
7153 if (m_nodes.get(i)->isPROTO()) {
7154 NodePROTO *protoNode = (NodePROTO *)m_nodes.get(i);
7155 for (int j = 0; j < protoNode->getNumProtoNodes(); j++) {
7156 Node *rootNode = protoNode->getProtoNode(j);
7157 rootNode->doWithBranch(searchNodeById, &id);
7158 }
7159 }
7160 return returnNode;
7161 }
7162
7163 int
getProtoType(Proto * proto)7164 Scene::getProtoType(Proto *proto)
7165 {
7166 int lastNodeType = LAST_NODE;
7167 ProtoMap::Chain::Iterator *j;
7168 for (j = m_protos.getExtraData(); j != NULL; j = j->next()) {
7169 Proto *jproto = j->item()->getData();
7170 lastNodeType++;
7171 if (jproto == proto) {
7172 return lastNodeType;
7173 }
7174 }
7175 return -1;
7176 }
7177
7178 void
setSelectionMode(int mode)7179 Scene::setSelectionMode(int mode)
7180 {
7181 int oldMode = getSelectionMode();
7182 m_selectionMode = mode;
7183 if (oldMode != mode) {
7184 Node *node = getSelection()->getNode();
7185 NodeIndexedFaceSet *faceSet = NULL;
7186 MyMesh *mesh = NULL;
7187 MFInt32 *ci = NULL;
7188 if (node->hasParent())
7189 if (node->getParent()->getType() == VRML_INDEXED_FACE_SET) {
7190 faceSet = (NodeIndexedFaceSet *)node->getParent();
7191 mesh = faceSet->getMesh();
7192 ci = mesh->getCoordIndex();
7193 }
7194 if (faceSet == NULL)
7195 return;
7196 MyArray<int> oldSelection;
7197 for (int i = 0; i < getSelectedHandlesSize(); i++)
7198 oldSelection.append(getSelectedHandle(i));
7199 removeSelectedHandles();
7200
7201 if ((oldMode == SELECTION_MODE_FACES) &&
7202 (mode == SELECTION_MODE_VERTICES)) {
7203 for (long i = 0; i < oldSelection.size(); i++) {
7204 int handle = oldSelection[i];
7205 for (int j = 0; j < mesh->getNumFaces(); j++) {
7206 FaceData *face = mesh->getFace(j);
7207 if (handle == j) {
7208 int offset = face->getOffset();
7209 for (int n = offset; n < offset +
7210 face->getNumVertices(); n++)
7211 addSelectedHandle(ci->getValue(n));
7212 }
7213
7214 }
7215 }
7216 UpdateViews(NULL, UPDATE_REDRAW_3D, NULL);
7217 } else if ((oldMode == SELECTION_MODE_VERTICES) &&
7218 (mode == SELECTION_MODE_FACES)) {
7219 for (int j = 0; j < mesh->getNumFaces(); j++) {
7220 FaceData *face = mesh->getFace(j);
7221 int offset = face->getOffset();
7222 int vertexCount = 0;
7223 for (int n = offset; n < offset + face->getNumVertices(); n++) {
7224 for (long i = 0; i < oldSelection.size(); i++) {
7225 int handle = oldSelection[i];
7226 int meshVertex = ci->getValue(n);
7227 if (meshVertex == handle)
7228 vertexCount++;
7229 }
7230 }
7231 if (vertexCount >= face->getNumVertices())
7232 addSelectedHandle(j);
7233 }
7234 UpdateViews(NULL, UPDATE_REDRAW_3D, NULL);
7235 }
7236 }
7237 }
7238
7239
7240 void
addSelectionRange(int firstRangeHandle,int secondRangeHandle)7241 Scene::addSelectionRange(int firstRangeHandle, int secondRangeHandle)
7242 {
7243 if ((firstRangeHandle > -1) && (m_selection)) {
7244 Node *node = m_selection->getNode();
7245 if (node == NULL)
7246 return;
7247 Vec3f first = node->getVertex(firstRangeHandle);
7248 Vec3f second = node->getVertex(secondRangeHandle);
7249 float len = (second - first).length();
7250 bool addedHandle = false;
7251 for (int i = 0; i < node->getNumVertex(); i++) {
7252 if (i == firstRangeHandle)
7253 continue;
7254 if (i == secondRangeHandle)
7255 continue;
7256 if (node->validHandle(i) &&
7257 (node->getVertex(i) - first).length() - len <=
7258 TheApp->GetHandleEpsilon()) {
7259 if (addSelectedHandle(i))
7260 addedHandle = true;
7261 }
7262 }
7263 if (addedHandle) {
7264 UpdateViews(NULL, UPDATE_REDRAW_3D);
7265 m_firstSelectionRangeHandle = -1;
7266 m_isNewSelectedHandle = false;
7267 }
7268 }
7269 }
7270
7271 void
hideSelectedVertices(void)7272 Scene::hideSelectedVertices(void)
7273 {
7274 float epsilon = TheApp->GetHandleEpsilon();
7275 Node *node = getSelection()->getNode();
7276 for (int i = 0; i < getSelectedHandlesSize(); i++) {
7277 if (getXSymetricMode() && node->validHandle(getSelectedHandle(i))) {
7278 Vec3f vertex = node->getVertex(getSelectedHandle(i));
7279 for (int j = 0; j < node->getNumVertex(); j++) {
7280 Vec3f vec = node->getVertex(j);
7281 if ((fabsf(vertex.x + vec.x) < epsilon) &&
7282 (fabsf(vertex.y - vec.y) < epsilon) &&
7283 (fabsf(vertex.z - vec.z) < epsilon))
7284 m_hiddenVertices.append(j);
7285 }
7286 }
7287 if (node->validHandle(getSelectedHandle(i))) {
7288 Vec3f vertex = node->getVertex(getSelectedHandle(i));
7289 for (int j = 0; j < node->getNumVertex(); j++) {
7290 Vec3f vec = node->getVertex(j);
7291 if ((fabsf(vertex.x - vec.x) < epsilon) &&
7292 (fabsf(vertex.y - vec.y) < epsilon) &&
7293 (fabsf(vertex.z - vec.z) < epsilon))
7294 m_hiddenVertices.append(j);
7295 }
7296 }
7297 m_hiddenVertices.append(getSelectedHandle(i));
7298 }
7299 }
7300
7301 void
showOnlySelectedVertices(void)7302 Scene::showOnlySelectedVertices(void)
7303 {
7304 float epsilon = TheApp->GetHandleEpsilon();
7305 Node *node = getSelection()->getNode();
7306 IntArray notHiddenVertices;
7307 for (int i = 0; i < getSelectedHandlesSize(); i++) {
7308 if (getXSymetricMode() && node->validHandle(getSelectedHandle(i))) {
7309 Vec3f vertex = node->getVertex(getSelectedHandle(i));
7310 for (int j = 0; j < node->getNumVertex(); j++) {
7311 Vec3f vec = node->getVertex(j);
7312 if ((fabsf(vertex.x + vec.x) < epsilon) &&
7313 (fabsf(vertex.y - vec.y) < epsilon) &&
7314 (fabsf(vertex.z - vec.z) < epsilon))
7315 notHiddenVertices.append(j);
7316 }
7317 }
7318 if (node->validHandle(getSelectedHandle(i))) {
7319 Vec3f vertex = node->getVertex(getSelectedHandle(i));
7320 for (int j = 0; j < node->getNumVertex(); j++) {
7321 Vec3f vec = node->getVertex(j);
7322 if ((fabsf(vertex.x - vec.x) < epsilon) &&
7323 (fabsf(vertex.y - vec.y) < epsilon) &&
7324 (fabsf(vertex.z - vec.z) < epsilon))
7325 notHiddenVertices.append(j);
7326 }
7327 }
7328 notHiddenVertices.append(getSelectedHandle(i));
7329 }
7330 for (int i = 0; i < node->getNumVertex(); i++) {
7331 bool skip = false;
7332 for (long j = 0; j < notHiddenVertices.size(); j++)
7333 if (i == notHiddenVertices[j]) {
7334 skip = true;
7335 break;
7336 }
7337 if (!skip)
7338 m_hiddenVertices.append(i);
7339 }
7340 }
7341
7342 void
warning(const char * string)7343 Scene::warning(const char* string)
7344 {
7345 int newIndex = m_warnings.size();
7346 m_warnings[newIndex] = "";
7347 m_warnings[newIndex] += string;
7348 swDebugf("%s\n", string);
7349 }
7350
7351 MyArray<Node *> *
getViewPorts()7352 Scene::getViewPorts()
7353 {
7354 return &m_viewports;
7355 }
7356
7357
7358 void
warning(int id)7359 Scene::warning(int id)
7360 {
7361 char message[256];
7362 swLoadString(id, message, 255);
7363 warning(message);
7364 }
7365
7366 void
warning(int id,const char * string)7367 Scene::warning(int id, const char *string)
7368 {
7369 char idText[256];
7370 static char text[256];
7371 swLoadString(id, idText, 255);
7372 mysnprintf(text, 255, idText, string);
7373 warning(text);
7374 }
7375
7376 void
addToStore4ConvexHull(void)7377 Scene::addToStore4ConvexHull(void)
7378 {
7379 if (getSelectionMode() != SELECTION_MODE_VERTICES)
7380 return;
7381 Node *node = getSelection()->getNode();
7382 if (!node->getValidVertex())
7383 return;
7384
7385 static Matrix transformMatrix;
7386 Path *trans = searchTransform();
7387 Node *transform = NULL;
7388 if (trans)
7389 transform = trans->getNode();
7390 if (transform) {
7391 transform->transform();
7392 transform->getMatrix(transformMatrix);
7393 }
7394 bool changed = false;
7395 float eps = TheApp->GetHandleEpsilon();
7396 for (int i = 0; i < getSelectedHandlesSize(); i++) {
7397 int handle = getSelectedHandle(i);
7398 if (handle >= NO_HANDLE)
7399 continue;
7400 Vec3f vertex = node->getVertex(handle);
7401 // also collect symetric handles
7402 if (getXSymetricMode())
7403 for (int j = 0; j < node->getNumVertex(); j++) {
7404 if (j == handle)
7405 continue;
7406 Vec3f vec = node->getVertex(j);
7407 if (vec.x != 0) {
7408 if ((fabs(vertex.x + vec.x) < eps) &&
7409 (fabs(vertex.y - vec.y) < eps) &&
7410 (fabs(vertex.x - vec.z) < eps)) {
7411 m_store4ConvexHull.append(transformMatrix * vec);
7412 if ((m_convexHullCounter % 2) == 1)
7413 m_store4Extrusion1ConvexHull.append(
7414 transformMatrix * vec);
7415 else
7416 m_store4Extrusion2ConvexHull.append(
7417 transformMatrix * vec);
7418 break;
7419 }
7420 }
7421 }
7422 m_store4ConvexHull.append(transformMatrix * vertex);
7423 if ((m_convexHullCounter % 2) == 1)
7424 m_store4Extrusion1ConvexHull.append(transformMatrix * vertex);
7425 else
7426 m_store4Extrusion2ConvexHull.append(transformMatrix * vertex);
7427 changed = true;
7428 }
7429 if (changed)
7430 m_convexHullCounter++;
7431
7432 }
7433
7434 void
storeHtmlData(const char * data)7435 Scene::storeHtmlData(const char *data)
7436 {
7437 if (data)
7438 if (m_htmlData.size() > 0)
7439 m_htmlData[m_htmlData.size() - 1] += data;
7440 }
7441
7442 void
storeHtmlElementAndAttributes(const char * element,const char ** attributes,int numAttributes,bool htmlFirstPart)7443 Scene::storeHtmlElementAndAttributes(const char *element,
7444 const char **attributes,
7445 int numAttributes, bool htmlFirstPart)
7446 {
7447 MyString begin = "";
7448 MyString end = "";
7449 if (strlen(element) > 0) {
7450 begin += "<";
7451 begin += element;
7452 for (int i = 0; i < numAttributes; i += 2) {
7453 begin += " ";
7454 begin += attributes[i];
7455 begin += "=";
7456 begin += "'";
7457 if (i + 1 < numAttributes)
7458 begin += attributes[i + 1];
7459 begin += "'";
7460 }
7461 begin += ">";
7462
7463 end += "</";
7464 end += element;
7465 end += ">";
7466 }
7467 m_htmlBegin.append(begin);
7468 m_htmlData.append("");
7469 m_htmlEnd.append(end);
7470 m_htmlFirstPart.append(htmlFirstPart);
7471 }
7472
searchPROTO(Node * node,void * data)7473 static bool searchPROTO(Node *node, void *data)
7474 {
7475 bool *result = (bool *)data;
7476 if (node->isPROTO())
7477 *result = true;
7478 return true;
7479 }
7480
7481
7482 bool
hasPROTONodes(void)7483 Scene::hasPROTONodes(void)
7484 {
7485 bool result = false;
7486 m_root->doWithBranch(searchPROTO, &result, true, false, false, true, false);
7487 return result;
7488 }
7489
setBoundingBox(Node * node,void * data)7490 static bool setBoundingBox(Node *node, void *data)
7491 {
7492 if (node != NULL)
7493 node->setBoundingBox();
7494 return true;
7495 }
7496
7497 void
branchSetBbox(void)7498 Scene::branchSetBbox(void)
7499 {
7500 m_root->doWithBranch(setBoundingBox, NULL, false);
7501 }
7502
7503
7504 MyArray<Node *>*
searchInterpolators(void)7505 Scene::searchInterpolators(void)
7506 {
7507 MyArray<Node *> *targets;
7508 Node *node = getSelection()->getNode();
7509 for (int i = 0; i < node->getProto()->getNumEventIns(); i++) {
7510 for (SocketList::Iterator *j = node->getInput(i).first();
7511 j != NULL; j = j->next()) {
7512 Node *inputNode = j->item().getNode();
7513 if (!inputNode->isInterpolator())
7514 continue;
7515 bool targetIsNew = true;
7516 for (long n = 0; n < targets->size(); n++)
7517 if (inputNode == targets->get(n))
7518 targetIsNew = false;
7519 if (targetIsNew)
7520 targets->append(inputNode);
7521 }
7522 }
7523 return targets;
7524 }
7525
7526 NodeList
searchTimeSensorInInterpolator(Node * interpolator)7527 Scene::searchTimeSensorInInterpolator(Node *interpolator)
7528 {
7529 NodeList targets;
7530 for (int k = 0; k < interpolator->getProto()->getNumEventIns(); k++) {
7531 for (SocketList::Iterator *l = interpolator->getInput(k).first();
7532 l != NULL; l = l->next()) {
7533 Node *targetNode = l->item().getNode();
7534 if (targetNode->getType() != VRML_TIME_SENSOR)
7535 continue;
7536 bool targetIsNew = true;
7537 for (long n = 0; n < targets.size(); n++)
7538 if (targetNode == targets[n])
7539 targetIsNew = false;
7540 if (targetIsNew)
7541 targets.append(targetNode);
7542 }
7543 }
7544 return targets;
7545 }
7546
7547 MyArray<Node *> *
searchTimeSensors(void)7548 Scene::searchTimeSensors(void)
7549 {
7550 MyArray<Node *> *targets;
7551 Node *node = getSelection()->getNode();
7552 if (node->isInterpolator())
7553 targets = searchTimeSensorInInterpolator(node).copy();
7554 else {
7555 if (!node->hasInputs())
7556 return targets;
7557 for (int i = 0; i < node->getProto()->getNumEventIns(); i++) {
7558 for (SocketList::Iterator *j = node->getInput(i).first(); j != NULL;
7559 j = j->next()) {
7560 Node *inputNode = j->item().getNode();
7561 if (!inputNode->isInterpolator())
7562 continue;
7563 NodeList interpolatorTargets;
7564 searchTimeSensorInInterpolator(inputNode).copy();
7565 for (int i = 0; i < interpolatorTargets.size(); i++)
7566 targets->append(interpolatorTargets[i]);
7567 }
7568 }
7569 }
7570 return targets;
7571 }
7572
7573 void
removeUse(Node * node)7574 Scene::removeUse(Node *node)
7575 {
7576 unuse(node->getName());
7577 UpdateViews(NULL, UPDATE_ALL, NULL);
7578 }
7579
7580 void
makeEmpty(void)7581 Scene::makeEmpty(void)
7582 {
7583 NodeGroup *root = (NodeGroup *)getRoot();
7584 for (int i = 0; i < root->getChildren()->getSize(); i++) {
7585 MoveCommand command(root, root->getChildren()->getValue(i), i,
7586 NULL, -1);
7587 command.execute();
7588 }
7589 }
7590
FieldUpdate(Node * n,int f,int i)7591 FieldUpdate::FieldUpdate(Node *n, int f, int i)
7592 {
7593 node = n;
7594 field = f;
7595 index = i;
7596 }
7597
7598 #include "MainWindow.h"
7599
CreateDC(SWND canvas)7600 SDC CreateDC(SWND canvas)
7601 {
7602 if (swFromPtr(canvas) == 0) {
7603 return swCreateDC(TheApp->getCurrentMainWindow()->getParentWindow());
7604 }
7605 return swCreateDC(canvas);
7606 }
7607