Open Inventor Reference
SoSubNode.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * Further, this software is distributed without any warranty that it is
16  * free of the rightful claim of any third person regarding infringement
17  * or the like. Any license provided herein, whether implied or
18  * otherwise, applies only to this software file. Patent licenses, if
19  * any, provided herein do not apply to combinations of this program with
20  * other software, or any other product whatsoever.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  *
26  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
27  * Mountain View, CA 94043, or:
28  *
29  * http://www.sgi.com
30  *
31  * For further information regarding this notice, see:
32  *
33  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
34  *
35  */
36 
37 
38 /*
39  * Copyright (C) 1990,91 Silicon Graphics, Inc.
40  *
41  _______________________________________________________________________
42  ______________ S I L I C O N G R A P H I C S I N C . ____________
43  |
44  | $Revision: 1.1.1.1 $
45  |
46  | Description:
47  | This file defines some macros that implement things common to
48  | many subclasses of SoNode. They may be used to make SoNode
49  | subclassing easier. In all of the macros, the "className"
50  | parameter refers to the name of the node subclass.
51  |
52  | Methods containing the word "ABSTRACT" are to be used for
53  | abstract subclasses in place of the corresponding regular
54  | macro. Note that abstract classes may not have fields (you
55  | cannot call ADD_FIELD in their constructor).
56  |
57  | Defined macros:
58  |
59  | Within class header:
60  |
61  | SO_NODE_HEADER(className)
62  | SO_NODE_ABSTRACT_HEADER(className)
63  |
64  | Within class source:
65  |
66  | At file scope:
67  |
68  | SO_NODE_SOURCE(className)
69  | SO_NODE_ABSTRACT_SOURCE(className)
70  |
71  | Class initialization (initClass):
72  |
73  | SO_NODE_INIT_CLASS()
74  | SO_NODE_INIT_ABSTRACT_CLASS()
75  |
76  | Constructor initialization:
77  |
78  | SO_NODE_CONSTRUCTOR(className)
79  | SO_NODE_ADD_FIELD(fieldMember,(defaultValue))
80  | SO_NODE_DEFINE_ENUM_VALUE(enumType,enumValue)
81  | SO_NODE_IS_FIRST_INSTANCE() //!< a boolean value
82  |
83  | //!< the following are defined in <fields/So[SM]fEnum.h>:
84  | SO_NODE_SET_SF_ENUM_TYPE(fieldName,enumType)
85  | SO_NODE_SET_MF_ENUM_TYPE(fieldName,enumType)
86  |
87  | Author(s) : Paul S. Strauss, Gavin Bell, Ronen Barzel
88  |
89  ______________ S I L I C O N G R A P H I C S I N C . ____________
90  _______________________________________________________________________
91  */
92 
93 #ifndef _SO_SUB_NODE_
94 #define _SO_SUB_NODE_
95 
96 #include <stdlib.h>
100 #include <Inventor/nodes/SoNode.h>
101 
102 
106 
111 #ifdef DEBUG
112 #define SO__NODE_CHECK_INIT(className) { \
113  if (classTypeId == SoType::badType()) { \
114  SoDebugError::post("SO_NODE_CONSTRUCTOR", \
115  "Can't construct a node of type " \
116  SO__QUOTE(className) \
117  " until initClass() has been called"); \
118  return; \
119  } \
120 }
121 
122 #define SO__NODE_CHECK_CONSTRUCT(where) { \
123  if (fieldData == NULL) { \
124  SoDebugError::post(where, \
125  "Instance not properly constructed.\n" \
126  "Did you forget to put SO_NODE_CONSTRUCTOR()" \
127  " in the constructor?"); \
128  fieldData = new \
129  SoFieldData(parentFieldData ? *parentFieldData : NULL); \
130  } \
131 }
132 
133 #else
134 #define SO__NODE_CHECK_INIT(className) { }
135 #define SO__NODE_CHECK_CONSTRUCT(where) { }
136 #endif
137 
143 
149 
150 #define SO_NODE_ABSTRACT_HEADER(className) \
151  public: \
152  typedef className InventorThisClass; \
153  static SoType getClassTypeId() /* Returns class type id */ \
154  { return classTypeId; } \
155  virtual SoType getTypeId() const; /* Returns type id */ \
156  protected: \
157  virtual const SoFieldData *getFieldData() const; \
158  static const SoFieldData **getFieldDataPtr() \
159  { return const_cast<const SoFieldData **>(&fieldData); } \
160  private: \
161  static SoType classTypeId; /* Type id */ \
162  static bool firstInstance; /* true until 2nd c'tor call */ \
163  static SoFieldData *fieldData; \
164  static const SoFieldData **parentFieldData
165 
170 #define SO_NODE_HEADER(className) \
171  SO_NODE_ABSTRACT_HEADER(className); \
172  static void *createInstance()
173 
178 
184 
185 #define SO__NODE_ABSTRACT_VARS(className) \
186  SoType className::classTypeId; \
187  SoFieldData *className::fieldData; \
188  const SoFieldData **className::parentFieldData; \
189  bool className::firstInstance = TRUE
190 
194 #define SO__NODE_VARS(className) \
195  SO__NODE_ABSTRACT_VARS(className)
196 
201 
202 #define SO__NODE_ABSTRACT_METHODS(className) \
203  \
204  SoType \
205  className::getTypeId() const \
206  { \
207  return classTypeId; \
208  } \
209  \
210  const SoFieldData * \
211  className::getFieldData() const \
212  { \
213  SO__NODE_CHECK_CONSTRUCT(SO__QUOTE(className)); \
214  return fieldData; \
215  }
216 
222 
223 #define SO__NODE_METHODS(className) \
224  \
225  SO__NODE_ABSTRACT_METHODS(className) \
226  \
227  void * \
228  className::createInstance() \
229  { \
230  return static_cast<void *>(new className); \
231  }
232 
233 
239 
240 #define SO_NODE_SOURCE(className) \
241  SO__NODE_VARS(className); \
242  SO__NODE_METHODS(className)
243 
244 #define SO_NODE_ABSTRACT_SOURCE(className) \
245  SO__NODE_ABSTRACT_VARS(className); \
246  SO__NODE_ABSTRACT_METHODS(className)
247 
248 
253 
254 #define SO__NODE_INIT_CLASS(className,classPrintName,parentClass) { \
255  if ((SoNode::nextActionMethodIndex < 0) || \
256  (SoNode::nextActionMethodIndex > 32767)){ \
257  SoDebugError::post("SO__NODE_INIT_CLASS", \
258  "Overflow of SoNode::nextActionMethodIndex"); \
259  abort(); \
260  } \
261  classTypeId = \
262  SoType::createType(parentClass::getClassTypeId(), \
263  classPrintName, \
264  &className::createInstance, \
265  static_cast<short>(SoNode::nextActionMethodIndex++)); \
266  parentFieldData = parentClass::getFieldDataPtr(); \
267 }
268 
269 #define SO__NODE_INIT_ABSTRACT_CLASS(className,classPrintName,parentClass) { \
270  if ((SoNode::nextActionMethodIndex < 0) || \
271  (SoNode::nextActionMethodIndex > 32767)){ \
272  SoDebugError::post("SO__NODE_INIT_ABSTRACT_CLASS", \
273  "Overflow of SoNode::nextActionMethodIndex"); \
274  abort(); \
275  } \
276  classTypeId = \
277  SoType::createType(parentClass::getClassTypeId(), \
278  classPrintName, \
279  NULL, \
280  static_cast<short>(SoNode::nextActionMethodIndex++)); \
281  parentFieldData = parentClass::getFieldDataPtr(); \
282 }
283 
291 
292 #define SO_NODE_INIT_CLASS(className,parentClass,parentPrintClass) { \
293  if ((SoNode::nextActionMethodIndex < 0) || \
294  (SoNode::nextActionMethodIndex > 32767)){ \
295  SoDebugError::post("SO_NODE_INIT_CLASS", \
296  "Overflow of SoNode::nextActionMethodIndex"); \
297  abort(); \
298  } \
299  classTypeId = \
300  SoType::createType(SoType::fromName(parentPrintClass), \
301  SO__QUOTE(className), \
302  &className::createInstance, \
303  static_cast<short>(SoNode::nextActionMethodIndex++)); \
304  parentFieldData = parentClass::getFieldDataPtr(); \
305 }
306 
307 #define SO_NODE_INIT_ABSTRACT_CLASS(className, parentClass, parentPrintClass) { \
308  if ((SoNode::nextActionMethodIndex < 0) || \
309  (SoNode::nextActionMethodIndex > 32767)){ \
310  SoDebugError::post("SO_NODE_INIT_ABSTRACT_CLASS", \
311  "Overflow of SoNode::nextActionMethodIndex"); \
312  abort(); \
313  } \
314  classTypeId = \
315  SoType::createType(SoType::fromName(parentPrintClass), \
316  SO__QUOTE(className), \
317  NULL, \
318  static_cast<short>(SoNode::nextActionMethodIndex++)); \
319  parentFieldData = parentClass::getFieldDataPtr(); \
320 }
321 
327 
328 #define SO_NODE_CONSTRUCTOR(className) { \
329  SO__NODE_CHECK_INIT(className); \
330  if (fieldData == NULL) \
331  fieldData = new SoFieldData( \
332  parentFieldData ? *parentFieldData : NULL); \
333  else \
334  firstInstance = FALSE; \
335  isBuiltIn = FALSE; \
336 }
337 
343 
344 #define SO_NODE_IS_FIRST_INSTANCE() \
345  (firstInstance == TRUE)
346 
351 #define SO_NODE_ADD_REMOVED_FIELD(fieldName) {\
352  if (firstInstance) \
353  fieldData->addRemovedFieldName(SO__QUOTE(fieldName)); \
354  }
355 
371 
372 #define SO_NODE_ADD_FIELD(fieldName,defValue) { \
373  SO__NODE_CHECK_CONSTRUCT(__FILE__); \
374  if (firstInstance) \
375  fieldData->addField(this, SO__QUOTE(fieldName), \
376  &this->fieldName); \
377  this->fieldName.setValue defValue; \
378  this->fieldName.setContainer(this); \
379  }
380 
388 #define SO_NODE_ADD_ENUM_FIELD(field, type, defaultValue) \
389  SO_NODE_SET_SF_ENUM_TYPE(field, type);\
390  SO_NODE_ADD_FIELD(field, (defaultValue));
391 
413 
414 #define SO_NODE_DEFINE_ENUM_VALUE(enumType,enumValue) { \
415  SO__NODE_CHECK_CONSTRUCT(__FILE__); \
416  if (firstInstance) \
417  fieldData->addEnumValue(SO__QUOTE(enumType), \
418  SO__QUOTE(enumValue), \
419  enumValue); \
420  }
421 
446 
447 #define SO_NODE_DEFINE_ENUM_VALUE_NAMED(enumType,enumValue,enumValueName) { \
448  SO__NODE_CHECK_CONSTRUCT(__FILE__); \
449  if (firstInstance) \
450  fieldData->addEnumValue(SO__QUOTE(enumType), \
451  enumValueName, \
452  enumValue); \
453  }
454 
478 
479 #define SO_NODE_DEFINE_ENUM_VALUE_SCOPED(enumScope,enumType,enumValue) { \
480  SO__NODE_CHECK_CONSTRUCT(__FILE__); \
481  if (firstInstance) \
482  fieldData->addEnumValue(SO__QUOTE(enumScope) "::" SO__QUOTE(enumType),\
483  SO__QUOTE(enumValue), \
484  enumScope::enumValue); \
485  }
486 
487 
488 #endif /* _SO_SUB_NODE_ */
489