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