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