Open Inventor Release 2023.2.3
 
Loading...
Searching...
No Matches
SoSubNode.h
Go to the documentation of this file.
1/*=======================================================================
2 * Copyright 1991-1996, Silicon Graphics, Inc.
3 * ALL RIGHTS RESERVED
4 *
5 * UNPUBLISHED -- Rights reserved under the copyright laws of the United
6 * States. Use of a copyright notice is precautionary only and does not
7 * imply publication or disclosure.
8 *
9 * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
10 * Use, duplication or disclosure by the Government is subject to restrictions
11 * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
12 * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
13 * in similar or successor clauses in the FAR, or the DOD or NASA FAR
14 * Supplement. Contractor/manufacturer is Silicon Graphics, Inc.,
15 * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
16 *
17 * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
18 * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
19 * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
20 * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
21 * GRAPHICS, INC.
22**=======================================================================*/
23/*=======================================================================
24** Author : Paul S. Strauss (MMM yyyy)
25** Modified by : Gavin Bell (MMM yyyy)
26** Modified by : Ronen Barzel (MMM yyyy)
27**=======================================================================*/
28/*=======================================================================
29 *** THE CONTENT OF THIS WORK IS PROPRIETARY TO FEI S.A.S, (FEI S.A.S.), ***
30 *** AND IS DISTRIBUTED UNDER A LICENSE AGREEMENT. ***
31 *** ***
32 *** REPRODUCTION, DISCLOSURE, OR USE, IN WHOLE OR IN PART, OTHER THAN AS ***
33 *** SPECIFIED IN THE LICENSE ARE NOT TO BE UNDERTAKEN EXCEPT WITH PRIOR ***
34 *** WRITTEN AUTHORIZATION OF FEI S.A.S. ***
35 *** ***
36 *** RESTRICTED RIGHTS LEGEND ***
37 *** USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT OF THE CONTENT OF THIS ***
38 *** WORK OR RELATED DOCUMENTATION IS SUBJECT TO RESTRICTIONS AS SET FORTH IN ***
39 *** SUBPARAGRAPH (C)(1) OF THE COMMERCIAL COMPUTER SOFTWARE RESTRICTED RIGHT ***
40 *** CLAUSE AT FAR 52.227-19 OR SUBPARAGRAPH (C)(1)(II) OF THE RIGHTS IN ***
41 *** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 52.227-7013. ***
42 *** ***
43 *** COPYRIGHT (C) 1996-2014 BY FEI S.A.S, ***
44 *** BORDEAUX, FRANCE ***
45 *** ALL RIGHTS RESERVED ***
46**=======================================================================*/
47/*=======================================================================
48** Modified by : VSG (MMM YYYY)
49**=======================================================================*/
50
51
52#ifndef _SO_SUB_NODE_
53#define _SO_SUB_NODE_
54
60#include <Inventor/SoDB.h>
61
62// *** note: many of the macros use the "do { ... } while(0)"
63// *** hack to define multiline blocks as a single statement
64// *** of code that can be used anywhere and ended with a semicolon
65
67//
68// Debugging macros (used by other macros in this file)
69//
70#if defined(_DEBUG)
71#define SO__NODE_CHECK_INIT(className) { \
72 if (classTypeId.isBad()) { \
73 SoDebugError::post("SO_NODE_CONSTRUCTOR", \
74 "Can't construct a node of type " \
75 SO__QUOTE(className) \
76 " until initClass() has been called"); \
77 className::initClass(); \
78 } \
79 SoTypedObject::checkDatabase(SO__QUOTE(className), this, className::getClassTypeId(), classTypeId); \
80}
81
82#define SO__NODE_CHECK_CONSTRUCT(where) { \
83 if (fieldData == NULL) { \
84 SoDebugError::post(where, \
85 "Instance not properly constructed.\n" \
86 "Did you forget to put SO_NODE_CONSTRUCTOR()" \
87 " in the constructor?"); \
88 fieldData = new SoFieldData(parentFieldData ? *parentFieldData : NULL); \
89 } \
90}
91
92#else
93#define SO__NODE_CHECK_INIT(className) { \
94 if (classTypeId.isBad()) { \
95 className::initClass(); \
96 } \
97}
98
99#define SO__NODE_CHECK_CONSTRUCT(where) { \
100 if (fieldData == NULL) { \
101 fieldData = new SoFieldData(parentFieldData ? *parentFieldData : NULL); \
102 } \
103}
104#endif
105
107//
108// Macros to be called within the class definition header for a node
109// subclass:
110//
111
113//
114// These defines type-identifier and naming variables and methods that
115// all subclasses and abstract subclasses must support.
116//
117
118#define SO_NODE_ABSTRACT_HEADER(className) \
119 public: \
120 \
121 static SoType getClassTypeId() \
122 { return classTypeId; } \
123 \
124 virtual SoType getTypeId() const; \
125 \
126
128 { return className::getClassRenderEngineMode(); } \ \
130
132 { return s_renderEngineMode; } \
133 private: \
134 virtual SbBool getIsBuiltIn() const ; \
135 virtual const SoFieldData *getFieldData() const; \
136 private: \
137 static const SoFieldData **getFieldDataPtr(); \
138 private: \
139 static SbThreadMutex classMutex; \
140 static SoType classTypeId; /* Type id */ \
141 static SbBool isBuiltIn; \
142 static SbBool firstInstance; /* true until 2nd c'tor call */ \
143 static SoFieldData *fieldData; \
144 static const SoFieldData **parentFieldData; \
145 static SbRenderEngineMode s_renderEngineMode
146
147//
148// Non-abstract classes have everything abstract classes have, plus a way
149// to create an instance
150//
151#define SO_NODE_HEADER(className) \
152 SO_NODE_ABSTRACT_HEADER(className); \
153 static void *createInstance(SoType* dynamicType = NULL)
154
156//
157// Macros to be called within the source file for a node subclass:
158//
159
161//
162// This declares the static variables defined in SO_NODE_HEADER
163// or SO_NODE_ABSTRACT_HEADER.
164//
165
166#define SO__NODE_ABSTRACT_VARS(className) \
167 SbThreadMutex className::classMutex; \
168 SoType className::classTypeId; \
169 SbBool className::isBuiltIn = FALSE; \
170 SoFieldData *className::fieldData = NULL; \
171 const SoFieldData **className::parentFieldData = NULL; \
172 SbBool className::firstInstance = TRUE; \
173 SbRenderEngineMode className::s_renderEngineMode;
174
175//
176// Non-abstract nodes have all the stuff abstract nodes do
177//
178#define SO__NODE_VARS(className) \
179 SO__NODE_ABSTRACT_VARS(className)
180
182//
183// Methods on the abstract type
184//
185
186#define SO__NODE_ABSTRACT_METHODS(className) \
187 \
188 SoType \
189 className::getTypeId() const \
190 { \
191 return classTypeId; \
192 } \
193 \
194 const SoFieldData * \
195 className::getFieldData() const \
196 { \
197 classMutex.lock(); \
198 SO__NODE_CHECK_CONSTRUCT(SO__QUOTE(className)); \
199 SoFieldData * result = fieldData; \
200 classMutex.unlock(); \
201 return result; \
202 } \
203 \
204 SbBool className::getIsBuiltIn() const \
205 { \
206 return isBuiltIn; \
207 } \
208 \
209 const SoFieldData **className::getFieldDataPtr() \
210 { \
211 classMutex.lock(); \
212 const SoFieldData **result = (const SoFieldData **)&fieldData; \
213 classMutex.unlock(); \
214 return result; \
215 }
216
218//
219// These implement the methods defined in SO_NODE_HEADER or
220// SO_NODE_ABSTRACT_HEADER.
221//
222
223#define SO__NODE_METHODS(className) \
224 \
225 SO__NODE_ABSTRACT_METHODS(className) \
226 \
227 void * \
228 className::createInstance(SoType *) \
229 { \
230 return (void *)(new className); \
231 }
232
233
234
236//
237// These include all the definitions required
238// at file scope
239//
240
241#define SO_NODE_SOURCE(className) \
242 SO__NODE_VARS(className); \
243 SO__NODE_METHODS(className)
244
245#define SO_NODE_ABSTRACT_SOURCE(className) \
246 SO__NODE_ABSTRACT_VARS(className); \
247 SO__NODE_ABSTRACT_METHODS(className)
248
249
251//
252// Internal initialization macros
253//
254
255#if defined(_DEBUG)
256#define SO_NODE_INIT_CLASS_CHECK_PARENT(className, parentClass) \
257 if (parentClass::getClassTypeId().isBad()) { \
258 SoDebugError::post( SO__QUOTE(className)"::initClass", \
259 SO__QUOTE(className)" initialized before parent class " \
260 SO__QUOTE(parentClass)"\n"); \
261 parentClass::initClass(); \
262 }
263#else
264#define SO_NODE_INIT_CLASS_CHECK_PARENT(className, parentClass) \
265 if (parentClass::getClassTypeId().isBad()) \
266 parentClass::initClass()
267#endif
268
269#if defined(LIBRARYBUILD)
270// by default internal Open Inventor nodes are considered as OIV 10 compatible
271#define SO_NODE_INIT_RENDERING_MODE(className, parentClass) \
272 className::getClassRenderEngineMode().setRenderMode(SbRenderEngineMode::OIV_OPENINVENTOR_RENDERING);\
273 if (parentClass::getClassRenderEngineMode().isChildrenInherit()) \
274 className::getClassRenderEngineMode().setChildrenInherit(parentClass::getClassRenderEngineMode().isChildrenInherit())
275#else
276// for custom nodes we rely on explicit call of setRenderMode in initClass() implementation
277// before calling SO_NODE_INIT_CLASS macro.
278#define SO_NODE_INIT_RENDERING_MODE(className, parentClass) \
279 if ( className::getClassRenderEngineMode().isNotDefined() ) \
280 { \
281 if (parentClass::getClassRenderEngineMode().isChildrenInherit()) \
282 s_renderEngineMode = parentClass::getClassRenderEngineMode(); \
283 else \
284 SbRenderEngineMode::postInitWarning( OIV_FUNCTION); \
285 }
286#endif
287
288#define SO__NODE_INIT_CLASS_INTERNAL(className,classPrintName,parentClass) \
289 classMutex.lock(); \
290 SO_NODE_INIT_RENDERING_MODE(className, parentClass); \
291 SO_NODE_INIT_CLASS_CHECK_PARENT(className, parentClass); \
292 classTypeId = SoType::createType( parentClass::getClassTypeId(), \
293 classPrintName, \
294 &className::createInstance, \
295 (short)SoNode::getNextActionMethodIndex()); \
296 if (parentFieldData == NULL) \
297 SoNode::incNextActionMethodIndex(); \
298 parentFieldData = parentClass::getFieldDataPtr(); \
299 classMutex.unlock();
300
301#define SO__NODE_INIT_CLASS(className,classPrintName,parentClass) \
302 SO__NODE_INIT_CLASS_INTERNAL(className,classPrintName,parentClass)
303
304#define SO__NODE_INIT_ABSTRACT_CLASS_INTERNAL(className,classPrintName,parentClass) \
305 classMutex.lock(); \
306 SO_NODE_INIT_CLASS_CHECK_PARENT(className, parentClass); \
307 classTypeId = SoType::createType( parentClass::getClassTypeId(), \
308 classPrintName, \
309 NULL, \
310 (short)SoNode::getNextActionMethodIndex()); \
311 if (parentFieldData == NULL) \
312 SoNode::incNextActionMethodIndex(); \
313 parentFieldData = parentClass::getFieldDataPtr(); \
314 classMutex.unlock();
315
316#define SO__NODE_INIT_ABSTRACT_CLASS(className,classPrintName,parentClass) \
317 SO__NODE_INIT_ABSTRACT_CLASS_INTERNAL(className,classPrintName,parentClass)
318
319#if defined(_DEBUG)
320#define SO__NODE_EXIT_CLASS(className) \
321 if (! SoType::removeType(classTypeId.getName())) { \
322 SoDebugError::post(SO__QUOTE(className)"::exitClass", \
323 "Unable to remove type (%s) for this class. Check exitClass() " \
324 "method is implemented and is called only once.\n", \
325 classTypeId.getName().getString() ); \
326 } \
327 else \
328 { \
329 classTypeId = SoType::badType(); \
330 if (fieldData != NULL) \
331 { \
332 delete fieldData; \
333 fieldData = NULL; \
334 } \
335 parentFieldData = NULL; \
336 firstInstance = TRUE; \
337 }
338#else
339#define SO__NODE_EXIT_CLASS(className) \
340 SoType::removeType(classTypeId.getName()); \
341 classTypeId = SoType::badType(); \
342 if (fieldData != NULL) \
343 { \
344 delete fieldData; \
345 fieldData = NULL; \
346 } \
347 parentFieldData = NULL; \
348 firstInstance = TRUE
349#endif
350
352//
353// This requests allocation of thread local storage. This macro
354// should be called within initClass(). The structName argument
355// should be the structure (the type name) defining what size
356// of memory should be allocated for each thread, for this class
357//
358// LOCAL_THREAD_VAR gives access to the thread local storage
359// variable. _structName_ should be the same as structName, and
360// _varName_ should be a type declared within structName.
361// Note that LOCAL_THREAD_VAR should not be called before the
362// thread local storage has been initialized (see SbThreadLocalStorage)
363//
364// KEEP FOR COMPATIBILITY... Macros have been moved to SoTLS.h
365#define SO_THREAD_NODE_INIT_CLASS(className,structName) \
366 \
367 SB_THREAD_INIT_CLASS(className,structName)
368
369#define SO_THREAD_NODE_EXIT_CLASS(className) \
370 \
371 SB_THREAD_EXIT_CLASS(className)
372
373#define LOCAL_THREAD_VAR(_className_, _structName_, _varName_) \
374 \
375 GET_THREAD_LOCAL_VAR(_className_, _structName_, _varName_)
376
377#define LOCAL_THREAD_STORAGE(_className_) \
378 \
379 GET_THREAD_LOCAL_STORAGE(_className_)
380
381
383//
384// This initializes the type identifer variables defined in
385// SO_NODE_HEADER or SO_NODE_ABSTRACT_HEADER. This macro
386// should be called from within initClass(). The parentClass argument
387// should be the class that this subclass is derived from.
388//
389#define SO_NODE_INIT_CLASS_INTERNAL(className,parentClass,parentPrintClass) \
390 classMutex.lock(); \
391 SO_NODE_INIT_RENDERING_MODE(className, parentClass); \
392 SO_NODE_INIT_CLASS_CHECK_PARENT(className, parentClass); \
393 classTypeId = SoType::createType( SoType::fromName(parentPrintClass), \
394 SO__QUOTE(className), \
395 &className::createInstance, \
396 (short)SoNode::getNextActionMethodIndex()); \
397 if (parentFieldData == NULL) \
398 SoNode::incNextActionMethodIndex(); \
399 parentFieldData = parentClass::getFieldDataPtr(); \
400 classMutex.unlock();
401
402#define SO_NODE_INIT_CLASS(className,parentClass,parentPrintClass) \
403 \
404 SO_NODE_INIT_CLASS_INTERNAL(className,parentClass,parentPrintClass)
405
406#define SO_NODE_INIT_ABSTRACT_CLASS_INTERNAL(className, parentClass, parentPrintClass) \
407 classMutex.lock(); \
408 SO_NODE_INIT_RENDERING_MODE(className,parentClass); \
409 SO_NODE_INIT_CLASS_CHECK_PARENT(className, parentClass); \
410 classTypeId = SoType::createType( SoType::fromName(parentPrintClass), \
411 SO__QUOTE(className), \
412 NULL, \
413 (short)SoNode::getNextActionMethodIndex()); \
414 if (parentFieldData == NULL) \
415 SoNode::incNextActionMethodIndex(); \
416 parentFieldData = parentClass::getFieldDataPtr(); \
417 classMutex.unlock();
418
419#define SO_NODE_INIT_ABSTRACT_CLASS(className, parentClass, parentPrintClass) \
420 \
421 SO_NODE_INIT_ABSTRACT_CLASS_INTERNAL(className,parentClass,parentPrintClass)
422
427#define SO_NODE_CONSTRUCTOR(className) \
428 SoBaseInitializer sbi(this); \
429 classMutex.lock(); \
430 SO__NODE_CHECK_INIT(className); \
431 if (fieldData == NULL) \
432 fieldData = new SoFieldData(parentFieldData ? \
433 (SoFieldData *)*parentFieldData : \
434 (SoFieldData *)NULL); \
435 else \
436 firstInstance = FALSE; \
437 classMutex.unlock();
438
439
443#define SO_NODE_IS_FIRST_INSTANCE() \
444 \
445 (firstInstance == TRUE)
446
447
448
464#if defined(_DEBUG)
465// In fact it is allowed to initialize a MField with a single value with this macro...
466#define CHECK_FIELD_INIT(fieldName) /*\
467 if ( dynamic_cast<SoMField*>(&this->fieldName) != NULL) \
468 SoDebugError::post("SO_NODE_ADD_FIELD","Used for a SoMField.")*/
469
470#define CHECK_MFIELD_INIT(fieldName) \
471 if ( dynamic_cast<SoSField*>(&this->fieldName) != NULL) \
472 SoDebugError::post("SO_NODE_ADD_MFIELD","Used for a SoSFField.")
473#else
474#define CHECK_FIELD_INIT(fieldName)
475#define CHECK_MFIELD_INIT(fieldName)
476#endif
477
478#define SO_NODE_ADD_FIELD(fieldName,defValue) { \
479 classMutex.lock(); \
480 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
481 if (firstInstance) \
482 fieldData->addField(this, SO__QUOTE(fieldName), \
483 &this->fieldName); \
484 this->fieldName.setValue defValue; \
485 this->fieldName.setContainer(this); \
486 this->fieldName.setFieldType(SoField::EXPOSED_FIELD); \
487 CHECK_FIELD_INIT(fieldName); \
488 classMutex.unlock(); \
489}
490
492// Same as above but the fieldName is chosen by
493// the user
494//
495
496#define SO_NODE_ADD_NAMED_FIELD(fieldName,memberName,defValue) { \
497 classMutex.lock(); \
498 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
499 if (firstInstance) \
500 fieldData->addField(this, SO__QUOTE(fieldName), \
501 &this->memberName); \
502 this->memberName.setValue defValue; \
503 this->memberName.setContainer(this); \
504 this->memberName.setFieldType(SoField::EXPOSED_FIELD); \
505 classMutex.unlock(); \
506}
507
509//
510// This adds the info for a multifield to the SoFieldData.
511// The multifield is left empty.
512// The parameter is as follows:
513// fieldName: the name of the field (as a member)
514//
515// For example,
516//
517// SO_NODE_ADD_MFIELD(ambientColor)
518// SO_NODE_ADD_MFIELD(shininess)
519//
520// adds info about fields named ambientColor and shininess with the
521// given default values.
522//
523
524#define SO_NODE_ADD_MFIELD(fieldName) { \
525 classMutex.lock(); \
526 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
527 if (firstInstance) \
528 fieldData->addField(this, SO__QUOTE(fieldName), \
529 &this->fieldName); \
530 this->fieldName.setContainer(this); \
531 this->fieldName.setFieldType(SoField::EXPOSED_FIELD); \
532 CHECK_MFIELD_INIT(fieldName); \
533 classMutex.unlock(); \
534}
535
537//
538// This adds the info for a field to the SoFieldData and sets the
539// default value for it. The parameters are as follows:
540// fieldName: the name of the field (as a member)
541// defValue: the default value enclosed in parentheses
542//
543// For example,
544//
545// SO_NODE_ADD_PRIVATEFIELD(ambientColor, (0.2, 0.2, 0.2));
546// SO_NODE_ADD_PRIVATEFIELD(shininess, (0.0));
547//
548// adds info about fields named ambientColor and shininess with the
549// given default values.
550//
551
552#define SO_NODE_ADD_PRIVATEFIELD(fieldName,defValue) { \
553 classMutex.lock(); \
554 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
555 if (firstInstance) \
556 fieldData->addField(this, SO__QUOTE(fieldName), &this->fieldName); \
557 this->fieldName.setValue defValue; \
558 this->fieldName.setContainer(this); \
559 this->fieldName.setFieldType(SoField::HIDDEN_FIELD); \
560 classMutex.unlock(); \
561}
562
564//
565// This adds the info for a field to the SoFieldData and sets the
566// default value for it. The parameters are as follows:
567// fieldName: the name of the field (as a member)
568// defValue: the default value enclosed in parentheses
569//
570// For example,
571//
572// SO_NODE_ADD_PRIVATEMFIELD(ambientColor);
573// SO_NODE_ADD_PRIVATEMFIELD(shininess);
574//
575// adds info about fields named ambientColor and shininess with the
576// given default values.
577//
578
579#define SO_NODE_ADD_PRIVATEMFIELD(fieldName) { \
580 classMutex.lock(); \
581 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
582 if (firstInstance) \
583 fieldData->addField(this, SO__QUOTE(fieldName), \
584 &this->fieldName); \
585 this->fieldName.setContainer(this); \
586 this->fieldName.setFieldType(SoField::HIDDEN_FIELD); \
587 classMutex.unlock(); \
588}
589
591//
592// This adds the info for an exposedField to the SoFieldData and sets the
593// default value for it. The parameters are as follows:
594// fieldName: the name of the exposedField (as a member)
595// defValue: the default value enclosed in parentheses
596// Exposed fields are in the nodes. If a field is an exposedField
597// there is a corresponding eventIn and eventOut for the field. For
598// examples, if the exposedField is foo, there is a set_foo eventIn and
599// a foo_changed eventOut.
600//
601// For example,
602//
603// SO_NODE_ADD_EXPOSEDFIELD(ambientIntensity, (0));
604//
605// adds info about the exposedField named ambientIntensity with the
606// given default values.
607//
608
609#define SO_NODE_ADD_EXPOSEDFIELD(fieldName,defValue) { \
610 classMutex.lock(); \
611 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
612 if (firstInstance) \
613 fieldData->addField(this, SO__QUOTE(fieldName), \
614 &this->fieldName); \
615 this->fieldName.setValue defValue; \
616 this->fieldName.setContainer(this); \
617 this->fieldName.setFieldType(SoField::EXPOSED_FIELD); \
618 classMutex.unlock(); \
619}
620
622//
623// This adds the info for an eventIn field to the SoFieldData
624// The parameter is:
625// fieldName: the name of the eventIn field (as a member)
626//
627// For example,
628//
629// SO_NODE_ADD_EVENTIN(set_fraction);
630//
631// adds info about the eventIn set_fraction
632//
633
634#define SO_NODE_ADD_EVENTIN(fieldName) { \
635 classMutex.lock(); \
636 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
637 if (firstInstance) \
638 fieldData->addField(this, SO__QUOTE(fieldName), \
639 &this->fieldName); \
640 this->fieldName.setContainer(this); \
641 this->fieldName.setFieldType(SoField::EVENTIN_FIELD); \
642 classMutex.unlock(); \
643}
644
646//
647// This adds the info for an eventOut field to the SoFieldData
648// The parameter is:
649// fieldName: the name of the eventOut field (as a member)
650//
651// For example,
652//
653// SO_NODE_ADD_EVENTOUT(value_changed, defValue);
654//
655// adds info about the eventOut value_changed
656//
657
658#define SO_NODE_ADD_EVENTOUT(fieldName, defValue) { \
659 classMutex.lock(); \
660 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
661 if (firstInstance) \
662 fieldData->addField(this, SO__QUOTE(fieldName), \
663 &this->fieldName); \
664 this->fieldName.setValue defValue; \
665 this->fieldName.setContainer(this); \
666 this->fieldName.setFieldType(SoField::EVENTOUT_FIELD); \
667 classMutex.unlock(); \
668}
669
671//
672// This adds the info for a hidden field to the SoFieldData
673// The parameter is:
674// fieldName: the name of the hidden field (as a member)
675//
676// For example,
677//
678// SO_NODE_ADD_HIDDEN_FIELD(timeIn, defValue);
679//
680// adds info about the hidden field timeIn
681//
682
683#define SO_NODE_ADD_HIDDEN_FIELD(fieldName, defValue) { \
684 classMutex.lock(); \
685 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
686 if (firstInstance) \
687 fieldData->addField(this, SO__QUOTE(fieldName), \
688 &this->fieldName); \
689 this->fieldName.setValue defValue; \
690 this->fieldName.setContainer(this); \
691 this->fieldName.setFieldType(SoField::INTERNAL_FIELD); \
692 classMutex.unlock(); \
693}
694
696//
697// This adds the info for a field with an eventIn to the SoFieldData
698// The parameter is:
699// fieldName: the name of the eventIn and field (as a member)
700//
701// For example,
702//
703// SO_NODE_ADD_FIELD_EVENTIN(colorIndex, 0);
704//
705
706#define SO_NODE_ADD_FIELD_EVENTIN(fieldName, defValue) { \
707 classMutex.lock(); \
708 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
709 if (firstInstance) \
710 fieldData->addField(this, SO__QUOTE(fieldName), \
711 &this->fieldName); \
712 this->fieldName.setValue defValue; \
713 this->fieldName.setContainer(this); \
714 this->fieldName.setFieldType(SoField::FIELD_EVENTIN_FIELD); \
715 classMutex.unlock(); \
716}
717
719//
720// This registers a value of an enum type.
721// enumType: the name of the enum type
722// enumValue: the name of a value of that enum type
723//
724// If a node defines an enum, each of the enum's values
725// should be registered using this macro. For example:
726//
727// [ in MyNode.h file: ]
728// class MyNode {
729// ...
730// enum Chipmunk { ALVIN, SIMON, THEODORE };
731// ...
732// }
733//
734// [ in constructor MyNode::MyNode(): ]
735// SO_NODE_DEFINE_ENUM_VALUE(Chipmunk, ALVIN);
736// SO_NODE_DEFINE_ENUM_VALUE(Chipmunk, SIMON);
737// SO_NODE_DEFINE_ENUM_VALUE(Chipmunk, THEODORE);
738//
739
740#define SO_NODE_DEFINE_ENUM_VALUE(enumType,enumValue) { \
741 classMutex.lock(); \
742 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
743 if (firstInstance) \
744 fieldData->addEnumValue(SO__QUOTE(enumType), \
745 SO__QUOTE(enumValue), \
746 enumValue); \
747 classMutex.unlock(); \
748}
749
751//
752// Variant of previous macro. Allows to define a enum with
753// values that are holds by an external class.
754// This registers a value of an enum type.
755// enumType: the name of the enum type
756// enumValueName: the name of a value of that enum type
757// enumValue: the enum value
758//
759// If a node defines an enum, each of the enum's values
760// should be registered using this macro. For example:
761//
762// [ in MyClassWithEnumValues.h file: ]
763// class MyClassWithEnumValues {
764// ...
765// enum Chipmunk { ALVIN, SIMON, THEODORE };
766// ...
767// };
768//
769// [ in constructor MyNode::MyNode(): ]
770// SO_NODE_DEFINE_ENUM_VALUE(Chipmunk, ALVIN, MyClassWithEnumValues::ALVIN);
771// SO_NODE_DEFINE_ENUM_VALUE(Chipmunk, SIMON, MyClassWithEnumValues::SIMON);
772// SO_NODE_DEFINE_ENUM_VALUE(Chipmunk, THEODORE, MyClassWithEnumValues::THEODORE);
773//
774#define SO__NODE_DEFINE_ENUM_VALUE(enumType,enumValueName,enumValue) { \
775 classMutex.lock(); \
776 SO__NODE_CHECK_CONSTRUCT(__FILE__); \
777 if (firstInstance) \
778 fieldData->addEnumValue(SO__QUOTE(enumType), \
779 enumValueName, \
780 enumValue); \
781 classMutex.unlock(); \
782}
783
784#endif /* _SO_SUB_NODE_ */
785
SoFieldData(const SoFieldData *)
virtual const SbRenderEngineMode & getRenderEngineMode() const
Definition SoSubNode.h:127
static SbRenderEngineMode & getClassRenderEngineMode()
Returns the Render engine mode supported for this class.
Definition SoSubNode.h:131
<a href="IconLegend.html"><img src="extTGS.gif" alt="VSG extension" border="0"></a> Render engine mo...
<a href="IconLegend.html"><img src="extTGS.gif" alt="VSG extension" border="0"></a> Portable mutex c...
Stores runtime type information.
Definition SoType.h:98
int SbBool
Boolean type.
Definition SbBase.h:87