1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 /*!
34 \class SoWWWInline SoWWWInline.h Inventor/nodes/SoWWWInline.h
35 \brief The SoWWWInline class is a node used to include data from an URL.
36
37 \ingroup nodes
38
39 If the URL is not a local file, the application is responsible for
40 supplying a callback to a function which will fetch the data of the
41 URL.
42
43 As long as no data has been imported, the scenegraph representation
44 of the node will be that of a bounding box enclosing the geometry we
45 expect to fetch from the URL. The application is naturally also
46 responsible for specifying the expected dimensions of the geometry.
47
48 If FetchURLCallBack isn't set, the alternateRep will be rendered
49 instead.
50
51 <b>FILE FORMAT/DEFAULTS:</b>
52 \code
53 WWWInline {
54 name "<Undefined file>"
55 bboxCenter 0 0 0
56 bboxSize 0 0 0
57 alternateRep NULL
58 }
59 \endcode
60
61 \since SGI Inventor 2.1
62 \since Coin 1.0
63 */
64
65 // *************************************************************************
66
67 // FIXME: as far as I can tell, SoWWWInline does not automatically
68 // trigger a (re-)load when the "SoWWWInline::name" field
69 // changes. Shouldn't it? Test what SGI/TGS Inventor does and mimic
70 // its behaviour. 20020522 mortene.
71
72 // FIXME: setting up the alternateRep field doesn't seem to work as
73 // expected (or at all, actually). This simple scene graph shown in an
74 // examiner viewer will not display the alternateRep for Coin, while
75 // SGI Inventor ivview will correctly show the Cone:
76 // ----8<-------------- [snip] -------8<-------------- [snip] -------------
77 // #Inventor V2.1 ascii
78 //
79 // WWWInline { alternateRep Group { BaseColor { rgb .2 .4 .6 } Cone { } } }
80 // ----8<-------------- [snip] -------8<-------------- [snip] -------------
81 // 20050315 mortene.
82
83 // *************************************************************************
84
85 /*! \file SoWWWInline.h */
86 #include <Inventor/nodes/SoWWWInline.h>
87
88 #include <cstddef>
89 #include <cstdlib>
90 #include <cstdio>
91
92 #ifdef HAVE_CONFIG_H
93 #include <config.h>
94 #endif /* HAVE_CONFIG_H */
95
96 #include <Inventor/SbColor.h>
97 #include <Inventor/actions/SoGetBoundingBoxAction.h>
98 #include <Inventor/actions/SoGLRenderAction.h>
99 #include <Inventor/actions/SoSearchAction.h>
100 #include <Inventor/elements/SoGLMultiTextureEnabledElement.h>
101 #include <Inventor/elements/SoLazyElement.h>
102 #include <Inventor/bundles/SoMaterialBundle.h>
103 #include <Inventor/misc/SoChildList.h>
104 #include <Inventor/SbColor.h>
105 #include <Inventor/nodes/SoSeparator.h>
106 #include <Inventor/SoInput.h>
107 #include <Inventor/SoDB.h>
108 #include <Inventor/errors/SoReadError.h>
109 #include <Inventor/errors/SoDebugError.h>
110 #include <Inventor/threads/SbStorage.h>
111 #include <Inventor/system/gl.h>
112
113 #include "tidbitsp.h"
114 #include "coindefs.h" // COIN_OBSOLETED()
115 #include "nodes/SoSubNodeP.h"
116
117 // *************************************************************************
118
119 /*!
120 \enum SoWWWInline::BboxVisibility
121 Used to enumerate bbox rendering strategies.
122 */
123 /*!
124 \var SoWWWInline::BboxVisibility SoWWWInline::NEVER
125 Never render bounding box.
126 */
127 /*!
128 \var SoWWWInline::BboxVisibility SoWWWInline::UNTIL_LOADED
129 Render bounding box until children are loaded.
130 */
131 /*!
132 \var SoWWWInline::BboxVisibility SoWWWInline::ALWAYS
133 Always render bounding box, event when children are loaded.
134 */
135
136 /*!
137 \var SoSFString SoWWWInline::name
138 Name of file/URL where children should be read.
139 */
140
141 /*!
142 \var SoSFVec3f SoWWWInline::bboxCenter
143 Center of bounding box.
144 */
145 /*!
146 \var SoSFVec3f SoWWWInline::bboxSize
147 Size of bounding box.
148 */
149 /*!
150 \var SoSFNode SoWWWInline::alternateRep
151 Alternate representation. Used when children can't be read from name.
152 */
153
154 // *************************************************************************
155
156 // static members
157 SoWWWInlineFetchURLCB * SoWWWInline::fetchurlcb = NULL;
158 void * SoWWWInline::fetchurlcbdata = NULL;
159 SbColor * SoWWWInline::bboxcolor = NULL;
160 static SbStorage * wwwinline_colorpacker_storage = NULL;
161 SoWWWInline::BboxVisibility SoWWWInline::bboxvisibility = SoWWWInline::UNTIL_LOADED;
162 SbBool SoWWWInline::readassofile = FALSE;
163
alloc_colorpacker(void * ptr)164 static void alloc_colorpacker(void * ptr)
165 {
166 SoColorPacker ** cptr = (SoColorPacker**) ptr;
167 *cptr = new SoColorPacker;
168 }
169
free_colorpacker(void * ptr)170 static void free_colorpacker(void * ptr)
171 {
172 SoColorPacker ** cptr = (SoColorPacker**) ptr;
173 delete *cptr;
174 }
175
176 void
cleanup(void)177 SoWWWInline::cleanup(void)
178 {
179 delete SoWWWInline::bboxcolor;
180 SoWWWInline::bboxcolor = NULL;
181 delete wwwinline_colorpacker_storage;
182 wwwinline_colorpacker_storage = NULL;
183
184 SoWWWInline::fetchurlcb = NULL;
185 SoWWWInline::fetchurlcbdata = NULL;
186 SoWWWInline::bboxvisibility = SoWWWInline::UNTIL_LOADED;
187 SoWWWInline::readassofile = FALSE;
188 }
189
190 // *************************************************************************
191
192 class SoWWWInlineP {
193 public:
SoWWWInlineP(SoWWWInline * ownerptr)194 SoWWWInlineP(SoWWWInline * ownerptr) {
195 this->owner = ownerptr;
196 }
197 SoWWWInline * owner;
198 SoChildList * children;
199 SbBool readNamedFile();
200 SbBool readChildren();
201 SbString fullname;
202 SbBool didrequest;
203
204 static const char UNDEFINED_FILE[];
205 };
206
207 const char SoWWWInlineP::UNDEFINED_FILE[] = "<Undefined file>";
208
209 #define PRIVATE(obj) ((obj)->pimpl)
210
211 // *************************************************************************
212
213 SO_NODE_SOURCE(SoWWWInline);
214
215 // *************************************************************************
216
217 /*!
218 Constructor.
219 */
SoWWWInline()220 SoWWWInline::SoWWWInline()
221 {
222 SO_NODE_INTERNAL_CONSTRUCTOR(SoWWWInline);
223
224 PRIVATE(this) = new SoWWWInlineP(this);
225 PRIVATE(this)->children = new SoChildList(this);
226 PRIVATE(this)->didrequest = FALSE;
227
228 SO_NODE_ADD_FIELD(name, (SoWWWInlineP::UNDEFINED_FILE));
229 SO_NODE_ADD_FIELD(bboxCenter, (0.0f, 0.0f, 0.0f));
230 SO_NODE_ADD_FIELD(bboxSize, (0.0f, 0.0f, 0.0f));
231 SO_NODE_ADD_FIELD(alternateRep, (NULL));
232
233 // Instantiated dynamically to avoid problems on platforms with
234 // systemloaders that hate static constructors in C++ libraries.
235 if (SoWWWInline::bboxcolor == NULL) {
236 SoWWWInline::bboxcolor = new SbColor(0.8f, 0.8f, 0.8f);
237 wwwinline_colorpacker_storage = new SbStorage(sizeof(void*), alloc_colorpacker, free_colorpacker);
238 coin_atexit((coin_atexit_f *)SoWWWInline::cleanup, CC_ATEXIT_NORMAL);
239 }
240 }
241
242 /*!
243 Destructor.
244 */
~SoWWWInline()245 SoWWWInline::~SoWWWInline()
246 {
247 delete PRIVATE(this)->children;
248 delete PRIVATE(this);
249 }
250
251 // doc in super
252 void
initClass(void)253 SoWWWInline::initClass(void)
254 {
255 SO_NODE_INTERNAL_INIT_CLASS(SoWWWInline, SO_FROM_INVENTOR_2_1|SoNode::VRML1);
256 }
257
258 /*!
259 If the SoWWWInline::name field specifies a relative URL, use this
260 method to name the complete URL.
261 */
262 void
setFullURLName(const SbString & url)263 SoWWWInline::setFullURLName(const SbString & url)
264 {
265 PRIVATE(this)->fullname = url;
266 }
267
268 /*!
269 If a full URL has been set with the SoWWWInline::setFullURLName()
270 method, return it. If not, returns the value of the
271 SoWWWInline::name field.
272 */
273 const SbString &
getFullURLName(void)274 SoWWWInline::getFullURLName(void)
275 {
276 return PRIVATE(this)->fullname.getLength() ? PRIVATE(this)->fullname : this->name.getValue();
277 }
278
279 /*!
280 Returns a subgraph with a deep copy of the children of this node.
281 */
282 SoGroup *
copyChildren(void) const283 SoWWWInline::copyChildren(void) const
284 {
285 SoChildList * children = this->getChildren();
286
287 if (children->getLength() == 0) return NULL;
288 assert(children->getLength() == 1);
289 SoNode * rootcopy = (*children)[0]->copy();
290 assert(rootcopy->isOfType(SoGroup::getClassTypeId()));
291 return (SoGroup *) rootcopy;
292 }
293
294 /*!
295 Start requesting URL data. This might trigger a callback to
296 the callback set in SoWWWInline::setFetchURLCallBack().
297 */
298 void
requestURLData(void)299 SoWWWInline::requestURLData(void)
300 {
301 if (!PRIVATE(this)->didrequest) {
302 PRIVATE(this)->didrequest = TRUE;
303 (void) PRIVATE(this)->readChildren();
304 }
305 }
306
307 /*!
308 Returns \c TRUE if SoWWWInline::requestURLData() has been called
309 without being canceled by SoWWWInline::cancelURLData().
310 */
311 SbBool
isURLDataRequested(void) const312 SoWWWInline::isURLDataRequested(void) const
313 {
314 return PRIVATE(this)->didrequest;
315 }
316
317 /*!
318 Return \c TRUE if the current child data has been read from file/URL
319 and set using setChildData().
320 */
321 SbBool
isURLDataHere(void) const322 SoWWWInline::isURLDataHere(void) const
323 {
324 SoChildList * children = this->getChildren();
325 if (children->getLength() == 0 ||
326 (*children)[0] == this->alternateRep.getValue()) return FALSE;
327 return FALSE;
328 }
329
330 /*!
331 Can be used to signal that URL loading has been canceled. You
332 should use this method if you intend to request URL data more than
333 once.
334 */
335 void
cancelURLDataRequest(void)336 SoWWWInline::cancelURLDataRequest(void)
337 {
338 PRIVATE(this)->didrequest = FALSE;
339 }
340
341 /*!
342 Manually set up the subgraph for this node. This should be used
343 by the application to set the data that was read from the file/URL.
344 */
345 void
setChildData(SoNode * urldata)346 SoWWWInline::setChildData(SoNode * urldata)
347 {
348 PRIVATE(this)->children->truncate(0);
349 PRIVATE(this)->children->append(urldata);
350 }
351
352 /*!
353 Returns the child data for this node. This can be data read from a
354 file, from an URL, from the contents of SoWWWInline::alternateRep or
355 that was manually set with SoWWWInline::setChildData().
356 */
357 SoNode *
getChildData(void) const358 SoWWWInline::getChildData(void) const
359 {
360 if (PRIVATE(this)->children->getLength()) { return (*PRIVATE(this)->children)[0]; }
361 return NULL;
362 }
363
364 /*!
365 Sets the URL fetch callback. This will be used in
366 SoWWWInline::readInstance() or when the user calls
367 SoWWWInline::requestURLData().
368 // FIXME: Shouldn't called on readInstance(), only when we need to
369 // render the node (or calculate the bbox if we don't have one). kintel 20060203.
370 */
371 void
setFetchURLCallBack(SoWWWInlineFetchURLCB * f,void * userdata)372 SoWWWInline::setFetchURLCallBack(SoWWWInlineFetchURLCB * f,
373 void * userdata)
374 {
375 SoWWWInline::fetchurlcb = f;
376 SoWWWInline::fetchurlcbdata = userdata;
377 }
378
379 /*!
380 Sets the bounding box visibility strategy.
381 The default is UNTIL_LOADED.
382 */
383 void
setBoundingBoxVisibility(BboxVisibility b)384 SoWWWInline::setBoundingBoxVisibility(BboxVisibility b)
385 {
386 SoWWWInline::bboxvisibility = b;
387 }
388
389 /*!
390 Returns the bounding box visibility.
391 */
392 SoWWWInline::BboxVisibility
getBoundingBoxVisibility(void)393 SoWWWInline::getBoundingBoxVisibility(void)
394 {
395 return SoWWWInline::bboxvisibility;
396 }
397
398 /*!
399 Sets the bounding box color.
400 */
401 void
setBoundingBoxColor(SbColor & c)402 SoWWWInline::setBoundingBoxColor(SbColor & c)
403 {
404 *SoWWWInline::bboxcolor = c;
405 }
406
407 /*!
408 Returns the bounding box color.
409 */
410 const SbColor &
getBoundingBoxColor(void)411 SoWWWInline::getBoundingBoxColor(void)
412 {
413 return *SoWWWInline::bboxcolor;
414 }
415
416 /*!
417 Sets whether children should be read from a local file, in the same
418 manner as SoFile children are read.
419
420 If this is set to \c TRUE, the URL must point to a file on the local
421 file system, as can be accessed by the standard C library fopen()
422 call.
423 */
424 void
setReadAsSoFile(SbBool onoff)425 SoWWWInline::setReadAsSoFile(SbBool onoff)
426 {
427 SoWWWInline::readassofile = onoff;
428 }
429
430 /*!
431 Returns if children should be read from local files.
432
433 \sa setReadAsSoFile()
434 */
435 SbBool
getReadAsSoFile(void)436 SoWWWInline::getReadAsSoFile(void)
437 {
438 return SoWWWInline::readassofile;
439 }
440
441
442 // Documented in superclass. Overridden to render children and/or
443 // bounding box.
444 void
GLRender(SoGLRenderAction * action)445 SoWWWInline::GLRender(SoGLRenderAction * action)
446 {
447 if (this->getChildData()) {
448 SoWWWInline::doAction(action);
449 if (SoWWWInline::bboxvisibility == UNTIL_LOADED) return;
450 }
451 if (SoWWWInline::bboxvisibility == NEVER) return;
452
453 SoState * state = action->getState();
454 state->push();
455
456 SoColorPacker ** cptr = (SoColorPacker**) wwwinline_colorpacker_storage->get();
457
458 SoLazyElement::setDiffuse(state, this, 1, SoWWWInline::bboxcolor, *cptr);
459
460 // disable lighting
461 SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
462 // disable texture mapping
463 SoGLMultiTextureEnabledElement::disableAll(state);
464
465 SoMaterialBundle mb(action);
466 mb.sendFirst(); // set current color
467
468 float cx, cy, cz;
469 this->bboxCenter.getValue().getValue(cx, cy, cz);
470
471 float x0, y0, z0;
472 this->bboxSize.getValue().getValue(x0, y0, z0);
473 x0 = -x0/2.0f + cx;
474 y0 = -y0/2.0f + cy;
475 z0 = -z0/2.0f + cz;
476 float x1, y1, z1;
477 this->bboxSize.getValue().getValue(x1, y1, z1);
478 x1 = x1/2.0f + cx;
479 y1 = y1/2.0f + cy;
480 z1 = z1/2.0f + cz;
481
482 glBegin(GL_LINE_LOOP);
483 glVertex3f(x0, y0, z0);
484 glVertex3f(x1, y0, z0);
485 glVertex3f(x1, y1, z0);
486 glVertex3f(x0, y1, z0);
487 glEnd();
488 glBegin(GL_LINE_LOOP);
489 glVertex3f(x0, y0, z1);
490 glVertex3f(x1, y0, z1);
491 glVertex3f(x1, y1, z1);
492 glVertex3f(x0, y1, z1);
493 glEnd();
494
495 glBegin(GL_LINES);
496 glVertex3f(x0, y0, z0);
497 glVertex3f(x0, y0, z1);
498 glVertex3f(x0, y1, z0);
499 glVertex3f(x0, y1, z1);
500 glVertex3f(x1, y0, z0);
501 glVertex3f(x1, y0, z1);
502 glVertex3f(x1, y1, z0);
503 glVertex3f(x1, y1, z1);
504 glEnd();
505
506 state->pop(); // restore state
507 }
508
509 // doc in super
510 void
getBoundingBox(SoGetBoundingBoxAction * action)511 SoWWWInline::getBoundingBox(SoGetBoundingBoxAction * action)
512 {
513 if (this->getChildren()->getLength()) {
514 int numindices;
515 const int * indices;
516 int lastchildindex;
517
518 if (action->getPathCode(numindices, indices) == SoAction::IN_PATH)
519 lastchildindex = indices[numindices-1];
520 else
521 lastchildindex = this->getChildren()->getLength() - 1;
522
523 assert(lastchildindex < this->getChildren()->getLength());
524
525 // Initialize accumulation variables.
526 SbVec3f acccenter(0.0f, 0.0f, 0.0f);
527 int numcenters = 0;
528
529 for (int i = 0; i <= lastchildindex; i++) {
530 this->getChildren()->traverse(action, i);
531
532 // If center point is set, accumulate.
533 if (action->isCenterSet()) {
534 acccenter += action->getCenter();
535 numcenters++;
536 action->resetCenter();
537 }
538 }
539 if (numcenters != 0)
540 action->setCenter(acccenter / float(numcenters), FALSE);
541 }
542 else {
543 SbVec3f halfsize = bboxSize.getValue()/2.0f;
544 SbVec3f center = bboxCenter.getValue();
545
546 action->extendBy(SbBox3f(-halfsize[0] + center[0],
547 -halfsize[1] + center[1],
548 -halfsize[2] + center[2],
549 halfsize[0] + center[0],
550 halfsize[1] + center[1],
551 halfsize[2] + center[2]));
552
553 assert(! action->isCenterSet());
554 action->setCenter(center, TRUE);
555 }
556 }
557
558 /*!
559 Returns the child list with the child data for this node.
560 */
561 SoChildList *
getChildren(void) const562 SoWWWInline::getChildren(void) const
563 {
564 return PRIVATE(this)->children;
565 }
566
567 // doc in super
568 void
doAction(SoAction * action)569 SoWWWInline::doAction(SoAction * action)
570 {
571 if (this->getChildren()->getLength()) {
572 int numindices;
573 const int * indices;
574 if (action->getPathCode(numindices, indices) == SoAction::IN_PATH) {
575 this->getChildren()->traverseInPath(action, numindices, indices);
576 }
577 else {
578 this->getChildren()->traverse((SoAction *)action);
579 }
580 }
581 }
582
583 /*!
584 This method should probably have been private in OIV. It is
585 obsoleted in Coin. Let us know if you need it.
586 */
587 void
doActionOnKidsOrBox(SoAction * COIN_UNUSED_ARG (action))588 SoWWWInline::doActionOnKidsOrBox(SoAction * COIN_UNUSED_ARG(action))
589 {
590 COIN_OBSOLETED();
591 }
592
593 // doc in super
594 void
callback(SoCallbackAction * action)595 SoWWWInline::callback(SoCallbackAction * action)
596 {
597 SoWWWInline::doAction((SoAction *)action);
598 }
599
600 // doc in super
601 void
getMatrix(SoGetMatrixAction * action)602 SoWWWInline::getMatrix(SoGetMatrixAction * action)
603 {
604 SoWWWInline::doAction((SoAction *)action);
605 }
606
607 // doc in super
608 void
handleEvent(SoHandleEventAction * action)609 SoWWWInline::handleEvent(SoHandleEventAction * action)
610 {
611 SoWWWInline::doAction((SoAction *)action);
612 }
613
614 // doc in super
615 void
search(SoSearchAction * action)616 SoWWWInline::search(SoSearchAction * action)
617 {
618 SoNode::search(action);
619 if (!action->isFound()) {
620 SoWWWInline::doAction(action);
621 }
622 }
623
624 // doc in super
625 void
pick(SoPickAction * action)626 SoWWWInline::pick(SoPickAction * action)
627 {
628 SoWWWInline::doAction((SoAction *)action);
629 }
630
631 // doc in super
632 void
getPrimitiveCount(SoGetPrimitiveCountAction * action)633 SoWWWInline::getPrimitiveCount(SoGetPrimitiveCountAction * action)
634 {
635 SoWWWInline::doAction((SoAction *)action);
636 }
637
638 // doc in super
639 void
audioRender(SoAudioRenderAction * action)640 SoWWWInline::audioRender(SoAudioRenderAction * action)
641 {
642 SoWWWInline::doAction((SoAction *)action);
643 }
644
645 /*!
646 Convenience method that extends the current bounding box to
647 include the box specified by \a center and \a size.
648 */
649 void
addBoundingBoxChild(SbVec3f center,SbVec3f size)650 SoWWWInline::addBoundingBoxChild(SbVec3f center, SbVec3f size)
651 {
652 SbVec3f orgsize = this->bboxSize.getValue();
653 SbVec3f orgcenter = this->bboxCenter.getValue();
654
655 orgsize *= 0.5f;
656 SbBox3f bbox(orgcenter-orgsize, orgcenter+orgsize);
657
658 size *= 0.5f;
659 SbBox3f newbox(center-size, center+size);
660
661 bbox.extendBy(newbox);
662 this->bboxCenter = bbox.getCenter();
663 bbox.getSize(size[0], size[1], size[2]);
664 this->bboxSize = size;
665 }
666
667 // Documented in superclass. Overridden to fetch/read child data.
668 SbBool
readInstance(SoInput * in,unsigned short flags)669 SoWWWInline::readInstance(SoInput * in, unsigned short flags)
670 {
671 SbBool ret = inherited::readInstance(in, flags);
672 if (ret) {
673 ret = PRIVATE(this)->readChildren();
674 }
675 return ret;
676 }
677
678 // Documented in superclass. Overridden to copy children.
679 void
copyContents(const SoFieldContainer * fromfc,SbBool copyconnections)680 SoWWWInline::copyContents(const SoFieldContainer * fromfc,
681 SbBool copyconnections)
682 {
683 this->getChildren()->truncate(0);
684 inherited::copyContents(fromfc, copyconnections);
685
686 SoWWWInline * inlinenode = (SoWWWInline *) fromfc;
687
688 if (inlinenode->getChildren()->getLength() == 0) return;
689
690 assert(inlinenode->getChildren()->getLength() == 1);
691
692 SoNode * cp = (SoNode *)
693 SoFieldContainer::findCopy((*(inlinenode->getChildren()))[0], copyconnections);
694 this->getChildren()->append(cp);
695 }
696
697 #undef PRIVATE
698
699 // *************************************************************************
700
701 // Read the file named in the name field.
702 SbBool
readNamedFile()703 SoWWWInlineP::readNamedFile()
704 {
705 // If we can't find file, ignore it. Note that this does not match
706 // the way Inventor works, which will make the whole read process
707 // exit with a failure code.
708 SoInput in;
709
710 SbString name = this->owner->getFullURLName();
711 if (!in.openFile(name.getString())) return TRUE;
712
713 SoSeparator * node = SoDB::readAll(&in);
714
715 // Popping the file off the stack again is done implicit in SoInput
716 // upon hitting EOF (unless the read fails, see below).
717
718 if (node) {
719 this->children->truncate(0);
720 this->children->append((SoNode *)node);
721 }
722 else {
723 // Note that we handle this differently than Inventor, which lets
724 // the whole import fail.
725 SoReadError::post(&in, "Unable to read subfile: ``%s''",
726 name.getString());
727 }
728
729 return TRUE;
730 }
731
732 /*!
733 Read children, either using the URL callback or by reading from
734 local file directly.
735
736 fetchURLCB is NULL: Use alternaterep. NB! Always uses alternate rep
737 in this case.
738 else name not set: Do nothing
739 else readassofile is TRUE: Assume name points to a local file and load
740 automatically without using fetchURLCB.
741
742 */
743 SbBool
readChildren()744 SoWWWInlineP::readChildren()
745 {
746 if (!SoWWWInline::fetchurlcb) {
747 if (this->owner->alternateRep.getValue()) {
748 this->owner->setChildData(this->owner->alternateRep.getValue());
749 }
750 }
751 else if (this->owner->name.getValue() != SoWWWInlineP::UNDEFINED_FILE) {
752 if (SoWWWInline::readassofile) {
753 return this->readNamedFile();
754 }
755 else {
756 SoWWWInline::fetchurlcb(this->owner->getFullURLName(),
757 SoWWWInline::fetchurlcbdata,
758 this->owner);
759 }
760 }
761 return TRUE;
762 }
763