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 SoNode SoNode.h Inventor/nodes/SoNode.h
35 \brief The SoNode class is the base class for nodes used in scene graphs.
36
37 \ingroup nodes
38
39 Coin is a \e retained \e mode 3D visualization library (built on top
40 of the \e immediate \e mode OpenGL library). "Retained mode" means
41 that instead of passing commands to draw graphics primitives
42 directly to the renderer, you build up data structures which are
43 rendered by the library \e on \e demand.
44
45 The node classes are the main "primitive" for building these data
46 structures. In Coin, you build tree hierarchies made up of different
47 node types: group nodes (for the tree structure layout of the other
48 nodes), appearance nodes (for setting up materials, textures, etc),
49 shape nodes (for the actual geometry), and nodes for lighting and
50 camera positioning.
51
52 One common issue with newcomers to the API is that you should not
53 and can not use the C++ delete operator on nodes -- the destructor
54 is protected. This is because node instances are using a common
55 technique for memory resource handling called "reference
56 counting". Nodes are deleted (actually, they delete themselves) when
57 their unref() method is called and the reference count goes to zero.
58
59 One important side-effect of this is that SoNode-derived classes
60 should \e not be statically allocated, neither in static module
61 memory nor on function's stack-frames. SoNode-derived classes must
62 \e always be allocated dynamically from the memory heap with the \c
63 new operator (or else the scheme with self-destruction upon
64 de-referencing to 0 would not work).
65
66
67 Usually application programmers won't manually ref() and unref()
68 nodes a lot, because you pass the nodes directly to
69 SoGroup::addChild() or So\@Gui\@Viewer\::setSceneGraph() or something
70 similar. These functions will ref() the nodes they are passed, and
71 unref() them when they are finished with them.
72
73 Make sure you do ref() nodes that you keep pointers to so they
74 aren't accidentally deleted prematurely due to an unref() call from
75 within the library itself. If you haven't manually called ref() on
76 a top-level root node, it will then be deleted automatically. This
77 code shows how to do it:
78
79 \code
80 SoSeparator * root = new SoSeparator; // root's refcount starts out at zero
81 root->addChild(foo_node); // foo_node refcount is increased by 1
82 root->addChild(bar_node); // bar_node refcount +1
83
84 // increase refcount before passing it to setScenegraph(), to avoid
85 // premature destruction
86 root->ref();
87
88 myviewer->setSceneGraph(root); // root's refcount +1, is now 2
89
90 // [misc visualization and processing]
91
92 // myviewer will let go of it's reference to the root node, thereby
93 // decreasing it's referencecount by 1
94 myviewer->setSceneGraph(NULL);
95
96 // root's refcount goes from +1 to 0, and it will self-destruct controllably
97 root->unref();
98 // avoid dangling pointer, in case "root" is attempted used again
99 // (not really necessary, but good for smoking out bugs early)
100 root = NULL;
101 \endcode
102
103 For full information and tutorial-style introductions to all API
104 issues, see the "Inventor Mentor: Programming Object-Oriented 3D
105 Graphics with Open Inventor" (ISBN 0-201-62495-8). It has detailed
106 explanations on all the basic principles involved.
107
108 See specifically the section "References and Deletion" in Chapter 3
109 to learn about the reference counting techniques.
110
111
112 Often when using the Coin library, one is interested in making
113 extensions to it. Of particular interest is setting up extension
114 nodes, which are then traversed, rendered and otherwise used by the
115 rest of the library as any internal node.
116
117 The Coin header file Inventor/nodes/SoSubNode.h includes a set of
118 convenience macros for quick and easy construction of extension
119 nodes. Here's a complete snippet of code which shows how to set up a
120 skeleton framework for an extension node class:
121
122 \code
123 #include <Inventor/nodes/SoWWWInline.h>
124
125 //// Definition of extension class "MyWWWInline" ///////////////
126
127 class MyWWWInline : public SoWWWInline {
128 SO_NODE_HEADER(MyWWWInline);
129
130 public:
131 static void initClass(void);
132 MyWWWInline(void);
133
134 protected:
135 virtual ~MyWWWInline();
136 };
137
138 //// Implementation of extension class "MyWWWInline" ///////////
139
140 SO_NODE_SOURCE(MyWWWInline);
141
142 MyWWWInline::MyWWWInline(void)
143 {
144 SO_NODE_CONSTRUCTOR(MyWWWInline);
145 }
146
147 MyWWWInline::~MyWWWInline()
148 {
149 }
150
151 void
152 MyWWWInline::initClass(void)
153 {
154 SO_NODE_INIT_CLASS(MyWWWInline, SoWWWInline, "SoWWWInline");
155 }
156
157 //// main //////////////////////////////////////////////////////
158
159 int
160 main(int argc, char ** argv)
161 {
162 SoDB::init();
163 MyWWWInline::initClass();
164
165 // [...]
166
167 return 0;
168 }
169 \endcode
170
171 You can then override for instance the GLRender() method to have
172 your new class render OpenGL geometry different from it's
173 superclass.
174
175 \TOOLMAKER_REF
176
177 For information about dynamic loading of extension nodes, see the
178 documentation of SoType::fromName().
179 */
180
181 /*!
182 \class SbUniqueId SbBasic.h Inventor/SbBasic.h
183 \brief SbUniqueId is an integer type for node identifiers.
184 \ingroup base
185
186 SbUniqueId is meant to be a "32/64 bit portable" way of defining an
187 integer type that is used for storing unique node identifiers.
188
189 SbUniqueId is not really a class, just a \c typedef.
190 */
191
192
193 // *************************************************************************
194
195 #include <Inventor/nodes/SoNode.h>
196
197 #ifdef HAVE_CONFIG_H
198 #include "config.h"
199 #endif // HAVE_CONFIG_H
200
201 #include <cassert>
202 #include <cstdlib>
203
204 #include <Inventor/SoInput.h>
205 #include <Inventor/SoOutput.h>
206 #include <Inventor/actions/SoActions.h>
207 #include <Inventor/elements/SoCacheElement.h>
208 #include <Inventor/errors/SoDebugError.h>
209 #include <Inventor/misc/SoChildList.h>
210 #include <Inventor/misc/SoProto.h>
211 #include <Inventor/misc/SoProtoInstance.h>
212 #include <Inventor/nodes/SoNodes.h>
213 #include <Inventor/engines/SoNodeEngine.h>
214 #include <Inventor/lists/SoEngineOutputList.h>
215
216 #include "tidbitsp.h"
217 #include "misc/SbHash.h"
218 #include "rendering/SoGL.h"
219 #include "nodes/SoSubNodeP.h"
220 #include "nodes/SoUnknownNode.h"
221 #include "threads/threadsutilp.h"
222 #include "glue/glp.h"
223 #include "misc/SoDBP.h" // for global envvar COIN_PROFILER
224
225 // *************************************************************************
226
227 /*!
228 \var SbUniqueId SoNode::uniqueId
229 \COININTERNAL
230 */
231 /*!
232 \var SbUniqueId SoNode::nextUniqueId
233 \COININTERNAL
234 */
235 /*!
236 \var int SoNode::nextActionMethodIndex
237 \COININTERNAL
238 */
239
240 /*!
241 \enum SoNode::NodeType
242 Used to store node type.
243 */
244
245 /*!
246 \var SoNode::NodeType SoNode::INVENTOR
247 Specifies Inventor node type.
248 */
249
250 /*!
251 \var SoNode::NodeType SoNode::VRML1
252 Node is VRML V1.0 compatible.
253 */
254
255 /*!
256 \var SoNode::NodeType SoNode::VRML2
257 Node is from the VRML V2.0 specification.
258 */
259
260 /*!
261 \var SoNode::NodeType SoNode::INVENTOR_1
262 Node was part of SGI Inventor version 1.
263 */
264
265 /*!
266 \var SoNode::NodeType SoNode::INVENTOR_2_0
267 Node was part of SGI Inventor version 2.0.
268 */
269
270 /*!
271 \var SoNode::NodeType SoNode::INVENTOR_2_1
272 Node was introduced with SGI / TGS Inventor version 2.1.
273 */
274
275 /*!
276 \var SoNode::NodeType SoNode::INVENTOR_2_5
277 Node was introduced with TGS Inventor version 2.5.
278 */
279
280 /*!
281 \var SoNode::NodeType SoNode::INVENTOR_2_6
282 Node was introduced with TGS Inventor version 2.6.
283 */
284
285 /*!
286 \var SoNode::NodeType SoNode::COIN_1_0
287 Node was part of Coin version 1.
288 */
289
290 /*!
291 \var SoNode::NodeType SoNode::COIN_2_0
292 Node was introduced with Coin 2.0.
293 */
294
295 /*!
296 \var SoNode::NodeType SoNode::EXTENSION
297 Node is a client code extension.
298 */
299
300 // *************************************************************************
301
302 SbUniqueId SoNode::nextUniqueId = 1;
303 int SoNode::nextActionMethodIndex = 0;
304 SoType SoNode::classTypeId STATIC_SOTYPE_INIT;
305 static void * sonode_mutex = NULL;
306
307 typedef SbHash<int16_t, uint32_t> Int16ToUInt32Map;
308 static Int16ToUInt32Map * compatibility_dict = NULL;
309
310 static void init_action_methods(void);
311
312 // *************************************************************************
313
314 // Overridden from parent.
315 SoType
getClassTypeId(void)316 SoNode::getClassTypeId(void)
317 {
318 return SoNode::classTypeId;
319 }
320
321 // *************************************************************************
322
323 // defines for node state flags
324
325 // we can currently have 31 node types. The last bit is used to store
326 // the override flag.
327 #define FLAG_TYPEMASK 0x7fffffff
328 #define FLAG_OVERRIDE 0x80000000
329
330 // private methods. Inlined inside this file only.
331
332 // clear bits in stateflags
333 inline void
clearStateFlags(const unsigned int bits)334 SoNode::clearStateFlags(const unsigned int bits)
335 {
336 this->stateflags &= ~bits;
337 }
338
339 // sets bits in stateflags
340 inline void
setStateFlags(const unsigned int bits)341 SoNode::setStateFlags(const unsigned int bits)
342 {
343 this->stateflags |= bits;
344 }
345
346 // return TRUE if any of bits are set
347 inline SbBool
getState(const unsigned int bits) const348 SoNode::getState(const unsigned int bits) const
349 {
350 return (this->stateflags & bits) != 0;
351 }
352
353 // Macro which sets the node id for the node to a new unique id. The
354 // node id is used by the caching system in Coin to quickly identify
355 // changes in the scene graph (and to optimize notification). To
356 // simplify the VBO handling in attribute nodes, no node can have
357 // nodeid == 0 (making it possible for VBO caches to set the current
358 // dataid to 0 to mark the data as invalid / not set).
359 #define SET_UNIQUE_NODE_ID(obj) \
360 CC_MUTEX_LOCK(sonode_mutex); \
361 (obj)->uniqueId = SoNode::nextUniqueId++; \
362 if (obj->uniqueId == 0) { \
363 obj->uniqueId = SoNode::nextUniqueId++; \
364 } \
365 CC_MUTEX_UNLOCK(sonode_mutex)
366
367 // *************************************************************************
368
369 /*!
370 Default constructor, initializes node instance.
371 */
SoNode(void)372 SoNode::SoNode(void)
373 {
374 SET_UNIQUE_NODE_ID(this);
375 this->stateflags = 0; // clear all flags
376
377 // set node type to Inventor by default.
378 this->setNodeType(SoNode::INVENTOR);
379 }
380
381 /*!
382 Destructor.
383 */
~SoNode()384 SoNode::~SoNode()
385 {
386 // check if this is an SoProtoInstance root node.
387 SoProtoInstance * inst = SoProtoInstance::findProtoInstance(this);
388 if (inst) {
389 // unref the instance
390 inst->unref();
391 }
392 #if COIN_DEBUG && 0 // debug
393 SoDebugError::postInfo("SoNode::~SoNode", "%p", this);
394 #endif // debug
395 }
396
397 // *************************************************************************
398
399 /*!
400 Make a duplicate of this node and return a pointer to the duplicate.
401
402 If this node is a group node, children are also copied and we return
403 a pointer to the root of a full copy of the subgraph rooted here.
404
405 If \a copyconnections is \c TRUE, we also copy the connections to
406 fields within this node (and ditto for any children and children's
407 children etc).
408
409
410 Note that this function has been made virtual in Coin, which is not
411 the case in the original Open Inventor API. We may change this
412 method back into being non-virtual again for major Coin versions
413 after this, as it was made virtual more or less by mistake. So
414 please don't write application code that depends on SoNode::copy()
415 being virtual.
416
417 The reason this method should not be virtual is because this is \e
418 not the function the application programmer should override in
419 extension nodes if she needs some special behavior during a copy
420 operation (like copying the value of internal data not exposed as
421 fields).
422
423 For that purpose, override the copyContents() method. Your
424 overridden copyContents() method should then \e both copy internal
425 data aswell as calling the parent superclass' copyContents() method
426 for automatically handling of fields and other common data.
427 */
428 SoNode *
copy(SbBool copyconnections) const429 SoNode::copy(SbBool copyconnections) const
430 {
431 // FIXME: "de-virtualize" this method for next major Coin release?
432 // See method documentation above. 20011220 mortene.
433
434 SoFieldContainer::initCopyDict();
435 SoNode * cp = this->addToCopyDict();
436 // ref() to make sure the copy is not destructed while copying
437 cp->ref();
438 // Call findCopy() to have copyContents() run only once.
439 #if COIN_DEBUG
440 SoNode * cp2 = (SoNode *)SoFieldContainer::findCopy(this, copyconnections);
441 assert(cp == cp2);
442 #else // COIN_DEBUG
443 (void) SoFieldContainer::findCopy(this, copyconnections);
444 #endif
445 SoFieldContainer::copyDone();
446 // unrefNoDelete() so that we return a copy with reference count 0
447 cp->unrefNoDelete();
448 return cp;
449 }
450
451
452 // Overridden from parent.
453 void
startNotify(void)454 SoNode::startNotify(void)
455 {
456 inherited::startNotify();
457 }
458
459 // Overridden from parent.
460 void
notify(SoNotList * l)461 SoNode::notify(SoNotList * l)
462 {
463 #if COIN_DEBUG && 0 // debug
464 SoDebugError::postInfo("SoNode::notify", "node %p (%s \"%s\"), list %p",
465 this, this->getTypeId().getName().getString(),
466 this->getName().getString(), l);
467 #endif // debug
468
469 // only continue if node hasn't already been notified.
470 // The time stamp is set in the SoNotList constructor.
471 if (l->getTimeStamp() > this->uniqueId) {
472 SET_UNIQUE_NODE_ID(this);
473 inherited::notify(l);
474 }
475 }
476
477 /*!
478 \COININTERNAL
479 */
480 int
getActionMethodIndex(const SoType type)481 SoNode::getActionMethodIndex(const SoType type)
482 {
483 return type.getData();
484 }
485
486 /*!
487 \COININTERNAL
488
489 Only in TGS Inventor on Win32 -- to avoid needing to export the
490 nextActionMethodIndex member, see SoNode.h for more info.
491 */
492 void
setNextActionMethodIndex(int index)493 SoNode::setNextActionMethodIndex(int index)
494 {
495 SoNode::nextActionMethodIndex = index;
496 }
497
498 /*!
499 \COININTERNAL
500
501 Only in TGS Inventor on Win32 -- to avoid needing to export the
502 nextActionMethodIndex member, see SoNode.h for more info.
503 */
504 int
getNextActionMethodIndex(void)505 SoNode::getNextActionMethodIndex(void)
506 {
507 return SoNode::nextActionMethodIndex;
508 }
509
510 /*!
511 \COININTERNAL
512
513 Only in TGS Inventor on Win32 -- to avoid needing to export the
514 nextActionMethodIndex member, see SoNode.h for more info.
515 */
516 void
incNextActionMethodIndex(void)517 SoNode::incNextActionMethodIndex(void)
518 {
519 SoNode::nextActionMethodIndex++;
520 }
521
522 // doc in super
523 void
initClass(void)524 SoNode::initClass(void)
525 {
526 // Make sure we only initialize once.
527 assert(SoNode::classTypeId == SoType::badType());
528 // Make sure parent class has been initialized.
529 assert(inherited::getClassTypeId() != SoType::badType());
530
531 CC_MUTEX_CONSTRUCT(sonode_mutex);
532 SoNode::classTypeId =
533 SoType::createType(inherited::getClassTypeId(), "Node", NULL,
534 SoNode::nextActionMethodIndex++);
535
536 // initialize the compatibility dict
537 compatibility_dict = new Int16ToUInt32Map;
538 coin_atexit((coin_atexit_f*)SoNode::cleanupClass, CC_ATEXIT_NORMAL);
539
540 SoNode::setCompatibilityTypes(SoNode::getClassTypeId(),
541 SO_FROM_INVENTOR_1);
542
543 SoNode::initClasses();
544
545 // action methods must be initialized here, since both nodes and
546 // actions must be initialized before we can use
547 // SO_ACTION_ADD_METHOD
548 init_action_methods();
549 }
550
551 /*!
552 Initialize all the node classes of Coin.
553 */
554 void
initClasses(void)555 SoNode::initClasses(void)
556 {
557 SoCamera::initClass();
558 SoPerspectiveCamera::initClass();
559 SoReversePerspectiveCamera::initClass();
560 SoOrthographicCamera::initClass();
561 SoFrustumCamera::initClass();
562 SoShape::initClass();
563 SoAsciiText::initClass();
564 SoCone::initClass();
565 SoCube::initClass();
566 SoCylinder::initClass();
567 SoVertexShape::initClass();
568 SoNonIndexedShape::initClass();
569 SoFaceSet::initClass();
570 SoLineSet::initClass();
571 SoPointSet::initClass();
572 SoMarkerSet::initClass();
573 SoQuadMesh::initClass();
574 SoTriangleStripSet::initClass();
575 SoIndexedShape::initClass();
576 SoIndexedFaceSet::initClass();
577 SoIndexedLineSet::initClass();
578 SoIndexedPointSet::initClass();
579 SoIndexedMarkerSet::initClass();
580 SoIndexedTriangleStripSet::initClass();
581 SoImage::initClass();
582 SoIndexedNurbsCurve::initClass();
583 SoIndexedNurbsSurface::initClass();
584 SoNurbsCurve::initClass();
585 SoNurbsSurface::initClass();
586 SoSphere::initClass();
587 SoText2::initClass();
588 SoText3::initClass();
589 SoGroup::initClass();
590 SoSeparator::initClass();
591 SoAnnotation::initClass();
592 SoLocateHighlight::initClass();
593 SoWWWAnchor::initClass();
594 SoArray::initClass();
595 SoSwitch::initClass();
596 SoBlinker::initClass();
597 SoLOD::initClass();
598 SoLevelOfDetail::initClass();
599 SoMultipleCopy::initClass();
600 SoPathSwitch::initClass();
601 SoTransformSeparator::initClass();
602 SoTransformation::initClass();
603 SoMatrixTransform::initClass();
604 SoRotation::initClass();
605 SoPendulum::initClass();
606 SoRotor::initClass();
607 SoResetTransform::initClass();
608 SoRotationXYZ::initClass();
609 SoScale::initClass();
610 SoTranslation::initClass();
611 SoShuttle::initClass();
612 SoTransform::initClass();
613 SoUnits::initClass();
614 SoBaseColor::initClass();
615 SoCallback::initClass();
616 SoClipPlane::initClass();
617 SoColorIndex::initClass();
618 SoComplexity::initClass();
619 SoCoordinate3::initClass();
620 SoCoordinate4::initClass();
621 SoLight::initClass();
622 SoDirectionalLight::initClass();
623 SoSpotLight::initClass();
624 SoPointLight::initClass();
625 SoDrawStyle::initClass();
626 SoEnvironment::initClass();
627 SoEventCallback::initClass();
628 SoFile::initClass();
629 SoFont::initClass();
630 SoFontStyle::initClass();
631 SoInfo::initClass();
632 SoLabel::initClass();
633 SoLightModel::initClass();
634 SoProfile::initClass();
635 SoLinearProfile::initClass();
636 SoNurbsProfile::initClass();
637 SoMaterial::initClass();
638 SoMaterialBinding::initClass();
639 SoVertexAttributeBinding::initClass();
640 SoNormal::initClass();
641 SoNormalBinding::initClass();
642 SoPackedColor::initClass();
643 SoPickStyle::initClass();
644 SoPolygonOffset::initClass();
645 SoProfileCoordinate2::initClass();
646 SoProfileCoordinate3::initClass();
647 SoShapeHints::initClass();
648 SoTexture::initClass();
649 SoTexture2::initClass();
650 SoTexture3::initClass();
651 SoTexture2Transform::initClass();
652 SoTexture3Transform::initClass();
653 SoTextureMatrixTransform::initClass();
654 SoTextureCoordinate2::initClass();
655 SoTextureCoordinate3::initClass();
656 SoTextureCoordinateBinding::initClass();
657 SoTextureCoordinateFunction::initClass();
658 SoTextureCoordinateDefault::initClass();
659 SoTextureCoordinateEnvironment::initClass();
660 SoTextureCoordinatePlane::initClass();
661 SoUnknownNode::initClass();
662 SoVertexProperty::initClass();
663 SoWWWInline::initClass();
664 SoListener::initClass();
665
666 SoTransparencyType::initClass();
667 SoTextureScalePolicy::initClass();
668
669 SoTextureUnit::initClass();
670
671 SoBumpMap::initClass();
672 SoBumpMapCoordinate::initClass();
673 SoBumpMapTransform::initClass();
674
675 SoSceneTexture2::initClass();
676 SoSceneTextureCubeMap::initClass();
677
678 SoTextureCoordinateCube::initClass();
679 SoTextureCoordinateSphere::initClass();
680 SoTextureCoordinateCylinder::initClass();
681
682 SoTextureCombine::initClass();
683 SoCacheHint::initClass();
684 SoTextureCubeMap::initClass();
685 SoTextureCoordinateNormalMap::initClass();
686 SoTextureCoordinateReflectionMap::initClass();
687 SoTextureCoordinateObject::initClass();
688 SoVertexAttribute::initClass();
689
690 SoDepthBuffer::initClass();
691 SoAlphaTest::initClass();
692 }
693
694 /*!
695 Set the override flag.
696
697 If this flag is \c TRUE, the field values of this node will override
698 the field values of other nodes of the same type during scene graph
699 traversal.
700
701 A common applicaton for "override nodes" is to place them at the top
702 of the tree as a convenient way to force e.g. a common drawstyle on
703 the complete tree.
704
705 The override flag does not exist in the Inventor file format. This
706 flag is in other words not persistent, and must be programmatically
707 set. The rationale for this flag is for viewers to be able to
708 control rendering style of the 3D models, so it would look stupid if
709 some parts of certain models suddenly didn't adhere to the viewer
710 mode.
711 */
712 void
setOverride(const SbBool state)713 SoNode::setOverride(const SbBool state)
714 {
715 if (state != this->getState(FLAG_OVERRIDE)) {
716 // This change affects caches in the tree, so we must change our id
717 // setting, so the caches are regenerated.
718 SET_UNIQUE_NODE_ID(this);
719
720 if (state) this->setStateFlags(FLAG_OVERRIDE);
721 else this->clearStateFlags(FLAG_OVERRIDE);
722 }
723 }
724
725 /*!
726 Return status of override flag.
727
728 \sa setOverride()
729 */
730 SbBool
isOverride(void) const731 SoNode::isOverride(void) const
732 {
733 return this->getState(FLAG_OVERRIDE);
734 }
735
736 /*!
737 Sets the node type for this node to \a type. Since some nodes
738 should be handled differently in VRML1 vs. Inventor, this
739 should be used to get correct behavior for those cases.
740 The default node type is INVENTOR.
741
742 This method is an extension versus the Open Inventor API.
743
744 \sa getNodeType()
745 */
746 void
setNodeType(const NodeType type)747 SoNode::setNodeType(const NodeType type)
748 {
749 // make sure we have enogh bits to store this type
750 assert((uint32_t) type <= FLAG_TYPEMASK);
751 // clear old type
752 this->clearStateFlags(FLAG_TYPEMASK);
753 // set new type
754 this->setStateFlags((uint32_t) type);
755 }
756
757 /*!
758 Returns the node type set for this node.
759
760 This method is an extension versus the Open Inventor API.
761
762 \sa setNodeType()
763 */
764 SoNode::NodeType
getNodeType(void) const765 SoNode::getNodeType(void) const
766 {
767 uint32_t type = this->stateflags & FLAG_TYPEMASK;
768 return (NodeType) type;
769 }
770
771 /*!
772 Returns the last node that was registered under \a name.
773
774 \sa SoBase::setName()
775 */
776 SoNode *
getByName(const SbName & name)777 SoNode::getByName(const SbName & name)
778 {
779 SoBase * b = SoBase::getNamedBase(name, SoNode::getClassTypeId());
780 if (!b) return NULL;
781 return (SoNode *)b;
782 }
783
784 /*!
785 Finds all nodes with \a name and appends them to the \a l nodelist.
786 Returns the number of nodes with the specified name.
787
788 \sa SoBase::setName()
789 */
790 int
getByName(const SbName & name,SoNodeList & l)791 SoNode::getByName(const SbName & name, SoNodeList & l)
792 {
793 SoBaseList bl;
794 int nr = SoBase::getNamedBases(name, bl, SoNode::getClassTypeId());
795 for (int i=0; i < nr; i++) l.append((SoNode *)bl[i]);
796 return nr;
797 }
798
799
800 // *************************************************************************
801 // * ACTION STUFF
802 // *************************************************************************
803
804 /*!
805 This function performs the typical operation of a node for any
806 action.
807 */
808 void
doAction(SoAction * COIN_UNUSED_ARG (action))809 SoNode::doAction(SoAction * COIN_UNUSED_ARG(action))
810 {
811 }
812
813 // Note that this documentation will also be used for all subclasses
814 // which reimplements the method, so keep the doc "generic enough".
815 /*!
816 Returns \c TRUE if the node could have any effect on the state
817 during traversal.
818
819 If it returns \c FALSE, no data in the traversal-state will change
820 from the pre-traversal state to the post-traversal state. The
821 SoSeparator node will for instance return \c FALSE, as it pushes and
822 pops the state before and after traversal of its children. All
823 SoShape nodes will also return \c FALSE, as just pushing out
824 geometry data to the rendering engine won't affect the actual
825 rendering state.
826
827 The default method returns \c TRUE, on a "better safe than sorry"
828 philosophy.
829 */
830 SbBool
affectsState(void) const831 SoNode::affectsState(void) const
832 {
833 return TRUE;
834 }
835
836 /*!
837 This is a static "helper" method registered with the action, and
838 used for calling the SoNode::getBoundingBox() virtual method which
839 does the \e real work.
840 */
841 void
getBoundingBoxS(SoAction * action,SoNode * node)842 SoNode::getBoundingBoxS(SoAction * action, SoNode * node)
843 {
844 assert(action && node);
845 SoGetBoundingBoxAction * bboxaction = (SoGetBoundingBoxAction *)action;
846 bboxaction->checkResetBefore();
847 node->getBoundingBox(bboxaction);
848 bboxaction->checkResetAfter();
849 }
850
851 // Note that this documentation will also be used for all subclasses
852 // which reimplements the method, so keep the doc "generic enough".
853 /*!
854 Action method for the SoGetBoundingBoxAction.
855
856 Calculates bounding box and center coordinates for node and modifies
857 the values of the \a action to encompass the bounding box for this
858 node and to shift the center point for the scene more towards the
859 one for this node.
860
861 Nodes influencing how geometry nodes calculates their bounding box
862 also overrides this method to change the relevant state variables.
863 */
864 void
getBoundingBox(SoGetBoundingBoxAction * COIN_UNUSED_ARG (action))865 SoNode::getBoundingBox(SoGetBoundingBoxAction * COIN_UNUSED_ARG(action))
866 {
867 }
868
869 /*!
870 This is a static "helper" method registered with the action, and
871 used for calling the SoNode::getPrimitiveCount() virtual method
872 which does the \e real work.
873 */
874 void
getPrimitiveCountS(SoAction * action,SoNode * node)875 SoNode::getPrimitiveCountS(SoAction * action, SoNode * node)
876 {
877 assert(action && node);
878 node->getPrimitiveCount((SoGetPrimitiveCountAction *)action);
879 }
880
881 // Note that this documentation will also be used for all subclasses
882 // which reimplements the method, so keep the doc "generic enough".
883 /*!
884 Action method for the SoGetPrimitiveCountAction.
885
886 Calculates the number of triangle, line segment and point primitives
887 for the node and adds these to the counters of the \a action.
888
889 Nodes influencing how geometry nodes calculates their primitive
890 count also overrides this method to change the relevant state
891 variables.
892 */
893 void
getPrimitiveCount(SoGetPrimitiveCountAction * COIN_UNUSED_ARG (action))894 SoNode::getPrimitiveCount(SoGetPrimitiveCountAction * COIN_UNUSED_ARG(action))
895 {
896 }
897
898 // *************************************************************************
899
900 /*!
901 This is a static "helper" method registered with the action, and
902 used for calling the SoNode::GLRender() virtual method which does
903 the \e real work.
904 */
905 void
GLRenderS(SoAction * action,SoNode * node)906 SoNode::GLRenderS(SoAction * action, SoNode * node)
907 {
908 if ((action->getCurPathCode() != SoAction::OFF_PATH) ||
909 node->affectsState()) {
910 if (((SoGLRenderAction*)action)->abortNow()) {
911 SoCacheElement::invalidate(action->getState());
912 }
913 else {
914 node->GLRender((SoGLRenderAction*)action);
915 }
916 }
917
918 if (COIN_DEBUG) {
919 // Note: debugging code like this is also present in
920 // SoSeparator::GLRenderBelowPath() and SoState::lazyEvaluate(),
921 // but they are default disabled -- even when COIN_DEBUG=1 (due to
922 // performance reasons).
923 //
924 // If you're seeing notifications about GL-errors from this place,
925 // the first thing to do is to enable those debugging checks too
926 // by setting COIN_GLERROR_DEBUGGING to "1".
927 cc_string str;
928 cc_string_construct(&str);
929 const unsigned int errs = coin_catch_gl_errors(&str);
930 if (errs > 0) {
931 const SbBool extradebug = sogl_glerror_debugging();
932 SoDebugError::post("SoNode::GLRenderS",
933 "GL error: '%s', nodetype: %s %s",
934 cc_string_get_text(&str),
935 node->getTypeId().getName().getString(),
936 extradebug ? "" :
937 "(set envvar COIN_GLERROR_DEBUGGING=1 "
938 "and re-run to get more information)");
939 }
940 cc_string_clean(&str);
941 }
942 }
943
944 // Note that this documentation will also be used for all subclasses
945 // which reimplements the method, so keep the doc "generic enough".
946 /*!
947 Action method for the SoGLRenderAction.
948
949 This is called during rendering traversals. Nodes influencing the
950 rendering state in any way or who wants to throw geometry primitives
951 at OpenGL overrides this method.
952 */
953 void
GLRender(SoGLRenderAction * COIN_UNUSED_ARG (action))954 SoNode::GLRender(SoGLRenderAction * COIN_UNUSED_ARG(action))
955 {
956 }
957
958 // Note that this documentation will also be used for all subclasses
959 // which reimplements the method, so keep the doc "generic enough".
960 /*!
961 Implements the SoAction::BELOW_PATH traversal method for the
962 rendering action.
963 */
964 void
GLRenderBelowPath(SoGLRenderAction * action)965 SoNode::GLRenderBelowPath(SoGLRenderAction * action)
966 {
967 this->GLRender(action);
968 }
969
970 // Note that this documentation will also be used for all subclasses
971 // which reimplements the method, so keep the doc "generic enough".
972 /*!
973 Implements the SoAction::IN_PATH traversal method for the rendering
974 action.
975 */
976 void
GLRenderInPath(SoGLRenderAction * action)977 SoNode::GLRenderInPath(SoGLRenderAction * action)
978 {
979 this->GLRender(action);
980 }
981
982 // Note that this documentation will also be used for all subclasses
983 // which reimplements the method, so keep the doc "generic enough".
984 /*!
985 Implements the SoAction::OFF_PATH traversal method for the rendering
986 action.
987 */
988 void
GLRenderOffPath(SoGLRenderAction * action)989 SoNode::GLRenderOffPath(SoGLRenderAction * action)
990 {
991 this->GLRender(action);
992 }
993
994 // *************************************************************************
995
996 /*!
997 This is a static "helper" method registered with the action, and
998 used for calling the SoNode::callback() virtual method which does
999 the \e real work.
1000 */
1001 void
callbackS(SoAction * action,SoNode * node)1002 SoNode::callbackS(SoAction * action, SoNode * node)
1003 {
1004 assert(action && node);
1005 SoCallbackAction * const cbAction = (SoCallbackAction *)(action);
1006 if (cbAction->hasTerminated()) return;
1007 cbAction->setCurrentNode(node);
1008
1009 cbAction->invokePreCallbacks(node);
1010 if (cbAction->getCurrentResponse() == SoCallbackAction::CONTINUE) {
1011 node->callback(cbAction);
1012 }
1013 cbAction->invokePostCallbacks(node);
1014 }
1015
1016 // Note that this documentation will also be used for all subclasses
1017 // which reimplements the method, so keep the doc "generic enough".
1018 /*!
1019 Action method for SoCallbackAction.
1020
1021 Simply updates the state according to how the node behaves for the
1022 render action, so the application programmer can use the
1023 SoCallbackAction for extracting information about the scene graph.
1024 */
1025 void
callback(SoCallbackAction * COIN_UNUSED_ARG (action))1026 SoNode::callback(SoCallbackAction * COIN_UNUSED_ARG(action))
1027 {
1028 }
1029
1030 /*!
1031 This is a static "helper" method registered with the action, and
1032 used for calling the SoNode::getMatrix() virtual method which does
1033 the \e real work.
1034 */
1035 void
getMatrixS(SoAction * action,SoNode * node)1036 SoNode::getMatrixS(SoAction * action, SoNode * node)
1037 {
1038 assert(action && node);
1039 assert(action->getTypeId() == SoGetMatrixAction::getClassTypeId());
1040 SoGetMatrixAction * const getMatrixAction = (SoGetMatrixAction *)(action);
1041 node->getMatrix(getMatrixAction);
1042 }
1043
1044 // Note that this documentation will also be used for all subclasses
1045 // which reimplements the method, so keep the doc "generic enough".
1046 /*!
1047 Action method for SoGetMatrixAction.
1048
1049 Updates \a action by accumulating with the transformation matrix of
1050 this node (if any).
1051 */
1052 void
getMatrix(SoGetMatrixAction * COIN_UNUSED_ARG (action))1053 SoNode::getMatrix(SoGetMatrixAction * COIN_UNUSED_ARG(action))
1054 {
1055 }
1056
1057 /*!
1058 This is a static "helper" method registered with the action, and
1059 used for calling the SoNode::handleEvent() virtual method which does
1060 the \e real work.
1061 */
1062 void
handleEventS(SoAction * action,SoNode * node)1063 SoNode::handleEventS(SoAction * action, SoNode * node)
1064 {
1065 assert(action && node);
1066 assert(action->getTypeId().isDerivedFrom(SoHandleEventAction::getClassTypeId()));
1067 SoHandleEventAction * handleEventAction = (SoHandleEventAction *)(action);
1068 node->handleEvent(handleEventAction);
1069 }
1070
1071 // Note that this documentation will also be used for all subclasses
1072 // which reimplements the method, so keep the doc "generic enough".
1073 /*!
1074 Action method for SoHandleEventAction.
1075
1076 Inspects the event data from \a action, and processes it if it is
1077 something which this node should react to.
1078
1079 Nodes influencing relevant state variables for how event handling is
1080 done also overrides this method.
1081 */
1082 void
handleEvent(SoHandleEventAction * COIN_UNUSED_ARG (action))1083 SoNode::handleEvent(SoHandleEventAction * COIN_UNUSED_ARG(action))
1084 {
1085 }
1086
1087 /*!
1088 This is a static "helper" method registered with the action, and
1089 used for calling the SoNode::pick() virtual method which does the \e
1090 real work.
1091 */
1092 void
pickS(SoAction * action,SoNode * node)1093 SoNode::pickS(SoAction * action, SoNode * node)
1094 {
1095 assert(action && node);
1096 assert(action->getTypeId().isDerivedFrom(SoPickAction::getClassTypeId()));
1097 SoPickAction * const pickAction = (SoPickAction *)(action);
1098 node->pick(pickAction);
1099 }
1100
1101 // Note that this documentation will also be used for all subclasses
1102 // which reimplements the method, so keep the doc "generic enough".
1103 /*!
1104 Action method for SoPickAction.
1105
1106 Does common processing for SoPickAction \a action instances.
1107 */
1108 void
pick(SoPickAction * COIN_UNUSED_ARG (action))1109 SoNode::pick(SoPickAction * COIN_UNUSED_ARG(action))
1110 {
1111 }
1112
1113 /*!
1114 This is a static "helper" method registered with the action, and
1115 used for calling the SoNode::rayPick() virtual method which does the
1116 \e real work.
1117 */
1118 void
rayPickS(SoAction * action,SoNode * node)1119 SoNode::rayPickS(SoAction * action, SoNode * node)
1120 {
1121 assert(action && node);
1122 assert(action->getTypeId().isDerivedFrom(SoRayPickAction::getClassTypeId()));
1123 SoRayPickAction * const rayPickAction = (SoRayPickAction *)(action);
1124 node->rayPick(rayPickAction);
1125 }
1126
1127 // Note that this documentation will also be used for all subclasses
1128 // which reimplements the method, so keep the doc "generic enough".
1129 /*!
1130 Action method for SoRayPickAction.
1131
1132 Checks the ray specification of the \a action and tests for
1133 intersection with the data of the node.
1134
1135 Nodes influencing relevant state variables for how picking is done
1136 also overrides this method.
1137 */
1138 void
rayPick(SoRayPickAction * action)1139 SoNode::rayPick(SoRayPickAction * action)
1140 {
1141 // if node has no defined rayPick(), try the pick method
1142 this->pick(action);
1143 }
1144
1145 /*!
1146 This is a static "helper" method registered with the action, and
1147 used for calling the SoNode::search() virtual method which does the
1148 \e real work.
1149 */
1150 void
searchS(SoAction * action,SoNode * node)1151 SoNode::searchS(SoAction * action, SoNode * node)
1152 {
1153 assert(action && node);
1154 assert(action->getTypeId().isDerivedFrom(SoSearchAction::getClassTypeId()));
1155 SoSearchAction * const searchAction = (SoSearchAction *)(action);
1156 node->search(searchAction);
1157 }
1158
1159 // Note that this documentation will also be used for all subclasses
1160 // which reimplements the method, so keep the doc "generic enough".
1161 /*!
1162 Action method for SoSearchAction.
1163
1164 Compares the search criteria from the \a action to see if this node
1165 is a match. Searching is done by matching up \e all criteria set up
1166 in the SoSearchAction -- if \e any of the requested criteria is a
1167 miss, the search is not deemed successful for the node.
1168
1169 \sa SoSearchAction
1170 */
1171 void
search(SoSearchAction * action)1172 SoNode::search(SoSearchAction * action)
1173 {
1174 if (action->isFound()) { return; }
1175
1176 int lookfor = action->getFind();
1177 SbBool hit = FALSE;
1178
1179 // A little tidbit of history, which could be relevant when
1180 // answering support inquiries: Coin v1.0.0 was released with a bug
1181 // where just one hit out of the criteria would make the search
1182 // operation on the node successful. Since this doesn't match
1183 // neither the behavior of SGI Inventor nor the documentation for
1184 // SoSearchAction, we corrected the behavior for Coin v1.0.1 even
1185 // though this is on the borderline of what is acceptable for fixing
1186 // in a minor patch-release update.
1187 //
1188 // mortene.
1189
1190 if (lookfor & SoSearchAction::NODE) {
1191 hit = this == action->getNode();
1192 if (!hit) { return; }
1193 }
1194
1195 if (lookfor & SoSearchAction::NAME) {
1196 hit = this->getName() == action->getName();
1197 if (!hit) { return; }
1198 }
1199
1200 if (lookfor & SoSearchAction::TYPE) {
1201 SbBool chkderived;
1202 SoType searchtype = action->getType(chkderived);
1203 hit = (this->getTypeId() == searchtype) ||
1204 (chkderived && this->getTypeId().isDerivedFrom(searchtype));
1205 if (!hit) { return; }
1206 }
1207
1208 if (hit) { action->addPath(action->getCurPath()->copy()); }
1209 }
1210
1211 /*!
1212 This is a static "helper" method registered with the action, and
1213 used for calling the SoNode::write() virtual method which does the
1214 \e real work.
1215 */
1216 void
writeS(SoAction * action,SoNode * node)1217 SoNode::writeS(SoAction * action, SoNode * node)
1218 {
1219 assert(action && node);
1220 assert(action->getTypeId().isDerivedFrom(SoWriteAction::getClassTypeId()));
1221 SoWriteAction * const writeAction = (SoWriteAction *)(action);
1222
1223 // Do not write Proto instance graphs. Just let the Proto instance
1224 // class handle the writing.
1225 SoProtoInstance * proto = SoProtoInstance::findProtoInstance(node);
1226 if (proto) {
1227 node = proto;
1228 }
1229 node->write(writeAction);
1230 }
1231
1232 // Note that this documentation will also be used for all subclasses
1233 // which reimplements the method, so keep the doc "generic enough".
1234 /*!
1235 Action method for SoWriteAction.
1236
1237 Writes out a node object, and any connected nodes, engines etc, if
1238 necessary.
1239 */
1240 void
write(SoWriteAction * action)1241 SoNode::write(SoWriteAction * action)
1242 {
1243 SoOutput * out = action->getOutput();
1244
1245 SoNode * node = this;
1246
1247 SoProtoInstance * proto = SoProtoInstance::findProtoInstance(this);
1248 if (proto) { node = proto; }
1249
1250 if (out->getStage() == SoOutput::COUNT_REFS) {
1251 node->addWriteReference(out, FALSE);
1252 }
1253 else if (out->getStage() == SoOutput::WRITE) {
1254 if (node->writeHeader(out, FALSE, FALSE)) return;
1255
1256 // check for special case where we actually have to write out an
1257 // SoEngineOutput "field". An engine output might be connected via
1258 // an IS reference in a PROTO, and we then need to write back this
1259 // IS reference when exporting the VRML file.
1260 SoProto * proto = out->getCurrentProto();
1261 if (proto && node->isOfType(SoNodeEngine::getClassTypeId())) {
1262 SoEngineOutputList l;
1263 const int num = ((SoNodeEngine*)node)->getOutputs(l);
1264
1265 for (int i = 0; i < num; i++) {
1266 SbName name;
1267 if (((SoNodeEngine*)node)->getOutputName(l[i], name)) {
1268 SbName pname = proto->findISReference(node, name);
1269 if (pname.getLength()) {
1270 out->indent();
1271 out->write(name.getString());
1272 out->write(" IS ");
1273 out->write(pname.getString());
1274 out->write("\n");
1275 }
1276 }
1277 }
1278 }
1279 node->getFieldData()->write(out, node);
1280 node->writeFooter(out);
1281 }
1282 else assert(0 && "unknown stage");
1283 }
1284
1285 /*!
1286 This is a static "helper" method registered with the action, and
1287 used for calling the SoNode::audioRender() virtual method which does the \e
1288 real work.
1289 */
1290 void
audioRenderS(SoAction * action,SoNode * node)1291 SoNode::audioRenderS(SoAction * action, SoNode * node)
1292 {
1293 assert(action && node);
1294 assert(action->getTypeId().isDerivedFrom(SoAudioRenderAction::getClassTypeId()));
1295 SoAudioRenderAction * const ara = (SoAudioRenderAction *)(action);
1296 node->audioRender(ara);
1297 }
1298
1299 // Note that this documentation will also be used for all subclasses
1300 // which reimplements the method, so keep the doc "generic enough".
1301 /*!
1302 Action method for SoAudioRenderAction.
1303
1304 Does common processing for SoAudioRenderAction \a action instances.
1305 */
1306 void
audioRender(SoAudioRenderAction * COIN_UNUSED_ARG (action))1307 SoNode::audioRender(SoAudioRenderAction * COIN_UNUSED_ARG(action))
1308 {
1309 }
1310
1311 // Note that this documentation will also be used for all subclasses
1312 // which reimplements the method, so keep the doc "generic enough".
1313 /*!
1314 Returns list of children for this node.
1315 */
1316 SoChildList *
getChildren(void) const1317 SoNode::getChildren(void) const
1318 {
1319 return NULL;
1320 }
1321
1322 /*!
1323 Called from SoHandleEventAction::setGrabber() to notify a node when
1324 it becomes the node where all events are sent.
1325 */
1326 void
grabEventsSetup(void)1327 SoNode::grabEventsSetup(void)
1328 {
1329 }
1330
1331 /*!
1332 Called from SoHandleEventAction to notify a node when it looses
1333 status as the node where events are sent.
1334 */
1335 void
grabEventsCleanup(void)1336 SoNode::grabEventsCleanup(void)
1337 {
1338 }
1339
1340 /*!
1341 This returns the node's current unique identification number. It is
1342 unlikely that application programmers will ever need use this method
1343 fom client application code, unless working with extensions to the
1344 core library (and probably not even then).
1345
1346 The id number is only valid for as long as the node is kept
1347 unchanged -- upon \e any kind of change the internal id will be
1348 updated (in the notify() method), and the old id number forgotten.
1349
1350 The technique described above plays an important role in the way
1351 internal scenegraph caches are set up and invalidated.
1352
1353 \sa SoNode::getNextNodeId()
1354 */
1355 SbUniqueId
getNodeId(void) const1356 SoNode::getNodeId(void) const
1357 {
1358 return this->uniqueId;
1359 }
1360
1361 // Documentation in superclass.
1362 void
writeInstance(SoOutput * out)1363 SoNode::writeInstance(SoOutput * out)
1364 {
1365 SoNode * node = this;
1366
1367 SoProtoInstance * proto = SoProtoInstance::findProtoInstance(this);
1368 if (proto) { node = proto; }
1369
1370 // Catch common misuse of SoOutput (a single pass instead of two,
1371 // lacking the setStage() initialization).
1372 assert(((out->getStage() == SoOutput::COUNT_REFS) ||
1373 (out->getStage() == SoOutput::WRITE)) &&
1374 "unknown write stage");
1375 SoWriteAction wa(out);
1376 wa.continueToApply(node);
1377 }
1378
1379 /*!
1380 Add a copy of this node and (recursively) all children to the copy
1381 dictionary of SoFieldContainer if this has not already been done.
1382
1383 Used internally during copy operations.
1384 */
1385 SoNode *
addToCopyDict(void) const1386 SoNode::addToCopyDict(void) const
1387 {
1388 #if COIN_DEBUG && 0 // debug
1389 SoDebugError::postInfo("SoNode::addToCopyDict",
1390 "%s node", this->getTypeId().getName().getString());
1391 #endif // debug
1392
1393 SoNode * cp = (SoNode *)SoFieldContainer::checkCopy(this);
1394 if (!cp) {
1395 // We need to do some extra work when copying nodes that are
1396 // ProtoInstance root nodes. We create a new ProtoInstance node,
1397 // and register its root node as the copy. pederb, 2002-06-17
1398 SoProtoInstance * inst = SoProtoInstance::findProtoInstance(this);
1399 if (inst) {
1400 SoProto * proto = inst->getProtoDefinition();
1401 SoProtoInstance * newinst = proto->createProtoInstance();
1402 if (inst->getName().getLength()) newinst->setName(inst->getName());
1403 cp = newinst->getRootNode();
1404 assert(cp);
1405 // We have to call addCopy() before calling copyContents() since
1406 // the proto instance might have a field that has a pointer to
1407 // the root node. pederb, 2002-09-04
1408 SoFieldContainer::addCopy(this, cp);
1409 newinst->copyContents(inst, FALSE);
1410 }
1411 else {
1412 if (this->isOfType(SoProto::getClassTypeId())) {
1413 // just copy the pointer. A PROTO definition is
1414 // read-only. It's not possible to change it after it has been
1415 // created so this should be safe.
1416 cp = (SoNode*) this;
1417 }
1418 else {
1419 cp = (SoNode *)this->getTypeId().createInstance();
1420 }
1421 assert(cp);
1422 SoFieldContainer::addCopy(this, cp);
1423
1424 SoChildList * l = this->getChildren();
1425 for (int i=0; l && (i < l->getLength()); i++)
1426 (void)(*l)[i]->addToCopyDict();
1427 }
1428 }
1429 return cp;
1430 }
1431
1432 // Doc in superclass.
1433 void
copyContents(const SoFieldContainer * from,SbBool copyconnections)1434 SoNode::copyContents(const SoFieldContainer * from, SbBool copyconnections)
1435 {
1436 // workaround when copying PROTO definitions. A PROTO definition is
1437 // read-only, and we just copy the pointer (in
1438 // SoNode::addToCopyDict(), not the contents.
1439 if (!this->isOfType(SoProto::getClassTypeId())) {
1440 inherited::copyContents(from, copyconnections);
1441
1442 SoNode * src = (SoNode *)from;
1443 this->stateflags = src->stateflags;
1444 }
1445 }
1446
1447 // Overridden from parent class.
1448 SoFieldContainer *
copyThroughConnection(void) const1449 SoNode::copyThroughConnection(void) const
1450 {
1451 // Important note: _don't_ try to optimize by skipping the
1452 // checkCopy() call, as we're not supposed to create copies of
1453 // containers "outside" the part of the scene graph which is
1454 // involved in the copy operation.
1455 SoFieldContainer * connfc = SoFieldContainer::checkCopy(this);
1456 // if a copy has been made, return the findCopy instance (findCopy
1457 // will run copyContents() the first time it's called on an
1458 // instance).
1459 if (connfc) return SoFieldContainer::findCopy(this, TRUE);
1460 // if no copy has been made, just return self
1461 return (SoFieldContainer*) this;
1462 }
1463
1464 /*!
1465 Return the next unique identification number to be assigned upon
1466 node construction or change. It is unlikely that application
1467 programmers will ever need use this method from client application
1468 code, unless working with extensions to the core library (and
1469 probably not even then).
1470
1471 \sa SoNode::getNodeId
1472 */
1473 SbUniqueId
getNextNodeId(void)1474 SoNode::getNextNodeId(void)
1475 {
1476 return SoNode::nextUniqueId;
1477 }
1478
1479 /*!
1480 \COININTERNAL
1481 */
1482 const SoFieldData **
getFieldDataPtr(void)1483 SoNode::getFieldDataPtr(void)
1484 {
1485 return NULL;
1486 }
1487
1488 // Doc in super.
1489 SbBool
readInstance(SoInput * in,unsigned short flags)1490 SoNode::readInstance(SoInput * in, unsigned short flags)
1491 {
1492 // Overridden to set node type.
1493
1494 SbBool ret = inherited::readInstance(in, flags);
1495 if (ret) {
1496 if (in->isFileVRML1()) this->setNodeType(SoNode::VRML1);
1497 else if (in->isFileVRML2()) this->setNodeType(SoNode::VRML2);
1498 }
1499 return ret;
1500 }
1501
1502 /*!
1503 Get the node compatibility mask for node type \a nodetype. The
1504 return value will be a bit mask of SoNode::NodeType flags,
1505 containing one or several flags.
1506
1507 \COIN_FUNCTION_EXTENSION
1508
1509 \since Coin 2.0
1510 */
1511 uint32_t
getCompatibilityTypes(const SoType & nodetype)1512 SoNode::getCompatibilityTypes(const SoType & nodetype)
1513 {
1514 assert(compatibility_dict);
1515 assert(nodetype.isDerivedFrom(SoNode::getClassTypeId()));
1516
1517 uint32_t tmp;
1518 if (compatibility_dict->get(nodetype.getKey(), tmp)) { return tmp; }
1519 return SoNode::EXTENSION;
1520 }
1521
1522 /*!
1523 Set the node compatibility mask for node type \a nodetype. The mask
1524 specifies for which file formats the node is supported.
1525
1526 \COIN_FUNCTION_EXTENSION
1527
1528 \sa getCompatibilityMode()
1529 \since Coin 2.0
1530 */
1531 void
setCompatibilityTypes(const SoType & nodetype,const uint32_t bitmask)1532 SoNode::setCompatibilityTypes(const SoType & nodetype, const uint32_t bitmask)
1533 {
1534 assert(compatibility_dict);
1535 assert(nodetype.isDerivedFrom(SoNode::getClassTypeId()));
1536 compatibility_dict->put(nodetype.getKey(), bitmask);
1537 }
1538
1539 //
1540 // called by atexit()
1541 //
1542 void
cleanupClass(void)1543 SoNode::cleanupClass(void)
1544 {
1545 delete compatibility_dict;
1546 SoNode::classTypeId STATIC_SOTYPE_INIT;
1547 CC_MUTEX_DESTRUCT(sonode_mutex);
1548 }
1549
1550 // just undef flags here
1551
1552 #undef FLAG_TYPEMASK
1553 #undef FLAG_OVERRIDE
1554
1555 // The following function should probably eventually be renamed/moved
1556 // to SoAction::initActionMethods(). We cannot initialize action
1557 // methods in SoAction::initClass() since nodes must be initialized
1558 // before we can set up action methods, and we cannot initialize nodes
1559 // before actions, since elements (which also depend on actions) are
1560 // enabled in nodes.
1561 static void
init_action_methods(void)1562 init_action_methods(void)
1563 {
1564 SoCallbackAction::addMethod(SoNode::getClassTypeId(), SoNode::callbackS);
1565 SoGLRenderAction::addMethod(SoNode::getClassTypeId(), SoNode::GLRenderS);
1566 SoGetBoundingBoxAction::addMethod(SoNode::getClassTypeId(), SoNode::getBoundingBoxS);
1567 SoGetMatrixAction::addMethod(SoNode::getClassTypeId(), SoNode::getMatrixS);
1568 SoGetPrimitiveCountAction::addMethod(SoNode::getClassTypeId(), SoNode::getPrimitiveCountS);
1569 SoHandleEventAction::addMethod(SoNode::getClassTypeId(), SoNode::handleEventS);
1570 SoPickAction::addMethod(SoNode::getClassTypeId(), SoNode::pickS);
1571
1572 // most methods for SoRayPickAction are inherited from SoPickAction
1573 SoRayPickAction::addMethod(SoCamera::getClassTypeId(), SoNode::rayPickS);
1574 SoRayPickAction::addMethod(SoSeparator::getClassTypeId(), SoNode::rayPickS);
1575 SoRayPickAction::addMethod(SoLOD::getClassTypeId(), SoNode::rayPickS);
1576 SoRayPickAction::addMethod(SoLevelOfDetail::getClassTypeId(), SoNode::rayPickS);
1577 SoRayPickAction::addMethod(SoShape::getClassTypeId(), SoNode::rayPickS);
1578 SoRayPickAction::addMethod(SoTexture2::getClassTypeId(), SoNode::rayPickS);
1579 SoRayPickAction::addMethod(SoBumpMap::getClassTypeId(), SoNode::rayPickS);
1580 SoRayPickAction::addMethod(SoImage::getClassTypeId(), SoNode::rayPickS);
1581 SoRayPickAction::addMethod(SoSceneTexture2::getClassTypeId(), SoNode::rayPickS);
1582 SoRayPickAction::addMethod(SoSceneTextureCubeMap::getClassTypeId(), SoNode::rayPickS);
1583 SoRayPickAction::addMethod(SoTextureCubeMap::getClassTypeId(), SoNode::rayPickS);
1584
1585 SoSearchAction::addMethod(SoNode::getClassTypeId(), SoNode::searchS);
1586 SoWriteAction::addMethod(SoNode::getClassTypeId(), SoNode::writeS);
1587
1588 SoAudioRenderAction::addMethod(SoNode::getClassTypeId(),
1589 SoAction::nullAction);
1590 SoAudioRenderAction::addMethod(SoListener::getClassTypeId(),
1591 SoNode::audioRenderS);
1592 SoAudioRenderAction::addMethod(SoCamera::getClassTypeId(),
1593 SoNode::audioRenderS);
1594 SoAudioRenderAction::addMethod(SoGroup::getClassTypeId(),
1595 SoNode::audioRenderS);
1596 SoAudioRenderAction::addMethod(SoWWWInline::getClassTypeId(),
1597 SoNode::audioRenderS);
1598 SoAudioRenderAction::addMethod(SoFile::getClassTypeId(),
1599 SoNode::audioRenderS);
1600 // just call doAction() for all transformation nodes. This will make
1601 // sound nodes work even for extension nodes that implements the
1602 // doAction() method
1603 SoAudioRenderAction::addMethod(SoTransformation::getClassTypeId(),
1604 SoAudioRenderAction::callDoAction);
1605 }
1606
1607 #undef SET_UNIQUE_NODE_ID
1608