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 SoCallbackAction SoCallbackAction.h Inventor/actions/SoCallbackAction.h
35 \brief The SoCallbackAction class invokes callbacks at specific nodes.
36
37 \ingroup actions
38
39 This action has mechanisms for tracking traversal position and
40 traversal state. In combination with the ability to pass geometry
41 primitives to callback actions set by the user, this does for
42 instance make it rather straightforward to extract the geometry of a
43 scene graph.
44
45 You should be able to use this action for most of your "simple"
46 traversal needs, instead of cooking up your own code, as the
47 SoCallbackAction is rather flexible.
48
49 A common use of this action is to extract geometry of non-primitive
50 shapes as triangles. A full-fledged example that demonstrates this
51 on a scenegraph with two spheres follows:
52
53 \code
54 #include <Inventor/SoDB.h>
55 #include <Inventor/SoPrimitiveVertex.h>
56 #include <Inventor/actions/SoCallbackAction.h>
57 #include <Inventor/nodes/SoCoordinate3.h>
58 #include <Inventor/nodes/SoIndexedFaceSet.h>
59 #include <Inventor/nodes/SoSeparator.h>
60 #include <Inventor/nodes/SoShape.h>
61 #include <Inventor/nodes/SoSphere.h>
62 #include <Inventor/nodes/SoTranslation.h>
63
64
65 static SoCoordinate3 * coord3 = NULL;
66 static SoIndexedFaceSet * ifs = NULL;
67
68 static int coord3idx = 0;
69
70
71 static void
72 triangle_cb(void * userdata, SoCallbackAction * action,
73 const SoPrimitiveVertex * v1,
74 const SoPrimitiveVertex * v2,
75 const SoPrimitiveVertex * v3)
76 {
77 const SbVec3f vtx[] = { v1->getPoint(), v2->getPoint(), v3->getPoint() };
78 const SbMatrix mm = action->getModelMatrix();
79
80 SbVec3f vx[3];
81 for (int j=0; j < 3; j++) { mm.multVecMatrix(vtx[j], vx[j]); }
82
83 // (This is sub-optimal -- should scan for the same vertex
84 // coordinates already being present in the SoCoordinate3
85 // node. We'll get lots of duplicate coordinates from this.)
86 coord3->point.setNum(coord3->point.getNum() + 3);
87 coord3->point.setValues(coord3idx, 3, vx);
88
89 int32_t indices[] = { coord3idx, coord3idx + 1, coord3idx + 2, -1 };
90 coord3idx += 3;
91
92 int oldsize = ifs->coordIndex.getNum();
93 ifs->coordIndex.setNum(oldsize + 4);
94 ifs->coordIndex.setValues(oldsize, 4, indices);
95
96 // (Note that it would likely be desirable to grab normal vectors,
97 // materials and / or texture coordinates in a real-world
98 // application. How to do this is not shown by the above code,
99 // but it is not much different from the extraction of vertex
100 // coordinates.)
101 }
102
103
104 int
105 main(void)
106 {
107 SoDB::init();
108
109 SoSeparator * root = new SoSeparator;
110 root->addChild(new SoSphere);
111 SoTranslation * trans = new SoTranslation;
112 trans->translation.setValue(10, 0, 0);
113 root->addChild(trans);
114 SoSphere * ss = new SoSphere;
115 ss->radius = 3;
116 root->addChild(ss);
117
118 root->ref();
119
120 coord3 = new SoCoordinate3;
121 coord3->point.setNum(0);
122 ifs = new SoIndexedFaceSet;
123 ifs->coordIndex.setNum(0);
124
125 SoCallbackAction ca;
126 ca.addTriangleCallback(SoShape::getClassTypeId(), triangle_cb, NULL);
127 ca.apply(root);
128
129 root->unref();
130
131 // [the generated SoCoordinate3 and SoIndexedFaceSet nodes would now
132 // typically be used in a scenegraph in a viewer, or written to disk
133 // or something]
134
135 return 0;
136 }
137 \endcode
138 */
139
140 /*!
141 \typedef void SoTriangleCB(void *userdata, SoCallbackAction *action, const SoPrimitiveVertex *v1, const SoPrimitiveVertex *v2, const SoPrimitiveVertex *v3)
142
143 \param userdata is a void pointer to any data the application need to
144 know of in the callback function (like for instance a \e this
145 pointer).
146 \param action the action which invoked the callback
147 \param v1 first vertex of the triangle
148 \param v2 second vertex of the triangle
149 \param v3 third vertex of the triangle
150
151 \sa SoLineSegmentCB, SoPointCB
152 */
153
154 /*!
155 \typedef void SoLineSegmentCB(void *userdata, SoCallbackAction *action, const SoPrimitiveVertex *v1, const SoPrimitiveVertex *v2)
156
157 \param userdata is a void pointer to any data the application need to
158 know of in the callback function (like for instance a \e this
159 pointer).
160 \param action the action which invoked the callback
161 \param v1 first vertex of the line
162 \param v2 second vertex of the line
163
164 \sa setPassCallback() SoPointCB
165 */
166
167 /*!
168 \typedef void SoPointCB(void *userdata, SoCallbackAction *action, const SoPrimitiveVertex *v)
169
170 \param userdata is a void pointer to any data the application need to
171 know of in the callback function (like for instance a \e this
172 pointer).
173 \param action the action which invoked the callback
174 \param v the vertex of the point
175
176 \sa setPassCallback()
177 */
178
179
180 /*! \file SoCallbackAction.h */
181 #include <Inventor/actions/SoCallbackAction.h>
182
183 #include <Inventor/SoPath.h>
184 #include <Inventor/elements/SoComplexityElement.h>
185 #include <Inventor/elements/SoCoordinateElement.h>
186 #include <Inventor/elements/SoCreaseAngleElement.h>
187 #include <Inventor/elements/SoDecimationPercentageElement.h>
188 #include <Inventor/elements/SoFocalDistanceElement.h>
189 #include <Inventor/elements/SoFontNameElement.h>
190 #include <Inventor/elements/SoFontSizeElement.h>
191 #include <Inventor/elements/SoLazyElement.h>
192 #include <Inventor/elements/SoLightAttenuationElement.h>
193 #include <Inventor/elements/SoLinePatternElement.h>
194 #include <Inventor/elements/SoLineWidthElement.h>
195 #include <Inventor/elements/SoMaterialBindingElement.h>
196 #include <Inventor/elements/SoModelMatrixElement.h>
197 #include <Inventor/elements/SoNormalBindingElement.h>
198 #include <Inventor/elements/SoNormalElement.h>
199 #include <Inventor/elements/SoOverrideElement.h>
200 #include <Inventor/elements/SoPickStyleElement.h>
201 #include <Inventor/elements/SoPointSizeElement.h>
202 #include <Inventor/elements/SoProfileCoordinateElement.h>
203 #include <Inventor/elements/SoProfileElement.h>
204 #include <Inventor/elements/SoProjectionMatrixElement.h>
205 #include <Inventor/elements/SoShapeHintsElement.h>
206 #include <Inventor/elements/SoSwitchElement.h>
207 #include <Inventor/elements/SoMultiTextureCoordinateElement.h>
208 #include <Inventor/elements/SoMultiTextureMatrixElement.h>
209 #include <Inventor/elements/SoTextureOverrideElement.h>
210 #include <Inventor/elements/SoUnitsElement.h>
211 #include <Inventor/elements/SoViewVolumeElement.h>
212 #include <Inventor/elements/SoViewingMatrixElement.h>
213 #include <Inventor/elements/SoViewportRegionElement.h>
214 #include <Inventor/elements/SoCacheElement.h>
215 #include <Inventor/elements/SoViewportRegionElement.h>
216 #include <Inventor/elements/SoCullElement.h>
217 #include <Inventor/lists/SoEnabledElementsList.h>
218 #include <Inventor/misc/SoState.h>
219 #include <Inventor/nodes/SoShape.h>
220 #include <Inventor/SbViewportRegion.h>
221
222 #include "actions/SoSubActionP.h"
223 #include "SbBasicP.h"
224
225 #ifndef DOXYGEN_SKIP_THIS
226
227 class SoCallbackData { //internal class
228 public:
SoCallbackData(void * cbfunc=NULL,void * userdata=NULL)229 SoCallbackData(void * cbfunc = NULL, void * userdata = NULL)
230 : func(cbfunc), data(userdata), next(NULL) {}
231
232
append(SoCallbackData * newdata)233 void append(SoCallbackData * newdata) {
234 SoCallbackData * cbdata = this;
235 while (cbdata->next != NULL) cbdata = cbdata->next;
236 cbdata->next = newdata;
237 }
238
deleteAll(void)239 void deleteAll(void) {
240 SoCallbackData * cbdata = this;
241 SoCallbackData * nextptr;
242 while (cbdata) {
243 nextptr = cbdata->next;
244 delete cbdata;
245 cbdata = nextptr;
246 }
247 }
248
249 SoCallbackAction::Response doNodeCallbacks(SoCallbackAction * action,
250 const SoNode * node);
251 void doTriangleCallbacks(SoCallbackAction * action,
252 const SoPrimitiveVertex * const v1,
253 const SoPrimitiveVertex * const v2,
254 const SoPrimitiveVertex * const v3);
255
256 void doLineSegmentCallbacks(SoCallbackAction * action,
257 const SoPrimitiveVertex * const v1,
258 const SoPrimitiveVertex * const v2);
259 void doPointCallbacks(SoCallbackAction * action,
260 const SoPrimitiveVertex * v);
261
262 public:
263 void * func;
264 void * data;
265 SoCallbackData * next;
266 };
267
268
269 SoCallbackAction::Response
doNodeCallbacks(SoCallbackAction * action,const SoNode * node)270 SoCallbackData::doNodeCallbacks(SoCallbackAction * action,
271 const SoNode * node)
272 {
273 SoCallbackData * cbdata = this;
274 SoCallbackAction::Response response = SoCallbackAction::CONTINUE;
275 while (cbdata) {
276 assert(cbdata->func != NULL);
277 SoCallbackAction::SoCallbackActionCB * cbfunc =
278 object_to_function_cast<SoCallbackAction::SoCallbackActionCB *>( cbdata->func);
279 SoCallbackAction::Response ret = cbfunc(cbdata->data, action, node);
280 if (ret == SoCallbackAction::ABORT) return SoCallbackAction::ABORT;
281 if (ret == SoCallbackAction::PRUNE) response = ret;
282 cbdata = cbdata->next;
283 }
284 return response;
285 }
286
287 void
doTriangleCallbacks(SoCallbackAction * action,const SoPrimitiveVertex * const v1,const SoPrimitiveVertex * const v2,const SoPrimitiveVertex * const v3)288 SoCallbackData::doTriangleCallbacks(SoCallbackAction * action,
289 const SoPrimitiveVertex * const v1,
290 const SoPrimitiveVertex * const v2,
291 const SoPrimitiveVertex * const v3)
292 {
293 SoCallbackData * cbdata = this;
294 while (cbdata) {
295 assert(cbdata->func != NULL);
296 SoTriangleCB * tricb = object_to_function_cast<SoTriangleCB *> (cbdata->func);
297 tricb(cbdata->data, action, v1, v2, v3);
298 cbdata = cbdata->next;
299 }
300 }
301
302 void
doLineSegmentCallbacks(SoCallbackAction * action,const SoPrimitiveVertex * const v1,const SoPrimitiveVertex * const v2)303 SoCallbackData::doLineSegmentCallbacks(SoCallbackAction * action,
304 const SoPrimitiveVertex * const v1,
305 const SoPrimitiveVertex * const v2)
306 {
307 SoCallbackData * cbdata = this;
308 while (cbdata) {
309 assert(cbdata->func != NULL);
310 SoLineSegmentCB * linecb = object_to_function_cast<SoLineSegmentCB *>( cbdata->func);
311 linecb(cbdata->data, action, v1, v2);
312 cbdata = cbdata->next;
313 }
314 }
315
316 void
doPointCallbacks(SoCallbackAction * action,const SoPrimitiveVertex * v)317 SoCallbackData::doPointCallbacks(SoCallbackAction * action,
318 const SoPrimitiveVertex * v)
319 {
320 SoCallbackData * cbdata = this;
321 while (cbdata) {
322 assert(cbdata->func != NULL);
323 SoPointCB * ptcb = object_to_function_cast<SoPointCB *>( cbdata->func);
324 ptcb(cbdata->data, action, v);
325 cbdata = cbdata->next;
326 }
327 }
328
329 // class to hold private, hidden data
330 class SoCallbackActionP {
331 public:
332 SbBool viewportset;
333 SbViewportRegion viewport;
334 SoCallbackAction::Response response;
335 SoNode * currentnode;
336
337 SbList <SoCallbackData *> precallback;
338 SbList <SoCallbackData *> postcallback;
339
340 SoCallbackData * pretailcallback;
341 SoCallbackData * posttailcallback;
342
343 SbList <SoCallbackData *> trianglecallback;
344 SbList <SoCallbackData *> linecallback;
345 SbList <SoCallbackData *> pointcallback;
346
347 SbBool callbackall;
348 };
349
350 #endif // !DOXYGEN_SKIP_THIS
351
352
353 // ***********************************************************************
354
355 /*!
356 \typedef Response SoCallbackAction::SoCallbackActionCB(void * userdata, SoCallbackAction * action, const SoNode * node)
357
358 Callback functions need to be of this type. \a node is at the
359 current traversal point in the scene graph.
360 */
361
362 /*!
363 \enum SoCallbackAction::Response
364 Response values for callback function.
365 */
366 /*!
367 \var SoCallbackAction::Response SoCallbackAction::CONTINUE
368 Continue traversal as usual.
369 */
370 /*!
371 \var SoCallbackAction::Response SoCallbackAction::ABORT
372 Abort traversal immediately. No other callbacks are called after
373 this has been returned.
374 */
375 /*!
376 \var SoCallbackAction::Response SoCallbackAction::PRUNE
377 Don't do traversal of neither the current node (if returning from a
378 pre-traversal callback) nor its children.
379
380 If returned from a pre-callback, the post-callbacks will still be
381 called. If returned from a post-callback, the behaviour will be the
382 same as for returning CONTINUE.
383 */
384
385 // ***********************************************************************
386
387
388 SO_ACTION_SOURCE(SoCallbackAction);
389
390
391 // Override from parent class.
392 void
initClass(void)393 SoCallbackAction::initClass(void)
394 {
395 SO_ACTION_INTERNAL_INIT_CLASS(SoCallbackAction, SoAction);
396
397 SO_ENABLE(SoCallbackAction, SoViewportRegionElement);
398 SO_ENABLE(SoCallbackAction, SoDecimationTypeElement);
399 SO_ENABLE(SoCallbackAction, SoDecimationPercentageElement);
400 SO_ENABLE(SoCallbackAction, SoOverrideElement);
401 SO_ENABLE(SoCallbackAction, SoTextureOverrideElement);
402 SO_ENABLE(SoCallbackAction, SoLazyElement);
403 SO_ENABLE(SoCallbackAction, SoCacheElement);
404
405 // view frustum culling is normally not used for this action, but
406 // the application programmer can manually add any number of culling
407 // planes to optimize callback action traversal. This is used by the
408 // SoExtSelection node.
409 SO_ENABLE(SoCallbackAction, SoCullElement);
410 }
411
412 #define PRIVATE(obj) ((obj)->pimpl)
413
414 /*!
415 Default constructor. Will set the viewport to a standard
416 viewport with size 640x512.
417 */
SoCallbackAction(void)418 SoCallbackAction::SoCallbackAction(void)
419 {
420 this->commonConstructor();
421 }
422
423 /*!
424 Constructor which lets you specify the viewport.
425
426 This constructor is an extension versus the Open Inventor API.
427 */
SoCallbackAction(const SbViewportRegion & vp)428 SoCallbackAction::SoCallbackAction(const SbViewportRegion & vp)
429 {
430 this->commonConstructor();
431 PRIVATE(this)->viewport = vp;
432 PRIVATE(this)->viewportset = TRUE;
433 }
434
435 void
commonConstructor(void)436 SoCallbackAction::commonConstructor(void)
437 {
438 SO_ACTION_CONSTRUCTOR(SoCallbackAction);
439
440 PRIVATE(this)->pretailcallback = NULL;
441 PRIVATE(this)->posttailcallback = NULL;
442 PRIVATE(this)->viewportset = FALSE;
443 PRIVATE(this)->callbackall = FALSE;
444 }
445
446 /*!
447 Sets the viewport region for this action. When set, the viewport
448 element is initialized right before a traversal starts, making it
449 the current viewport.
450
451 This method is an extension versus the Open Inventor API.
452 */
453 void
setViewportRegion(const SbViewportRegion & vp)454 SoCallbackAction::setViewportRegion(const SbViewportRegion & vp)
455 {
456 PRIVATE(this)->viewport = vp;
457 PRIVATE(this)->viewportset = TRUE;
458 }
459
460 static void
delete_list_elements(SbList<SoCallbackData * > & cl)461 delete_list_elements(SbList<SoCallbackData *> & cl)
462 {
463 int n = cl.getLength();
464 for (int i = 0; i < n; i++) cl[i]->deleteAll();
465 }
466
467 /*!
468 Destructor.
469 */
~SoCallbackAction()470 SoCallbackAction::~SoCallbackAction()
471 {
472 delete_list_elements(PRIVATE(this)->precallback);
473 delete_list_elements(PRIVATE(this)->postcallback);
474 delete_list_elements(PRIVATE(this)->trianglecallback);
475 delete_list_elements(PRIVATE(this)->linecallback);
476 delete_list_elements(PRIVATE(this)->pointcallback);
477
478 if (PRIVATE(this)->pretailcallback) {
479 PRIVATE(this)->pretailcallback->deleteAll();
480 }
481 if (PRIVATE(this)->posttailcallback) {
482 PRIVATE(this)->posttailcallback->deleteAll();
483 }
484 }
485
486 //
487 // for setting node callbacks. makes sure NULLs are filled in where not set
488 //
489 static void
set_callback_data_idx(SbList<SoCallbackData * > & list,const int idx,void * func,void * data)490 set_callback_data_idx(SbList<SoCallbackData *> & list, const int idx,
491 void * func, void * data)
492 {
493 int n = list.getLength();
494 while (n <= idx) {
495 list.append(NULL);
496 n++;
497 }
498 if (list[idx] == NULL) list[idx] = new SoCallbackData(func, data);
499 else list[idx]->append(new SoCallbackData(func, data));
500 }
501
502 static void
set_callback_data(SbList<SoCallbackData * > & list,const SoType type,void * func,void * data)503 set_callback_data(SbList<SoCallbackData *> & list, const SoType type,
504 void * func, void * data)
505 {
506 SoTypeList derivedtypes;
507 int n = SoType::getAllDerivedFrom(type, derivedtypes);
508 for (int i = 0; i < n; i++) {
509 set_callback_data_idx(list, static_cast<int>(derivedtypes[i].getData()),
510 func, data);
511 }
512 }
513
514 /*!
515 Set a function \a cb to call before every node of \a type is
516 traversed. \a cb will be called with \a userdata.
517 */
518 void
addPreCallback(const SoType type,SoCallbackActionCB * cb,void * userdata)519 SoCallbackAction::addPreCallback(const SoType type, SoCallbackActionCB * cb,
520 void * userdata)
521 {
522 set_callback_data(PRIVATE(this)->precallback, type, function_to_object_cast<void *>(cb), userdata);
523 }
524
525 /*!
526 Set a function \a cb to call after every node of \a type has been
527 traversed. \a cb will be called with \a userdata.
528 */
529 void
addPostCallback(const SoType type,SoCallbackActionCB * cb,void * userdata)530 SoCallbackAction::addPostCallback(const SoType type, SoCallbackActionCB * cb,
531 void * userdata)
532 {
533 set_callback_data(PRIVATE(this)->postcallback, type, function_to_object_cast<void *>(cb), userdata);
534 }
535
536 /*!
537 Set a function \a cb to call before the tail of a path is
538 traversed. \a cb will be called with \a userdata.
539 */
540 void
addPreTailCallback(SoCallbackActionCB * cb,void * userdata)541 SoCallbackAction::addPreTailCallback(SoCallbackActionCB * cb, void * userdata)
542 {
543 if (PRIVATE(this)->pretailcallback == NULL)
544 PRIVATE(this)->pretailcallback = new SoCallbackData(function_to_object_cast<void *>(cb), userdata);
545 else
546 PRIVATE(this)->pretailcallback->append(new SoCallbackData(function_to_object_cast<void *>(cb), userdata));
547 }
548
549 /*!
550 Set a function \a cb to call after the tail of a path has been
551 traversed. \a cb will be called with \a userdata.
552 */
553 void
addPostTailCallback(SoCallbackActionCB * cb,void * userdata)554 SoCallbackAction::addPostTailCallback(SoCallbackActionCB * cb, void * userdata)
555 {
556 if (PRIVATE(this)->posttailcallback == NULL)
557 PRIVATE(this)->posttailcallback = new SoCallbackData(function_to_object_cast<void *>(cb), userdata);
558 else
559 PRIVATE(this)->posttailcallback->append(new SoCallbackData(function_to_object_cast<void *>(cb), userdata));
560 }
561
562 /*!
563 Set a function \a cb to call when traversing a node of \a type which
564 generates triangle primitives for rendering. \a cb will be called
565 with \a userdata.
566 */
567 void
addTriangleCallback(const SoType type,SoTriangleCB * cb,void * userdata)568 SoCallbackAction::addTriangleCallback(const SoType type, SoTriangleCB * cb,
569 void * userdata)
570 {
571 set_callback_data(PRIVATE(this)->trianglecallback, type, function_to_object_cast<void *>(cb), userdata);
572 }
573
574 /*!
575 Set a function \a cb to call when traversing a node of \a type which
576 generates line primitives for rendering. \a cb will be called with
577 \a userdata.
578 */
579 void
addLineSegmentCallback(const SoType type,SoLineSegmentCB * cb,void * userdata)580 SoCallbackAction::addLineSegmentCallback(const SoType type, SoLineSegmentCB * cb,
581 void * userdata)
582 {
583 set_callback_data(PRIVATE(this)->linecallback, type, function_to_object_cast<void *>(cb), userdata);
584 }
585
586 /*!
587 Set a function \a cb to call when traversing a node of \a type which
588 generates single point primitives for rendering. \a cb will be
589 called with \a userdata.
590 */
591 void
addPointCallback(const SoType type,SoPointCB * cb,void * userdata)592 SoCallbackAction::addPointCallback(const SoType type, SoPointCB * cb,
593 void * userdata)
594 {
595 set_callback_data(PRIVATE(this)->pointcallback, type, function_to_object_cast<void *>(cb), userdata);
596 }
597
598 /************************************************************************************/
599
600 /*!
601 Returns current decimation type setting.
602 */
603 SoDecimationTypeElement::Type
getDecimationType(void) const604 SoCallbackAction::getDecimationType(void) const
605 {
606 return SoDecimationTypeElement::get(this->state);
607 }
608
609 /*!
610 Returns current decimation percentage setting.
611 */
612 float
getDecimationPercentage(void) const613 SoCallbackAction::getDecimationPercentage(void) const
614 {
615 return SoDecimationPercentageElement::get(this->state);
616 }
617
618 /*!
619 Returns current complexity setting.
620 */
621 float
getComplexity(void) const622 SoCallbackAction::getComplexity(void) const
623 {
624 return SoComplexityElement::get(this->state);
625 }
626
627 /*!
628 Returns current complexity type setting.
629 */
630 SoComplexity::Type
getComplexityType(void) const631 SoCallbackAction::getComplexityType(void) const
632 {
633 return static_cast<SoComplexity::Type>(SoComplexityTypeElement::get(this->state));
634 }
635
636 /*!
637 Returns current number of coordinates in the state.
638 */
639 int32_t
getNumCoordinates(void) const640 SoCallbackAction::getNumCoordinates(void) const
641 {
642 return SoCoordinateElement::getInstance(this->state)->getNum();
643 }
644
645 /*!
646 Returns a coordinate triplet from the current state pool of
647 coordinates.
648 */
649 const SbVec3f &
getCoordinate3(const int index) const650 SoCallbackAction::getCoordinate3(const int index) const
651 {
652 return SoCoordinateElement::getInstance(this->state)->get3(index);
653 }
654
655 /*!
656 Returns a coordinate quartuplet from the current state pool of
657 coordinates.
658 */
659 const SbVec4f &
getCoordinate4(const int index) const660 SoCallbackAction::getCoordinate4(const int index) const
661 {
662 return SoCoordinateElement::getInstance(this->state)->get4(index);
663 }
664
665 /*!
666 Returns current draw style setting.
667 */
668 SoDrawStyle::Style
getDrawStyle(void) const669 SoCallbackAction::getDrawStyle(void) const
670 {
671 return static_cast<SoDrawStyle::Style>(SoDrawStyleElement::get(this->state));
672 }
673
674 /*!
675 Returns current line pattern setting.
676 */
677 unsigned short
getLinePattern(void) const678 SoCallbackAction::getLinePattern(void) const
679 {
680 return SoLinePatternElement::get(this->state);
681 }
682
683 /*!
684 Returns current line width setting.
685 */
686 float
getLineWidth(void) const687 SoCallbackAction::getLineWidth(void) const
688 {
689 return SoLineWidthElement::get(this->state);
690 }
691
692 /*!
693 Returns current point size setting.
694 */
695 float
getPointSize(void) const696 SoCallbackAction::getPointSize(void) const
697 {
698 return SoPointSizeElement::get(this->state);
699 }
700
701 /*!
702 Returns current fontname setting.
703 */
704 const SbName &
getFontName(void) const705 SoCallbackAction::getFontName(void) const
706 {
707 return SoFontNameElement::get(this->state);
708 }
709
710 /*!
711 Returns current fontsize setting.
712 */
713 float
getFontSize(void) const714 SoCallbackAction::getFontSize(void) const
715 {
716 return SoFontSizeElement::get(this->state);
717 }
718
719 /*!
720 Returns current lightmodel setting.
721 */
722 SoLightModel::Model
getLightModel(void) const723 SoCallbackAction::getLightModel(void) const
724 {
725 return static_cast<SoLightModel::Model>(SoLazyElement::getLightModel(this->state));
726 }
727
728 /*!
729 Returns current light attenuation setting.
730 */
731 const SbVec3f &
getLightAttenuation(void) const732 SoCallbackAction::getLightAttenuation(void) const
733 {
734 return SoLightAttenuationElement::get(this->state);
735 }
736
737
738 /*!
739 Returns current material settings.
740 */
741 void
getMaterial(SbColor & ambient,SbColor & diffuse,SbColor & specular,SbColor & emission,float & shininess,float & transparency,const int index) const742 SoCallbackAction::getMaterial(SbColor & ambient, SbColor & diffuse,
743 SbColor & specular, SbColor & emission,
744 float & shininess, float & transparency,
745 const int index) const
746 {
747 ambient = SoLazyElement::getAmbient(this->state);
748 diffuse = SoLazyElement::getDiffuse(this->state, index);
749 emission = SoLazyElement::getEmissive(this->state);
750 specular = SoLazyElement::getSpecular(this->state);
751 shininess = SoLazyElement::getShininess(this->state);
752 transparency = SoLazyElement::getTransparency(this->state, index);
753 }
754
755 /*!
756 Returns current materialbinding setting.
757 */
758 SoMaterialBinding::Binding
getMaterialBinding(void) const759 SoCallbackAction::getMaterialBinding(void) const
760 {
761 return static_cast<SoMaterialBinding::Binding>(
762 SoMaterialBindingElement::get(this->state)
763 );
764 }
765
766 /*!
767 Returns current number of normals in the state.
768 */
769 uint32_t
getNumNormals(void) const770 SoCallbackAction::getNumNormals(void) const
771 {
772 return SoNormalElement::getInstance(this->state)->getNum();
773 }
774
775 /*!
776 Returns the normal vectors at \a index from the current state.
777 */
778 const SbVec3f &
getNormal(const int index) const779 SoCallbackAction::getNormal(const int index) const
780 {
781 return SoNormalElement::getInstance(this->state)->get(index);
782 }
783
784 /*!
785 Returns current normalbinding setting.
786 */
787 SoNormalBinding::Binding
getNormalBinding(void) const788 SoCallbackAction::getNormalBinding(void) const
789 {
790 return static_cast<SoNormalBinding::Binding>(
791 SoNormalBindingElement::get(this->state)
792 );
793 }
794
795 /*!
796 Returns current number of profile coordinates in the state.
797 */
798 int32_t
getNumProfileCoordinates(void) const799 SoCallbackAction::getNumProfileCoordinates(void) const
800 {
801 return SoProfileCoordinateElement::getInstance(this->state)->getNum();
802 }
803
804 /*!
805 Returns current number of SbVec2f profile coordinates in the state.
806 */
807 const SbVec2f &
getProfileCoordinate2(const int index) const808 SoCallbackAction::getProfileCoordinate2(const int index) const
809 {
810 return SoProfileCoordinateElement::getInstance(this->state)->get2(index);
811 }
812
813 /*!
814 Returns current number of SbVec3f profile coordinates in the state.
815 */
816 const SbVec3f &
getProfileCoordinate3(const int index) const817 SoCallbackAction::getProfileCoordinate3(const int index) const
818 {
819 return SoProfileCoordinateElement::getInstance(this->state)->get3(index);
820 }
821
822 /*!
823 Returns current list of profile nodes.
824 */
825 const SoNodeList &
getProfile(void) const826 SoCallbackAction::getProfile(void) const
827 {
828 return SoProfileElement::get(this->state);
829 }
830
831 /*!
832 Returns current vertexordering shapehint setting.
833
834 Please note that this is the vertex ordering set by the SoShapeHints
835 node. If you want to find the vertex ordering for VRML nodes you'll
836 need to read this directly from the \a ccw field in those
837 nodes.
838 */
839 SoShapeHints::VertexOrdering
getVertexOrdering(void) const840 SoCallbackAction::getVertexOrdering(void) const
841 {
842 return static_cast<SoShapeHints::VertexOrdering>(
843 SoShapeHintsElement::getVertexOrdering(this->state)
844 );
845 }
846
847 /*!
848 Returns current shapetype hint setting.
849
850 Please note that this is the shape type set by the SoShapeHints
851 node. If you want to find the shape type for VRML nodes you'll
852 need to read this directly from the \a solid field in those
853 nodes.
854 */
855 SoShapeHints::ShapeType
getShapeType(void) const856 SoCallbackAction::getShapeType(void) const
857 {
858 return static_cast<SoShapeHints::ShapeType>(
859 SoShapeHintsElement::getShapeType(this->state)
860 );
861 }
862
863 /*!
864 Returns current facetype hint setting.
865
866 Please note that this is the face type set by the SoShapeHints
867 node. If you want to find the face type for VRML nodes you'll
868 need to read this directly from the \a convex field in those
869 nodes.
870
871 */
872 SoShapeHints::FaceType
getFaceType(void) const873 SoCallbackAction::getFaceType(void) const
874 {
875 return static_cast<SoShapeHints::FaceType>(
876 SoShapeHintsElement::getFaceType(this->state)
877 );
878 }
879
880 /*!
881 Returns current creaseangle setting. Please note that this is the
882 crease angle value set by the SoShapeHints node. If you want to find
883 the crease angle for VRML nodes you'll need to read this directly
884 from the creaseAngle field in those nodes.
885 */
886 float
getCreaseAngle(void) const887 SoCallbackAction::getCreaseAngle(void) const
888 {
889 return SoCreaseAngleElement::get(this->state);
890 }
891
892 /*!
893 Returns current number of texture coordinates in the traversal
894 state.
895 */
896 int32_t
getNumTextureCoordinates(void) const897 SoCallbackAction::getNumTextureCoordinates(void) const
898 {
899 return SoMultiTextureCoordinateElement::getInstance(this->state)->getNum(0);
900 }
901
902 /*!
903 Returns SbVec2f texture coordinate at \a index from the texture
904 coordinate pool of the traversal state.
905 */
906 const SbVec2f &
getTextureCoordinate2(const int index) const907 SoCallbackAction::getTextureCoordinate2(const int index) const
908 {
909 return SoMultiTextureCoordinateElement::getInstance(this->state)->get2(0, index);
910 }
911
912 /*!
913 Returns SbVec3f texture coordinate at \a index from the texture
914 coordinate pool of the traversal state.
915
916 \COIN_FUNCTION_EXTENSION
917
918 \since Coin 2.0
919 */
920 const SbVec3f &
getTextureCoordinate3(const int index) const921 SoCallbackAction::getTextureCoordinate3(const int index) const
922 {
923 return SoMultiTextureCoordinateElement::getInstance(this->state)->get3(0, index);
924 }
925
926 /*!
927 Returns SbVec4f texture coordinate at \a index from the texture
928 coordinate pool of the traversal state.
929 */
930 const SbVec4f &
getTextureCoordinate4(const int index) const931 SoCallbackAction::getTextureCoordinate4(const int index) const
932 {
933 return SoMultiTextureCoordinateElement::getInstance(this->state)->get4(0, index);
934 }
935
936 /*!
937 Returns current texturecoordinate binding setting.
938 */
939 SoTextureCoordinateBinding::Binding
getTextureCoordinateBinding(void) const940 SoCallbackAction::getTextureCoordinateBinding(void) const
941 {
942 return static_cast<SoTextureCoordinateBinding::Binding>(
943 SoTextureCoordinateBindingElement::get(this->state)
944 );
945 }
946
947 /*!
948 Returns current texture blend color setting.
949 */
950 const SbColor &
getTextureBlendColor(void) const951 SoCallbackAction::getTextureBlendColor(void) const
952 {
953 return SoMultiTextureImageElement::getBlendColor(this->state, 0);
954 }
955
956 /*!
957 Returns current texture image settings.
958 */
959 const unsigned char *
getTextureImage(SbVec2s & size,int & numcomps) const960 SoCallbackAction::getTextureImage(SbVec2s & size, int & numcomps) const
961 {
962 return SoMultiTextureImageElement::getImage(state, 0, size, numcomps);
963 }
964
965 /*!
966 Returns current 3D texture image settings.
967
968 \COIN_FUNCTION_EXTENSION
969
970 \since Coin 2.0
971 */
972 const unsigned char *
getTextureImage(SbVec3s & size,int & numcomps) const973 SoCallbackAction::getTextureImage(SbVec3s & size, int & numcomps) const
974 {
975 return SoMultiTextureImageElement::getImage(state, 0, size, numcomps);
976 }
977
978 /*!
979 Returns current texture transformation matrix setting.
980 */
981 const SbMatrix &
getTextureMatrix(void) const982 SoCallbackAction::getTextureMatrix(void) const
983 {
984 return SoMultiTextureMatrixElement::get(this->state, 0);
985 }
986
987 /*!
988 Returns current texturemapping model setting.
989 */
990 SoTexture2::Model
getTextureModel(void) const991 SoCallbackAction::getTextureModel(void) const
992 {
993 return static_cast<SoTexture2::Model>( SoMultiTextureImageElement::getModel(this->state, 0));
994 }
995
996 /*!
997 Returns current texture wrapping setting for the \c S coordinate.
998 */
999 SoTexture2::Wrap
getTextureWrapS(void) const1000 SoCallbackAction::getTextureWrapS(void) const
1001 {
1002 return static_cast<SoTexture2::Wrap>( SoMultiTextureImageElement::getWrapS(this->state,0));
1003 }
1004
1005 /*!
1006 Returns current texture wrapping setting for the \c T coordinate.
1007 */
1008 SoTexture2::Wrap
getTextureWrapT(void) const1009 SoCallbackAction::getTextureWrapT(void) const
1010 {
1011 return static_cast<SoTexture2::Wrap>(SoMultiTextureImageElement::getWrapT(this->state, 0));
1012 }
1013
1014 /*!
1015 Returns current texture wrapping setting for the \c R coordinate.
1016
1017 \COIN_FUNCTION_EXTENSION
1018
1019 \since Coin 2.0
1020 */
1021 SoTexture2::Wrap
getTextureWrapR(void) const1022 SoCallbackAction::getTextureWrapR(void) const
1023 {
1024 return static_cast<SoTexture2::Wrap>(SoMultiTextureImageElement::getWrapR(this->state, 0));
1025 }
1026
1027 /*!
1028 Returns current model matrix.
1029 */
1030 const SbMatrix &
getModelMatrix(void) const1031 SoCallbackAction::getModelMatrix(void) const
1032 {
1033 return SoModelMatrixElement::get(this->state);
1034 }
1035
1036 /*!
1037 Returns current units setting.
1038 */
1039 SoUnits::Units
getUnits(void) const1040 SoCallbackAction::getUnits(void) const
1041 {
1042 return static_cast<SoUnits::Units>(SoUnitsElement::get(this->state));
1043 }
1044
1045 /*!
1046 Returns current camera focal distance setting.
1047 */
1048 float
getFocalDistance(void) const1049 SoCallbackAction::getFocalDistance(void) const
1050 {
1051 return SoFocalDistanceElement::get(this->state);
1052 }
1053
1054 /*!
1055 Returns current projection matrix.
1056 */
1057 const SbMatrix &
getProjectionMatrix(void) const1058 SoCallbackAction::getProjectionMatrix(void) const
1059 {
1060 return SoProjectionMatrixElement::get(this->state);
1061 }
1062
1063 /*!
1064 Returns current viewing matrix.
1065 */
1066 const SbMatrix &
getViewingMatrix(void) const1067 SoCallbackAction::getViewingMatrix(void) const
1068 {
1069 return SoViewingMatrixElement::get(this->state);
1070 }
1071
1072 /*!
1073 Returns current view volume setting.
1074 */
1075 const SbViewVolume &
getViewVolume(void) const1076 SoCallbackAction::getViewVolume(void) const
1077 {
1078 return SoViewVolumeElement::get(this->state);
1079 }
1080
1081 /*!
1082 Returns current viewport region setting.
1083
1084 This method is an extension versus the Open Inventor API.
1085 */
1086 const SbViewportRegion &
getViewportRegion(void) const1087 SoCallbackAction::getViewportRegion(void) const
1088 {
1089 return SoViewportRegionElement::get(this->getState());
1090 }
1091
1092 /*!
1093 Returns current pickstyle setting.
1094 */
1095 SoPickStyle::Style
getPickStyle(void) const1096 SoCallbackAction::getPickStyle(void) const
1097 {
1098 return static_cast<SoPickStyle::Style>(SoPickStyleElement::get(this->state));
1099 }
1100
1101 /*!
1102 Returns last SoSwitch::whichChild setting during the traversal.
1103 */
1104 int32_t
getSwitch(void) const1105 SoCallbackAction::getSwitch(void) const
1106 {
1107 return SoSwitchElement::get(this->state);
1108 }
1109
1110 /************************************************************************************/
1111
1112 /*!
1113 \COININTERNAL
1114 */
1115 SoCallbackAction::Response
getCurrentResponse(void) const1116 SoCallbackAction::getCurrentResponse(void) const
1117 {
1118 return PRIVATE(this)->response;
1119 }
1120
1121 /*!
1122 \COININTERNAL
1123
1124 Invoke all "pre traversal" callbacks.
1125 */
1126 void
invokePreCallbacks(const SoNode * const node)1127 SoCallbackAction::invokePreCallbacks(const SoNode * const node)
1128 {
1129 // reset response if previous node was pruned
1130 if (PRIVATE(this)->response == PRUNE) PRIVATE(this)->response = CONTINUE;
1131
1132 int idx = static_cast<int>(node->getTypeId().getData());
1133
1134 if (idx < PRIVATE(this)->precallback.getLength() && PRIVATE(this)->precallback[idx] != NULL) {
1135 PRIVATE(this)->response = PRIVATE(this)->precallback[idx]->doNodeCallbacks(this, node);
1136 if (PRIVATE(this)->response == SoCallbackAction::ABORT) {
1137 this->setTerminated(TRUE);
1138 return;
1139 }
1140 }
1141
1142 if (this->getWhatAppliedTo() == SoAction::PATH &&
1143 this->getPathAppliedTo()->getTail() == node && PRIVATE(this)->pretailcallback != NULL) {
1144 PRIVATE(this)->response = PRIVATE(this)->pretailcallback->doNodeCallbacks(this, node);
1145 if (PRIVATE(this)->response == SoCallbackAction::ABORT) {
1146 this->setTerminated(TRUE);
1147 return;
1148 }
1149 }
1150 // FIXME: add code to handle pathlist traversal callbacks
1151 // pederb, 19991209
1152 }
1153
1154 /*!
1155 \COININTERNAL
1156
1157 Invoke all "post traversal" callbacks.
1158 */
1159 void
invokePostCallbacks(const SoNode * const node)1160 SoCallbackAction::invokePostCallbacks(const SoNode * const node)
1161 {
1162 // reset response if previous node was pruned
1163 if (PRIVATE(this)->response == PRUNE) PRIVATE(this)->response = CONTINUE;
1164
1165 int idx = static_cast<int>(node->getTypeId().getData());
1166 if (idx < PRIVATE(this)->postcallback.getLength() && PRIVATE(this)->postcallback[idx] != NULL) {
1167 PRIVATE(this)->response = static_cast<Response>(PRIVATE(this)->postcallback[idx]->doNodeCallbacks(this, node));
1168 if (PRIVATE(this)->response == SoCallbackAction::ABORT) {
1169 this->setTerminated(TRUE);
1170 return;
1171 }
1172 }
1173
1174 if (this->getWhatAppliedTo() == SoAction::PATH &&
1175 this->getPathAppliedTo()->getTail() == node && PRIVATE(this)->posttailcallback) {
1176 PRIVATE(this)->response = PRIVATE(this)->posttailcallback->doNodeCallbacks(this, node);
1177 if (PRIVATE(this)->response == SoCallbackAction::ABORT) {
1178 this->setTerminated(TRUE);
1179 return;
1180 }
1181 }
1182 // FIXME: add code to handle pathlist traversal callbacks
1183 // pederb, 19991209
1184 }
1185
1186 /*!
1187 \COININTERNAL
1188
1189 Invoke all "triangle generation" callbacks.
1190 */
1191 void
invokeTriangleCallbacks(const SoShape * const shape,const SoPrimitiveVertex * const v1,const SoPrimitiveVertex * const v2,const SoPrimitiveVertex * const v3)1192 SoCallbackAction::invokeTriangleCallbacks(const SoShape * const shape,
1193 const SoPrimitiveVertex * const v1,
1194 const SoPrimitiveVertex * const v2,
1195 const SoPrimitiveVertex * const v3)
1196 {
1197 int idx = static_cast<int>(shape->getTypeId().getData());
1198 if (idx < PRIVATE(this)->trianglecallback.getLength() && PRIVATE(this)->trianglecallback[idx] != NULL)
1199 PRIVATE(this)->trianglecallback[idx]->doTriangleCallbacks(this, v1, v2, v3);
1200 }
1201
1202 /*!
1203 \COININTERNAL
1204
1205 Invoke all "line segment generation" callbacks.
1206 */
1207 void
invokeLineSegmentCallbacks(const SoShape * const shape,const SoPrimitiveVertex * const v1,const SoPrimitiveVertex * const v2)1208 SoCallbackAction::invokeLineSegmentCallbacks(const SoShape * const shape,
1209 const SoPrimitiveVertex * const v1,
1210 const SoPrimitiveVertex * const v2)
1211 {
1212 int idx = static_cast<int>(shape->getTypeId().getData());
1213 if (idx < PRIVATE(this)->linecallback.getLength() && PRIVATE(this)->linecallback[idx] != NULL)
1214 PRIVATE(this)->linecallback[idx]->doLineSegmentCallbacks(this, v1, v2);
1215 }
1216
1217 /*!
1218 \COININTERNAL
1219
1220 Invoke all "point" callbacks.
1221 */
1222 void
invokePointCallbacks(const SoShape * const shape,const SoPrimitiveVertex * const v)1223 SoCallbackAction::invokePointCallbacks(const SoShape * const shape,
1224 const SoPrimitiveVertex * const v)
1225 {
1226 int idx = static_cast<int>(shape->getTypeId().getData());
1227 if (idx < PRIVATE(this)->pointcallback.getLength() && PRIVATE(this)->pointcallback[idx] != NULL)
1228 PRIVATE(this)->pointcallback[idx]->doPointCallbacks(this, v);
1229 }
1230
1231 /*!
1232 \COININTERNAL
1233
1234 Check from the shape nodes whether or not to generate primitives
1235 from the complex shapes. If there are no callbacks attached to the
1236 node types, making the primitives would only be a waste of CPU.
1237 */
1238 SbBool
shouldGeneratePrimitives(const SoShape * shape) const1239 SoCallbackAction::shouldGeneratePrimitives(const SoShape * shape) const
1240 {
1241 int idx = static_cast<int>(shape->getTypeId().getData());
1242 if (idx < PRIVATE(this)->trianglecallback.getLength() && PRIVATE(this)->trianglecallback[idx])
1243 return TRUE;
1244 if (idx < PRIVATE(this)->linecallback.getLength() && PRIVATE(this)->linecallback[idx])
1245 return TRUE;
1246 if (idx < PRIVATE(this)->pointcallback.getLength() && PRIVATE(this)->pointcallback[idx])
1247 return TRUE;
1248 return FALSE;
1249 }
1250
1251 /*!
1252 Returns the current tail of the traversal path for the callback
1253 action.
1254 */
1255 SoNode *
getCurPathTail(void)1256 SoCallbackAction::getCurPathTail(void)
1257 {
1258 return PRIVATE(this)->currentnode;
1259 }
1260
1261 /*!
1262 Used from nodes during traversal to keep a current node pointer in
1263 the action.
1264 */
1265 void
setCurrentNode(SoNode * const node)1266 SoCallbackAction::setCurrentNode(SoNode * const node)
1267 {
1268 PRIVATE(this)->currentnode = node;
1269 }
1270
1271 // Documented in superclass. Overridden from parent class to
1272 // initialize variables which need to be reset for each traversal.
1273 void
beginTraversal(SoNode * node)1274 SoCallbackAction::beginTraversal(SoNode * node)
1275 {
1276 PRIVATE(this)->response = SoCallbackAction::CONTINUE;
1277 // we set the viewport region element here. This element is not enabled
1278 // for SoCallbackAction in Inventor, bu we think it should be.
1279 // It makes it possible to calculate screen space stuff in
1280 // the callback action callbacks.
1281 if (PRIVATE(this)->viewportset) {
1282 SoViewportRegionElement::set(this->getState(), PRIVATE(this)->viewport);
1283 }
1284 this->traverse(node);
1285 }
1286
setCallbackAll(SbBool callbackall)1287 void SoCallbackAction::setCallbackAll(SbBool callbackall)
1288 {
1289 PRIVATE(this)->callbackall = callbackall;
1290 }
1291
isCallbackAll(void) const1292 SbBool SoCallbackAction::isCallbackAll(void) const
1293 {
1294 return PRIVATE(this)->callbackall;
1295 }
1296
1297 #undef PRIVATE
1298
1299 #ifdef COIN_TEST_SUITE
1300
1301 #include <Inventor/nodes/SoSwitch.h>
1302 #include <Inventor/nodes/SoCube.h>
1303
1304 static SoCallbackAction::Response
preCB(void * userdata,SoCallbackAction *,const SoNode * node)1305 preCB(void * userdata, SoCallbackAction *, const SoNode * node)
1306 {
1307 SbString *str = (SbString *)userdata;
1308 (*str) += node->getName();
1309 return SoCallbackAction::CONTINUE;
1310 }
1311
BOOST_AUTO_TEST_CASE(callbackall)1312 BOOST_AUTO_TEST_CASE(callbackall)
1313 {
1314 SbString str;
1315 SoSwitch * sw = new SoSwitch;
1316 sw->setName("switch");
1317 SoCube * cube = new SoCube;
1318 cube->setName("cube");
1319 sw->addChild(cube);
1320 sw->ref();
1321
1322 SoCallbackAction cba;
1323 cba.addPreCallback(SoNode::getClassTypeId(), preCB, &str);
1324 cba.apply(sw);
1325 BOOST_CHECK_MESSAGE(str == "switch", "Should not traverse under switch node");
1326
1327 str = "";
1328 cba.setCallbackAll(true);
1329 cba.apply(sw);
1330 BOOST_CHECK_MESSAGE(str == "switchcube", "Should traverse under switch node");
1331
1332 sw->unref();
1333 }
1334
1335 #endif // COIN_TEST_SUITE
1336