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