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 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif // HAVE_CONFIG_H
36
37 #ifdef HAVE_VRML97
38
39 /*!
40 \class SoVRMLInline SoVRMLInline.h Inventor/VRMLnodes/SoVRMLInline.h
41 \brief The SoVRMLInline class is used to insert VRML files into a scene.
42
43 \ingroup VRMLnodes
44
45 \WEB3DCOPYRIGHT
46
47 \verbatim
48 Inline {
49 exposedField MFString url []
50 field SFVec3f bboxCenter 0 0 0 # (-,)
51 field SFVec3f bboxSize -1 -1 -1 # (0,) or -1,-1,-1
52 }
53 \endverbatim
54
55 The Inline node is a grouping node that reads its children data from
56 a location in the World Wide Web. Exactly when its children are read
57 and displayed is not defined (e.g. reading the children may be
58 delayed until the Inline node's bounding box is visible to the
59 viewer). The url field specifies the URL containing the children. An
60 Inline node with an empty URL does nothing.
61
62 Each specified URL shall refer to a valid VRML file that contains a
63 list of children nodes, prototypes, and routes at the top level as
64 described in 4.6.5, Grouping and children nodes.
65
66 The results are undefined if the URL refers to a file that is not
67 VRML or if the VRML file contains non-children nodes at the top
68 level.
69
70 If multiple URLs are specified, the browser may display a URL of a
71 lower preference VRML file while it is obtaining, or if it is unable
72 to obtain, the higher preference VRML file. Details on the url field
73 and preference order can be found in 4.5, VRML and the World Wide
74 Web
75 (<http://www.web3d.org/documents/specifications/14772/V2.0/part1/concepts.html#4.5>).
76
77 The results are undefined if the contents of the URL change after it
78 has been loaded.
79
80 The bboxCenter and bboxSize fields specify a bounding box that
81 encloses the Inline node's children. This is a hint that may be used
82 for optimization purposes. The results are undefined if the
83 specified bounding box is smaller than the actual bounding box of
84 the children at any time. A default bboxSize value, (-1, -1, -1),
85 implies that the bounding box is not specified and if needed shall
86 be calculated by the browser. A description of the bboxCenter and
87 bboxSize fields is in 4.6.4, Bounding boxes
88 (<http://www.web3d.org/documents/specifications/14772/V2.0/part1/concepts.html#4.6.4>).
89
90 */
91
92 /*!
93 SoSFVec3f SoVRMLInline::bboxCenter
94 Center of bounding box.
95 */
96
97 /*!
98 SoSFVec3f SoVRMLInline::bboxSize
99 Size of bounding box.
100 */
101
102 /*!
103 SoMFString SoVRMLInline::url
104 The VRML file URL.
105 */
106
107 /*!
108 enum SoVRMLInline::BboxVisibility
109 Used to enumerate bounding box visibility settings.
110 */
111
112 /*!
113 \var SoVRMLInline::BboxVisibility SoVRMLInline::NEVER
114 Never display bounding box.
115 */
116
117 /*!
118 \var SoVRMLInline::BboxVisibility SoVRMLInline::UNTIL_LOADED
119 Display bounding box until file is loaded.
120 */
121
122 /*!
123 \var SoVRMLInline::BboxVisibility SoVRMLInline::ALWAYS
124 Always display bounding box.
125 */
126
127 /*! \file SoVRMLInline.h */
128 #include <Inventor/VRMLnodes/SoVRMLInline.h>
129 #include "coindefs.h"
130
131 #include <cstdlib>
132
133 #include <Inventor/VRMLnodes/SoVRMLMacros.h>
134 #include <Inventor/nodes/SoSeparator.h>
135 #include <Inventor/SbColor.h>
136 #include <Inventor/SoInput.h>
137 #include <Inventor/SoDB.h>
138 #include <Inventor/SbBox3f.h>
139 #include <Inventor/errors/SoReadError.h>
140 #include <Inventor/actions/SoActions.h>
141 #include <Inventor/actions/SoSearchAction.h>
142 #include <Inventor/actions/SoGLRenderAction.h>
143 #include <Inventor/actions/SoGetBoundingBoxAction.h>
144 #include <Inventor/misc/SoChildList.h>
145 #include <Inventor/sensors/SoFieldSensor.h>
146 #include <Inventor/elements/SoGLLazyElement.h>
147 #include <Inventor/elements/SoGLMultiTextureEnabledElement.h>
148 #include <Inventor/system/gl.h>
149
150 #include "nodes/SoSubNodeP.h"
151 #include "tidbitsp.h"
152
153 class SoVRMLInlineP {
154 public:
155 SbString fullurlname;
156 SbBool isrequested;
157 SoChildList * children;
158 SoFieldSensor * urlsensor;
159 };
160
161 static SoVRMLInline::BboxVisibility
162 sovrmlinline_bboxvisibility = SoVRMLInline::UNTIL_LOADED;
163 static SoVRMLInlineFetchURLCB * sovrmlinline_fetchurlcb = NULL;
164 static void * sovrmlinline_fetchurlcbclosure;
165
166 static SbColor * sovrmlinline_bboxcolor = NULL;
167 static SbBool sovrmlinline_readassofile = TRUE;
168
169 static void
sovrmlinline_cleanup(void)170 sovrmlinline_cleanup(void)
171 {
172 delete sovrmlinline_bboxcolor;
173 sovrmlinline_bboxcolor = NULL;
174 sovrmlinline_bboxvisibility = SoVRMLInline::UNTIL_LOADED;
175 sovrmlinline_fetchurlcb = NULL;
176 sovrmlinline_readassofile = TRUE;
177 }
178
179 SO_NODE_SOURCE(SoVRMLInline);
180
181 // Doc in parent
182 void
initClass(void)183 SoVRMLInline::initClass(void)
184 {
185 SO_NODE_INTERNAL_INIT_CLASS(SoVRMLInline, SO_VRML97_NODE_TYPE);
186 sovrmlinline_bboxcolor = new SbColor(0.8f, 0.8f, 0.8f);
187 coin_atexit((coin_atexit_f*) sovrmlinline_cleanup, CC_ATEXIT_NORMAL);
188 SoAudioRenderAction::addMethod(SoVRMLInline::getClassTypeId(),
189 SoAudioRenderAction::callDoAction);
190 }
191
192 #define PRIVATE(obj) ((obj)->pimpl)
193
194 /*!
195 Constructor
196 */
SoVRMLInline(void)197 SoVRMLInline::SoVRMLInline(void)
198 {
199 PRIVATE(this) = new SoVRMLInlineP;
200 PRIVATE(this)->isrequested = FALSE;
201 PRIVATE(this)->children = new SoChildList(this);
202
203 SO_VRMLNODE_INTERNAL_CONSTRUCTOR(SoVRMLInline);
204
205 SO_VRMLNODE_ADD_FIELD(bboxCenter, (0.0f, 0.0f, 0.0f));
206 SO_VRMLNODE_ADD_FIELD(bboxSize, (-1.0f, -1.0f, -1.0f));
207 SO_VRMLNODE_ADD_EMPTY_EXPOSED_MFIELD(url);
208
209 PRIVATE(this)->urlsensor = new SoFieldSensor(SoVRMLInline::urlFieldModified, this);
210 PRIVATE(this)->urlsensor->setPriority(0); // immediate sensor
211 PRIVATE(this)->urlsensor->attach(& this->url);
212 }
213
214 /*!
215 Destructor.
216 */
~SoVRMLInline()217 SoVRMLInline::~SoVRMLInline()
218 {
219 delete PRIVATE(this)->urlsensor;
220 delete PRIVATE(this)->children;
221 delete PRIVATE(this);
222 }
223
224 /*!
225 Sets the full (non-relative) URL name.
226 */
227 void
setFullURLName(const SbString & urlref)228 SoVRMLInline::setFullURLName(const SbString & urlref)
229 {
230 PRIVATE(this)->fullurlname = urlref;
231 }
232
233 /*!
234 Returns the full URL name.
235 */
236 const SbString &
getFullURLName(void)237 SoVRMLInline::getFullURLName(void)
238 {
239 return PRIVATE(this)->fullurlname;
240 }
241
242 /*!
243 Returns a copy of the children.
244 */
245 SoGroup *
copyChildren(void) const246 SoVRMLInline::copyChildren(void) const
247 {
248 if (PRIVATE(this)->children->getLength() == 0) return NULL;
249 assert(PRIVATE(this)->children->getLength() == 1);
250 SoNode * rootcopy = (*(PRIVATE(this)->children))[0]->copy();
251 assert(rootcopy->isOfType(SoGroup::getClassTypeId()));
252 return (SoGroup *)rootcopy;
253 }
254
255 // Doc in parent
256 SoChildList *
getChildren(void) const257 SoVRMLInline::getChildren(void) const
258 {
259 return PRIVATE(this)->children;
260 }
261
262 /*!
263 Request URL data.
264 */
265 void
requestURLData(void)266 SoVRMLInline::requestURLData(void)
267 {
268 PRIVATE(this)->isrequested = TRUE;
269 if (sovrmlinline_fetchurlcb) {
270 sovrmlinline_fetchurlcb(PRIVATE(this)->fullurlname,
271 sovrmlinline_fetchurlcbclosure,
272 this);
273 }
274 }
275
276 /*!
277 Returns TRUE if the URL data has been requested.
278 */
279 SbBool
isURLDataRequested(void) const280 SoVRMLInline::isURLDataRequested(void) const
281 {
282 return PRIVATE(this)->isrequested;
283 }
284
285 /*!
286 Returns TRUE if the data has been loaded.
287 */
288 SbBool
isURLDataHere(void) const289 SoVRMLInline::isURLDataHere(void) const
290 {
291 return this->getChildData() != NULL;
292 }
293
294 /*!
295 Cancel the URL data request.
296 */
297 void
cancelURLDataRequest(void)298 SoVRMLInline::cancelURLDataRequest(void)
299 {
300 PRIVATE(this)->isrequested = FALSE;
301 }
302
303 /*!
304 Sets the child data. Can be used by the URL fetch callback.
305 */
306 void
setChildData(SoNode * urldata)307 SoVRMLInline::setChildData(SoNode * urldata)
308 {
309 PRIVATE(this)->isrequested = FALSE;
310 PRIVATE(this)->children->truncate(0);
311 if (urldata) {
312 PRIVATE(this)->children->append(urldata);
313 }
314 }
315
316 /*!
317 Returns the child data (the scene loaded from the url).
318 */
319 SoNode *
getChildData(void) const320 SoVRMLInline::getChildData(void) const
321 {
322 if (PRIVATE(this)->children->getLength()) {
323 return (*PRIVATE(this)->children)[0];
324 }
325 return NULL;
326 }
327
328 /*!
329 Sets the callback used to handle URL loading.
330 */
331 void
setFetchURLCallBack(SoVRMLInlineFetchURLCB * f,void * closure)332 SoVRMLInline::setFetchURLCallBack(SoVRMLInlineFetchURLCB * f,
333 void * closure)
334 {
335 sovrmlinline_fetchurlcb = f;
336 sovrmlinline_fetchurlcbclosure = closure;
337 }
338
339 /*!
340 Sets the bounding box visibility strategy.
341 */
342 void
setBoundingBoxVisibility(BboxVisibility b)343 SoVRMLInline::setBoundingBoxVisibility(BboxVisibility b)
344 {
345 sovrmlinline_bboxvisibility = b;
346 }
347
348 /*!
349 Returns the bounding box visibility strategy.
350 */
351 SoVRMLInline::BboxVisibility
getBoundingBoxVisibility(void)352 SoVRMLInline::getBoundingBoxVisibility(void)
353 {
354 return sovrmlinline_bboxvisibility;
355 }
356
357 /*!
358 Sets the color of the bounding box.
359 */
360 void
setBoundingBoxColor(SbColor & color)361 SoVRMLInline::setBoundingBoxColor(SbColor & color)
362 {
363 sovrmlinline_bboxcolor->setValue(color[0], color[1], color[2]);
364 }
365
366 /*!
367 Returns the color of the bounding box.
368 */
369 SbColor &
getBoundingBoxColor(void)370 SoVRMLInline::getBoundingBoxColor(void)
371 {
372 return *sovrmlinline_bboxcolor;
373 }
374
375 /*!
376 Sets whether Inline nodes should be treated as a normal Inventor SoFile node.
377 */
378 void
setReadAsSoFile(SbBool enable)379 SoVRMLInline::setReadAsSoFile(SbBool enable)
380 {
381 sovrmlinline_readassofile = enable;
382 }
383
384 /*!
385 Returns whether Inline nodes is read as SoFile nodes.
386 */
387 SbBool
getReadAsSoFile(void)388 SoVRMLInline::getReadAsSoFile(void)
389 {
390 return sovrmlinline_readassofile;
391 }
392
393 // Doc in parent
394 void
doAction(SoAction * action)395 SoVRMLInline::doAction(SoAction * action)
396 {
397 int numindices;
398 const int * indices;
399 if (action->getPathCode(numindices, indices) == SoAction::IN_PATH) {
400 PRIVATE(this)->children->traverseInPath(action, numindices, indices);
401 }
402 else {
403 PRIVATE(this)->children->traverse(action);
404 }
405 }
406
407 // Doc in parent
408 void
callback(SoCallbackAction * action)409 SoVRMLInline::callback(SoCallbackAction * action)
410 {
411 SoVRMLInline::doAction((SoAction*)action);
412 }
413
414 // Doc in parent
415 void
GLRender(SoGLRenderAction * action)416 SoVRMLInline::GLRender(SoGLRenderAction * action)
417 {
418 BboxVisibility vis = sovrmlinline_bboxvisibility;
419 SbVec3f size = this->bboxSize.getValue();
420 SoNode * child = this->getChildData();
421 if ((size[0] >= 0.0f && size[1] >= 0.0f && size[2] >= 0.0f) &&
422 ((vis == ALWAYS) ||
423 (vis == UNTIL_LOADED && child == NULL))) {
424 SoState * state = action->getState();
425 state->push();
426
427 SoGLMultiTextureEnabledElement::disableAll(state);
428
429 uint32_t packedcolor = sovrmlinline_bboxcolor->getPackedValue();
430 SoGLLazyElement::sendLightModel(state, SoLazyElement::BASE_COLOR);
431 SoGLLazyElement::sendPackedDiffuse(state, packedcolor);
432
433 SbVec3f center = this->bboxCenter.getValue();
434 SbVec3f minv = center - size*0.5f;
435 SbVec3f maxv = center + size*0.5f;
436
437 SbVec3f p[8];
438 for (int i = 0; i < 8; i++) {
439 p[i][0] = i & 1 ? minv[0] : maxv[0];
440 p[i][1] = i & 2 ? minv[1] : maxv[1];
441 p[i][2] = i & 4 ? minv[2] : maxv[2];
442 }
443
444 glBegin(GL_LINE_LOOP);
445 glVertex3fv(p[0].getValue());
446 glVertex3fv(p[1].getValue());
447 glVertex3fv(p[3].getValue());
448 glVertex3fv(p[2].getValue());
449 glEnd();
450
451 glBegin(GL_LINE_LOOP);
452 glVertex3fv(p[4].getValue());
453 glVertex3fv(p[5].getValue());
454 glVertex3fv(p[7].getValue());
455 glVertex3fv(p[6].getValue());
456 glEnd();
457
458 glBegin(GL_LINES);
459
460 glVertex3fv(p[0].getValue());
461 glVertex3fv(p[4].getValue());
462
463 glVertex3fv(p[2].getValue());
464 glVertex3fv(p[6].getValue());
465
466 glVertex3fv(p[3].getValue());
467 glVertex3fv(p[7].getValue());
468
469 glVertex3fv(p[1].getValue());
470 glVertex3fv(p[5].getValue());
471
472 glEnd();
473 state->pop();
474 }
475 SoVRMLInline::doAction(action);
476 }
477
478 // Doc in parent
479 void
getBoundingBox(SoGetBoundingBoxAction * action)480 SoVRMLInline::getBoundingBox(SoGetBoundingBoxAction * action)
481 {
482 SbVec3f size = this->bboxSize.getValue();
483 if (size[0] > 0.0f || size[1] > 0.0f || size[2] > 0) {
484 size[0] = SbMax(size[0], 0.0f);
485 size[1] = SbMax(size[1], 0.0f);
486 size[2] = SbMax(size[2], 0.0f);
487 SbVec3f center = this->bboxCenter.getValue();
488 size *= 0.5f;
489 SbBox3f box(center[0]-size[0],
490 center[1]-size[1],
491 center[2]-size[2],
492 center[0]+size[0],
493 center[1]+size[1],
494 center[2]+size[2]);
495 if (!box.isEmpty()) {
496 action->extendBy(box);
497 action->setCenter(center, TRUE);
498 }
499 }
500 else {
501 int numindices;
502 const int * indices;
503 int lastchildindex;
504
505 if (action->getPathCode(numindices, indices) == SoAction::IN_PATH)
506 lastchildindex = indices[numindices-1];
507 else
508 lastchildindex = this->getChildren()->getLength() - 1;
509
510 assert(lastchildindex < this->getChildren()->getLength());
511
512 // Initialize accumulation variables.
513 SbVec3f acccenter(0.0f, 0.0f, 0.0f);
514 int numcenters = 0;
515
516 for (int i = 0; i <= lastchildindex; i++) {
517 this->getChildren()->traverse(action, i);
518
519 // If center point is set, accumulate.
520 if (action->isCenterSet()) {
521 acccenter += action->getCenter();
522 numcenters++;
523 action->resetCenter();
524 }
525 }
526
527 if (numcenters != 0)
528 action->setCenter(acccenter / float(numcenters), FALSE);
529 }
530 }
531
532 // Doc in parent
533 void
getMatrix(SoGetMatrixAction * action)534 SoVRMLInline::getMatrix(SoGetMatrixAction * action)
535 {
536 SoVRMLInline::doAction((SoAction*)action);
537 }
538
539 // Doc in parent
540 void
handleEvent(SoHandleEventAction * action)541 SoVRMLInline::handleEvent(SoHandleEventAction * action)
542 {
543 SoVRMLInline::doAction((SoAction*)action);
544 }
545
546 // Doc in parent
547 void
search(SoSearchAction * action)548 SoVRMLInline::search(SoSearchAction * action)
549 {
550 SoNode::search(action);
551 if (action->isFound()) return;
552
553 SoVRMLInline::doAction(action);
554 }
555
556 // Doc in parent
557 void
pick(SoPickAction * action)558 SoVRMLInline::pick(SoPickAction * action)
559 {
560 SoVRMLInline::doAction((SoAction*)action);
561 }
562
563 // Doc in parent
564 void
getPrimitiveCount(SoGetPrimitiveCountAction * action)565 SoVRMLInline::getPrimitiveCount(SoGetPrimitiveCountAction * action)
566 {
567 SoVRMLInline::doAction((SoAction*)action);
568 }
569
570 void
addBoundingBoxChild(SbVec3f COIN_UNUSED_ARG (center),SbVec3f COIN_UNUSED_ARG (size))571 SoVRMLInline::addBoundingBoxChild(SbVec3f COIN_UNUSED_ARG(center),
572 SbVec3f COIN_UNUSED_ARG(size))
573 {
574 // FIXME: implement
575 }
576
577 // Doc in parent
578 SbBool
readInstance(SoInput * in,unsigned short flags)579 SoVRMLInline::readInstance(SoInput * in,
580 unsigned short flags)
581 {
582 SbBool ret = TRUE;
583
584 PRIVATE(this)->urlsensor->detach();
585 if (sovrmlinline_readassofile) {
586 PRIVATE(this)->fullurlname.makeEmpty();
587 ret = inherited::readInstance(in, flags);
588 ret = ret && this->readLocalFile(in);
589 }
590 else {
591 ret = inherited::readInstance(in, flags);
592 if (ret) this->requestURLData();
593 }
594 PRIVATE(this)->urlsensor->attach(&this->url);
595
596 return ret;
597 }
598
599 // Doc in parent
600 void
copyContents(const SoFieldContainer * from,SbBool copyconnections)601 SoVRMLInline::copyContents(const SoFieldContainer * from,
602 SbBool copyconnections)
603 {
604 PRIVATE(this)->children->truncate(0);
605 inherited::copyContents(from, copyconnections);
606
607 SoVRMLInline * inlinenode = (SoVRMLInline *)from;
608 PRIVATE(this)->fullurlname = inlinenode->pimpl->fullurlname;
609 // the request will go to the original node, not this one.
610 PRIVATE(this)->isrequested = FALSE;
611
612 if (inlinenode->pimpl->children->getLength() == 0) return;
613
614 assert(inlinenode->pimpl->children->getLength() == 1);
615
616 SoNode * cp = (SoNode *)
617 SoFieldContainer::findCopy((*(inlinenode->pimpl->children))[0],
618 copyconnections);
619 PRIVATE(this)->children->append(cp);
620 }
621
622 /*!
623 Read the (local) file named in the SoVRMLInline::url field.
624 */
625 SbBool
readLocalFile(SoInput * in)626 SoVRMLInline::readLocalFile(SoInput * in)
627 {
628 if (this->url.getNum() == 0) {
629 return TRUE;
630 }
631
632 SbString filename = this->url[0];
633
634 // If we can't find file, ignore it. Note that this does not match
635 // the way Inventor works, which will make the whole read process
636 // exit with a failure code.
637 if (!in->pushFile(filename.getString())) return TRUE;
638
639 PRIVATE(this)->fullurlname = in->getCurFileName();
640
641 SoSeparator * node = SoDB::readAll(in);
642
643 if (node) {
644 PRIVATE(this)->children->truncate(0);
645 PRIVATE(this)->children->append((SoNode *)node);
646 }
647 else {
648 if (in->getCurFileName() == PRIVATE(this)->fullurlname) {
649 // Take care of popping the file off the stack. This is a bit
650 // "hack-ish", but its done this way instead of loosening the
651 // protection of SoInput::popFile().
652 char dummy;
653 while (!in->eof() && in->get(dummy)) {}
654 assert(in->eof());
655
656 // Make sure the stack is really popped on EOF. Popping happens
657 // when attempting to read when the current file in the stack is
658 // at EOF.
659 SbBool gotchar = in->get(dummy);
660 if (gotchar) in->putBack(dummy);
661 }
662
663 // Note that we handle this differently than Inventor, which lets
664 // the whole import fail.
665 SoReadError::post(in, "Unable to read Inline file: ``%s''",
666 filename.getString());
667 }
668
669 return TRUE;
670 }
671
672 // Callback for the field sensor.
673 void
urlFieldModified(void * userdata,SoSensor * COIN_UNUSED_ARG (sensor))674 SoVRMLInline::urlFieldModified(void * userdata, SoSensor * COIN_UNUSED_ARG(sensor))
675 {
676 SoVRMLInline * thisp = (SoVRMLInline *)userdata;
677 SoInput in;
678 thisp->pimpl->fullurlname.makeEmpty();
679 if (sovrmlinline_readassofile) {
680 (void)thisp->readLocalFile(&in);
681 }
682 else {
683 thisp->requestURLData();
684 }
685 }
686
687 #undef PRIVATE
688
689 #endif // HAVE_VRML97
690