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   \page elements The Element Classes
35 
36   Elements are mostly internal to Coin, unless you create new extension
37   nodes over Coin. Then you will probably need to know about them.
38 
39   Elements are part of the design for scenegraph traversal in Coin.
40 
41   It works like this: any traversal action instantiates and keeps a
42   single SoState instance during traversal. The SoState instance uses
43   SoElement objects as "memory units" to keep track of the current
44   state for any feature of the scenegraph nodes.
45 
46   As an example, consider the SoPointSize node: when the SoPointSize
47   node is traversed by for instance a SoGLRenderAction, it will itself
48   push a SoPointSizeElement onto the SoGLRenderAction's SoState stack.
49   Later, when a SoPointSet node occurs in the scenegraph, it will
50   request the current pointsize value from the SoState by reading off
51   the value of it's SoPointSizeElement.
52 
53   SoSeparator nodes will push and pop elements on and off the state
54   stack, so anything that changes state below a SoSeparator node will
55   not influence anything \e above the SoSeparator.
56 
57 
58   For more information on the theoretical underpinnings of this
59   traversal design, you should consider reading available literature
60   on the so-called "Visitor pattern". We recommend "Design Patterns",
61   by Gamma, Helm, Johnson, Vlissides (aka the "Gang Of Four"). This
62   book actually uses the Inventor API traversal mechanism as the case
63   study for explaining the Visitor pattern.
64 
65   \TOOLMAKER_REF
66 
67   The following is a complete example on how to extend Coin with your
68   own traversal elements. First, the class declaration of the new
69   element (ie the header include file):
70 
71   \code
72   // [texturefilenameelement.h]
73   #ifndef TEXTUREFILENAMEELEMENT_H
74   #define TEXTUREFILENAMEELEMENT_H
75 
76   #include <Inventor/elements/SoReplacedElement.h>
77   #include <Inventor/SbString.h>
78 
79   class TextureFilenameElement : public SoReplacedElement {
80     typedef SoReplacedElement inherited;
81 
82     SO_ELEMENT_HEADER(TextureFilenameElement);
83   public:
84     static void initClass(void);
85 
86     virtual void init(SoState * state);
87     static void set(SoState * const state, SoNode * const node,
88                     const SbString & filename);
89     static const SbString & get(SoState * const state);
90     static const TextureFilenameElement * getInstance(SoState * state);
91 
92   protected:
93     virtual ~TextureFilenameElement();
94     virtual void setElt(const SbString & filename);
95 
96   private:
97     SbString filename;
98   };
99 
100   #endif // !TEXTUREFILENAMEELEMENT_H
101   \endcode
102 
103   The implementation of the element:
104 
105   \code
106   // [texturefilenameelement.cpp]
107   //
108   // The purpose of the code in this file is to demonstrate how you can
109   // make your own elements for scene graph traversals.
110   //
111   // Code by Peder Blekken <pederb@sim.no>. Copyright (C)
112   // Kongsberg Oil & Gas Technologies.
113 
114   #include "texturefilenameelement.h"
115 
116 
117   SO_ELEMENT_SOURCE(TextureFilenameElement);
118 
119 
120   void
121   TextureFilenameElement::initClass(void)
122   {
123     SO_ELEMENT_INIT_CLASS(TextureFilenameElement, inherited);
124   }
125 
126   void
127   TextureFilenameElement::init(SoState * state)
128   {
129     this->filename = "<none>";
130   }
131 
132   TextureFilenameElement::~TextureFilenameElement()
133   {
134   }
135 
136   void
137   TextureFilenameElement::set(SoState * const state, SoNode * const node,
138                               const SbString & filename)
139   {
140     TextureFilenameElement * elem = (TextureFilenameElement *)
141       SoReplacedElement::getElement(state, classStackIndex, node);
142     elem->setElt(filename);
143   }
144 
145   const SbString &
146   TextureFilenameElement::get(SoState * const state)
147   {
148     return TextureFilenameElement::getInstance(state)->filename;
149   }
150 
151   void
152   TextureFilenameElement::setElt(const SbString & filename)
153   {
154     this->filename = filename;
155   }
156 
157   const TextureFilenameElement *
158   TextureFilenameElement::getInstance(SoState * state)
159   {
160     return (const TextureFilenameElement *)
161       SoElement::getConstElement(state, classStackIndex);
162   }
163   \endcode
164 
165   And a small, stand-alone test application putting the new element to
166   use:
167 
168   \code
169   // [lstextures.cpp]
170   //
171   // The purpose of this file is to make a small wrapper "tool" around
172   // the TextureFilenameElement extension element, just for showing
173   // example code on how to make use of a user-defined custom element.
174   //
175   // The code goes like this:
176   //
177   // We initialize the element, enable it for the SoCallbackAction, read
178   // a scene graph file, set callbacks on SoTexture2 and all shape nodes
179   // and applies the SoCallbackAction. The callbacks will then print out
180   // the texture filename information from the TextureFilenameElement
181   // each time an interesting node is hit.
182   //
183   //
184   // Code by Peder Blekken <pederb@sim.no>. Cleaned up, integrated in
185   // Coin distribution and commented by Morten Eriksen
186   // <mortene@sim.no>. Copyright (C) Kongsberg Oil & Gas Technologies.
187 
188   #include <Inventor/SoDB.h>
189   #include <Inventor/SoInput.h>
190   #include <Inventor/actions/SoCallbackAction.h>
191   #include <Inventor/nodes/SoSeparator.h>
192   #include <Inventor/nodes/SoTexture2.h>
193   #include <Inventor/nodes/SoShape.h>
194   #include <Inventor/misc/SoState.h>
195   #include <cstdio>
196 
197   #include "texturefilenameelement.h"
198 
199 
200   SoCallbackAction::Response
201   pre_tex2_cb(void * data, SoCallbackAction * action, const SoNode * node)
202   {
203     const SbString & filename = ((SoTexture2 *)node)->filename.getValue();
204     TextureFilenameElement::set(action->getState(), (SoNode *)node, filename);
205 
206     (void)fprintf(stdout, "=> New texture: %s\n",
207                   filename.getLength() == 0 ?
208                   "<inlined>" : filename.getString());
209 
210     return SoCallbackAction::CONTINUE;
211   }
212 
213   SoCallbackAction::Response
214   pre_shape_cb(void * data, SoCallbackAction * action, const SoNode * node)
215   {
216     const SbString & filename =
217       TextureFilenameElement::get(action->getState());
218 
219     (void)fprintf(stdout, "   Texturemap on %s: %s\n",
220                   node->getTypeId().getName().getString(),
221                   filename.getLength() == 0 ?
222                   "<inlined>" : filename.getString());
223 
224     return SoCallbackAction::CONTINUE;
225   }
226 
227   void
228   usage(const char * appname)
229   {
230     (void)fprintf(stderr, "\n\tUsage: %s <modelfile.iv>\n\n", appname);
231     (void)fprintf(stderr,
232                   "\tLists all texture filenames in the model file,\n"
233                   "\tand on which shape nodes they are used.\n\n"
234                   "\tThe purpose of this example utility is simply to\n"
235                   "\tshow how to create and use an extension element for\n"
236                   "\tscene graph traversal.\n\n");
237   }
238 
239   int
240   main(int argc, char ** argv)
241   {
242     if (argc != 2) {
243       usage(argv[0]);
244       exit(1);
245     }
246 
247     SoDB::init();
248 
249     TextureFilenameElement::initClass();
250     SO_ENABLE(SoCallbackAction, TextureFilenameElement);
251 
252     SoInput input;
253     if (!input.openFile(argv[1])) {
254       (void)fprintf(stderr, "ERROR: couldn't open file ``%s''.\n", argv[1]);
255       exit(1);
256     }
257 
258     SoSeparator * root = SoDB::readAll(&input);
259     if (root) {
260       root->ref();
261       SoCallbackAction cbaction;
262       cbaction.addPreCallback(SoTexture2::getClassTypeId(), pre_tex2_cb, NULL);
263       cbaction.addPreCallback(SoShape::getClassTypeId(), pre_shape_cb, NULL);
264       cbaction.apply(root);
265       root->unref();
266       return 0;
267     }
268     return 1;
269   }
270   \endcode
271 
272   \ingroup elements
273 */
274 
275 /*!
276   \class SoElement Inventor/elements/SoElement.h
277   \brief SoElement is the abstract base class for all elements.
278 
279   This is the base class for all the element classes in Coin.
280 
281   \ingroup elements
282 */
283 
284 // *************************************************************************
285 
286 #include <Inventor/elements/SoElement.h>
287 
288 #include <cstdlib>
289 #include <cassert>
290 
291 #include <Inventor/elements/SoElements.h>
292 #include <Inventor/elements/SoTextureUnitElement.h>
293 #include <Inventor/elements/SoGLMultiTextureCoordinateElement.h>
294 #include <Inventor/elements/SoGLMultiTextureImageElement.h>
295 #include <Inventor/elements/SoGLMultiTextureEnabledElement.h>
296 #include <Inventor/elements/SoGLMultiTextureMatrixElement.h>
297 #include <Inventor/elements/SoBumpMapElement.h>
298 #include <Inventor/elements/SoBumpMapCoordinateElement.h>
299 #include <Inventor/elements/SoBumpMapMatrixElement.h>
300 #include <Inventor/elements/SoTextureCombineElement.h>
301 #include <Inventor/elements/SoCacheHintElement.h>
302 
303 #include <Inventor/elements/SoCullElement.h> // internal element
304 #include <Inventor/elements/SoGLLazyElement.h> // internal element
305 #include <Inventor/misc/SoState.h>
306 #include <Inventor/lists/SoTypeList.h>
307 
308 #include "elements/SoTextureScalePolicyElement.h" // internal element
309 #include "elements/SoTextureScaleQualityElement.h" // internal  element
310 #include "tidbitsp.h"
311 #include "coindefs.h"
312 
313 // *************************************************************************
314 
315 /*!
316   \fn SoElement * SoElement::getElement(SoState * const state, const int stackIndex)
317 
318   This method returns the top instance (in the \a state stack) of the
319   element class with stack index \a stackIndex.
320 
321   The retuned instance is writable.  To make this instance, some lazy
322   evaluation may have to be perfomed, so use getConstElement() instead
323   if the instance shouldn't be modified.
324 
325   If no instance is available and can not be made, \c NULL is
326   returned.
327 
328   \sa const SoElement * SoElement::getConstElement(SoState * const state, const int stackIndex)
329 */
330 
331 /*!
332   \var SoType SoElement::typeId
333   The element's unique SoType type identification.
334 */
335 
336 /*!
337   \var int SoElement::stackIndex
338   The index in the state stack for this particular element instance.
339 */
340 
341 /*!
342   \var int SoElement::depth
343   The depth of the element instance in the state stack.
344 */
345 
346 /*!
347   \fn SoType SoElement::getClassTypeId(void)
348   This static method returns the class type.
349 */
350 /*!
351   \var SoElement::classStackIndex
352   This is the static state stack index for the class.
353 */
354 /*!
355   \fn int SoElement::getClassStackIndex(void)
356   This static method returns the state stack index for the class.
357 */
358 
359 
360 // *************************************************************************
361 
362 /*! Provides mapping from state stack indices to element types. */
363 SoTypeList * SoElement::stackToType;
364 
365 int SoElement::classStackIndex;
366 SoType SoElement::classTypeId STATIC_SOTYPE_INIT;
367 
getClassTypeId(void)368 SoType SoElement::getClassTypeId(void) { return SoElement::classTypeId; }
getClassStackIndex(void)369 int SoElement::getClassStackIndex(void) { return SoElement::classStackIndex; }
370 
371 // *************************************************************************
372 
373 /*!
374   This function initializes all the built-in Coin element classes.
375 */
376 void
initElements(void)377 SoElement::initElements(void)
378 {
379   SoAccumulatedElement::initClass();
380   SoClipPlaneElement::initClass();
381   SoGLClipPlaneElement::initClass();
382   SoLightElement::initClass();
383   SoModelMatrixElement::initClass();
384   SoBBoxModelMatrixElement::initClass();
385   SoGLModelMatrixElement::initClass();
386   SoProfileElement::initClass();
387   SoCacheElement::initClass();
388   SoInt32Element::initClass();
389   SoAnnoText3CharOrientElement::initClass();
390   SoAnnoText3FontSizeHintElement::initClass();
391   SoAnnoText3RenderPrintElement::initClass();
392   SoComplexityTypeElement::initClass();
393   SoDecimationTypeElement::initClass();
394   SoDrawStyleElement::initClass();
395   SoGLDrawStyleElement::initClass();
396   SoGLLightIdElement::initClass();
397   SoLinePatternElement::initClass();
398   SoGLLinePatternElement::initClass();
399   SoMaterialBindingElement::initClass();
400   SoNormalBindingElement::initClass();
401   SoPickStyleElement::initClass();
402   SoSwitchElement::initClass();
403   SoTextOutlineEnabledElement::initClass();
404   SoTextureCoordinateBindingElement::initClass();
405   SoUnitsElement::initClass();
406   SoFloatElement::initClass();
407   SoComplexityElement::initClass();
408   SoCreaseAngleElement::initClass();
409   SoDecimationPercentageElement::initClass();
410   SoFocalDistanceElement::initClass();
411   SoFontSizeElement::initClass();
412   SoLineWidthElement::initClass();
413   SoGLLineWidthElement::initClass();
414   SoPointSizeElement::initClass();
415   SoGLPointSizeElement::initClass();
416   SoTextureQualityElement::initClass();
417   SoGLRenderPassElement::initClass();
418   SoGLUpdateAreaElement::initClass();
419   SoLocalBBoxMatrixElement::initClass();
420   SoOverrideElement::initClass();
421   SoTextureOverrideElement::initClass();
422   SoPickRayElement::initClass();
423   SoReplacedElement::initClass();
424   SoCoordinateElement::initClass();
425   SoGLCoordinateElement::initClass();
426   SoGLColorIndexElement::initClass();
427   SoEnvironmentElement::initClass();
428   SoGLEnvironmentElement::initClass();
429   SoFontNameElement::initClass();
430   SoLightAttenuationElement::initClass();
431   SoNormalElement::initClass();
432   SoGLNormalElement::initClass();
433   SoPolygonOffsetElement::initClass();
434   SoGLPolygonOffsetElement::initClass();
435   SoProjectionMatrixElement::initClass();
436   SoGLProjectionMatrixElement::initClass();
437   SoProfileCoordinateElement::initClass();
438   SoViewingMatrixElement::initClass();
439   SoGLViewingMatrixElement::initClass();
440   SoViewVolumeElement::initClass();
441   SoShapeHintsElement::initClass();
442   SoGLShapeHintsElement::initClass();
443   SoShapeStyleElement::initClass();
444   SoViewportRegionElement::initClass();
445   SoGLViewportRegionElement::initClass();
446   SoWindowElement::initClass();
447 
448   SoTransparencyElement::initClass();
449   SoAmbientColorElement::initClass();
450   SoDiffuseColorElement::initClass();
451   SoEmissiveColorElement::initClass();
452   SoLightModelElement::initClass();
453   SoShininessElement::initClass();
454   SoSpecularColorElement::initClass();
455 
456   SoLazyElement::initClass();
457   SoGLLazyElement::initClass();
458   SoCullElement::initClass();
459   SoGLCacheContextElement::initClass();
460 
461   SoTextureScalePolicyElement::initClass();
462   SoTextureScaleQualityElement::initClass();
463 
464   SoListenerPositionElement::initClass();
465   SoListenerOrientationElement::initClass();
466   SoListenerDopplerElement::initClass();
467   SoListenerGainElement::initClass();
468 
469   SoSoundElement::initClass();
470 
471   SoTextureUnitElement::initClass();
472 
473   SoMultiTextureCoordinateElement::initClass();
474   SoMultiTextureImageElement::initClass();
475   SoMultiTextureEnabledElement::initClass();
476   SoMultiTextureMatrixElement::initClass();
477   SoGLMultiTextureCoordinateElement::initClass();
478   SoGLMultiTextureImageElement::initClass();
479   SoGLMultiTextureEnabledElement::initClass();
480   SoGLMultiTextureMatrixElement::initClass();
481 
482   SoBumpMapElement::initClass();
483   SoBumpMapCoordinateElement::initClass();
484   SoBumpMapMatrixElement::initClass();
485 
486   SoTextureCombineElement::initClass();
487   SoCacheHintElement::initClass();
488 
489   SoGLVBOElement::initClass();
490 
491   SoDepthBufferElement::initClass();
492   SoGLDepthBufferElement::initClass();
493 
494   SoVertexAttributeElement::initClass();
495   SoGLVertexAttributeElement::initClass();
496   SoVertexAttributeBindingElement::initClass();
497 }
498 
499 // Note: the following documentation for initClass() will also be
500 // visible for subclasses, so keep it general.
501 /*!
502   Initialize relevant common data for all instances, like the type
503   system.
504  */
505 void
initClass(void)506 SoElement::initClass(void)
507 {
508   SoElement::stackToType = new SoTypeList;
509 
510   // Make sure we only initialize once.
511   assert(SoElement::classTypeId == SoType::badType());
512   SoElement::classTypeId =
513     SoType::createType(SoType::badType(), "Element", NULL);
514 
515   SoElement::classStackIndex = -1;
516   SoElement::initElements();
517 
518   coin_atexit(reinterpret_cast<coin_atexit_f *>(SoElement::cleanup), CC_ATEXIT_NORMAL);
519 }
520 
521 // atexit callback
522 void
cleanup(void)523 SoElement::cleanup(void)
524 {
525   delete SoElement::stackToType;
526   SoElement::classTypeId STATIC_SOTYPE_INIT;
527 }
528 
529 /*!
530   The constructor.  To create element instances, use SoType::createInstance()
531   for the elements type identifier..
532 */
SoElement(void)533 SoElement::SoElement(void)
534   : nextup(NULL),
535     nextdown(NULL)
536 {
537 }
538 
539 /*!
540   The destructor.
541 */
~SoElement()542 SoElement::~SoElement()
543 {
544 }
545 
546 /*!
547   This function initializes the element type in the given SoState.  It
548   is called for the first element of each enabled element type in
549   SoState objects.
550 */
551 void
init(SoState * COIN_UNUSED_ARG (state))552 SoElement::init(SoState * COIN_UNUSED_ARG(state))
553 {
554   // virtual method
555 }
556 
557 /*!
558   This method is called every time a new element is required in one of
559   the stacks. This happens when a writable element is requested, using
560   SoState::getElement() or indirectly SoElement::getElement(), and the
561   depth of the current element is less than the state depth.
562 
563   Override this method if your element needs to copy data from the
564   previous top of stack. The push() method is called on the new
565   element, and the previous element can be found using
566   SoElement::getNextInStack().
567 */
568 void
push(SoState * COIN_UNUSED_ARG (state))569 SoElement::push(SoState * COIN_UNUSED_ARG(state))
570 {
571   // virtual method
572 }
573 
574 /*!
575   This method is callled when the state is popped, and the depth of
576   the element is bigger than the current state depth. pop() is called
577   on the new top of stack, and a pointer to the previous top of stack
578   is passed in \a prevTopElement.
579 
580   Override this method if you need to copy some state information from
581   the previous top of stack.
582 */
583 void
pop(SoState * COIN_UNUSED_ARG (state),const SoElement * COIN_UNUSED_ARG (prevTopElement))584 SoElement::pop(SoState * COIN_UNUSED_ARG(state), const SoElement * COIN_UNUSED_ARG(prevTopElement))
585 {
586   // virtual method
587 }
588 
589 /*!
590   This function is for printing element information, and is used
591   mostly for debugging purposes.
592 */
593 void
print(FILE * file) const594 SoElement::print(FILE * file) const
595 {
596   (void)fprintf(file, "%s[%p]\n",
597                 this->getTypeId().getName().getString(), this);
598 }
599 
600 /*!
601   This function returns \c TRUE is the element matches another element
602   (of the same class), with respect to cache validity.
603 
604   If the application programmer's extension element has a matches()
605   function, it should also have a copyMatchInfo() function.
606 */
607 SbBool
matches(const SoElement * COIN_UNUSED_ARG (element)) const608 SoElement::matches(const SoElement * COIN_UNUSED_ARG(element)) const
609 {
610   return FALSE;
611 }
612 
613 /*!
614   \fn virtual SoElement * SoElement::copyMatchInfo(void) const = 0
615 
616   This function creates a copy of the element that contains enough
617   information to enable the matches() function to work.
618 
619   Used to help with scenegraph traversal caching operations.
620 */
621 
622 /*!
623   Returns the number of allocated element stack index slots.
624 */
625 int
getNumStackIndices(void)626 SoElement::getNumStackIndices(void)
627 {
628   return SoElement::stackToType->getLength();
629 }
630 
631 /*!
632   Returns the SoType identifier for the element class with element
633   state stack index \a stackIndex.
634 */
635 SoType
getIdFromStackIndex(const int stackIndex)636 SoElement::getIdFromStackIndex(const int stackIndex)
637 {
638   assert(SoElement::stackToType->getLength() > stackIndex);
639   return (*SoElement::stackToType)[stackIndex];
640 }
641 
642 /*!
643   Sets the depth value of the element instance in the state stack.
644 */
645 void
setDepth(const int depth)646 SoElement::setDepth(const int depth)
647 {
648   this->depth = depth;
649 }
650 
651 /*!
652   Returns the state stack depth value of the element instance.
653 */
654 int
getDepth() const655 SoElement::getDepth() const
656 {
657   return this->depth;
658 }
659 
660 /*!
661   \fn void SoElement::capture(SoState * const state) const;
662 
663   This function does whatever is necessary in the state for caching
664   purposes.  If should be called by subclasses of SoElement whenever
665   any value in the element is accessed.
666 */
667 
668 /*!
669   \fn void const SoElement * SoElement::getConstElement(SoState * const state, const int stackIndex);
670 
671   This method returns a reference to the top element of the class with
672   stack index \a stackIndex. The returned element is non-mutable.
673 
674   (Don't try to be clever and cast away the constness -- if the
675   returned instance is modified, strange, hard to find and generally
676   wonderful bugs will most likely start to happen.)
677 
678   If no instance can be returned, \c NULL is returned.
679 
680   \sa SoElement * SoElement::getElement(SoState * const state, const int stackIndex)
681 */
682 
683 /*!
684   Adds the element to the cache.
685 */
686 void
captureThis(SoState * state) const687 SoElement::captureThis(SoState * state) const
688 {
689   SoCacheElement::addElement(state, this);
690 }
691 
692 /*!
693   Sets the type identifier of an instance.
694 
695   Note that this is fundamentally different from the SoNode run-time
696   type system.
697 */
698 void
setTypeId(const SoType typeId)699 SoElement::setTypeId(const SoType typeId)
700 {
701   this->typeId = typeId;
702 }
703 
704 /*!
705   Returns the type identification of an object derived from a class
706   inheriting SoElement.  This is used for run-time type checking and
707   "downward" casting.
708 
709   For a more thorough explanation of the run-time type identification
710   functionality, see the documentation of SoBase::getTypeId().
711 */
712 const SoType
getTypeId(void) const713 SoElement::getTypeId(void) const
714 {
715   return this->typeId;
716 }
717 
718 /*!
719   Returns the stack index for an element instance.
720 */
721 int
getStackIndex(void) const722 SoElement::getStackIndex(void) const
723 {
724   return this->stackIndex;
725 }
726 
727 /*!
728   Sets the stack index in an instance.  Used in constructors of
729   derived elements.
730 */
731 void
setStackIndex(const int stackIndex)732 SoElement::setStackIndex(const int stackIndex)
733 {
734   this->stackIndex = stackIndex;
735 }
736 
737 /*!
738   Returns the value of a new available stack index.
739 */
740 int
createStackIndex(const SoType typeId)741 SoElement::createStackIndex(const SoType typeId)
742 {
743   if (typeId.canCreateInstance()) {
744     SoElement::stackToType->append(typeId);
745     return SoElement::stackToType->getLength() - 1;
746   }
747   return -1;
748 }
749 
750 /*!
751   Returns the next element down in the stack. Should be used in push()
752   to get the previous element.
753 
754   This method has a slightly misleading name, but we didn't change it
755   to stay compatible with the original SGI Inventor API.
756 */
757 SoElement *
getNextInStack(void) const758 SoElement::getNextInStack(void) const
759 {
760   return this->nextdown;
761 }
762 
763 /*!
764   Returns the next free element, ie the next element up in the stack.
765 */
766 SoElement *
getNextFree(void) const767 SoElement::getNextFree(void) const
768 {
769   return this->nextup;
770 }
771