Open Inventor Release 2024.1.0
 
Loading...
Searching...
No Matches
SoSubKit.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 Isaacs (MMM yyyy)
25** Modified by : Paul S. Strauss (MMM yyyy)
26**=======================================================================*/
27/*=======================================================================
28 *** THE CONTENT OF THIS WORK IS PROPRIETARY TO FEI S.A.S, (FEI S.A.S.), ***
29 *** AND IS DISTRIBUTED UNDER A LICENSE AGREEMENT. ***
30 *** ***
31 *** REPRODUCTION, DISCLOSURE, OR USE, IN WHOLE OR IN PART, OTHER THAN AS ***
32 *** SPECIFIED IN THE LICENSE ARE NOT TO BE UNDERTAKEN EXCEPT WITH PRIOR ***
33 *** WRITTEN AUTHORIZATION OF FEI S.A.S. ***
34 *** ***
35 *** RESTRICTED RIGHTS LEGEND ***
36 *** USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT OF THE CONTENT OF THIS ***
37 *** WORK OR RELATED DOCUMENTATION IS SUBJECT TO RESTRICTIONS AS SET FORTH IN ***
38 *** SUBPARAGRAPH (C)(1) OF THE COMMERCIAL COMPUTER SOFTWARE RESTRICTED RIGHT ***
39 *** CLAUSE AT FAR 52.227-19 OR SUBPARAGRAPH (C)(1)(II) OF THE RIGHTS IN ***
40 *** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 52.227-7013. ***
41 *** ***
42 *** COPYRIGHT (C) 1996-2014 BY FEI S.A.S, ***
43 *** BORDEAUX, FRANCE ***
44 *** ALL RIGHTS RESERVED ***
45**=======================================================================*/
46/*=======================================================================
47** Modified by : VSG (MMM YYYY)
48**=======================================================================*/
49
50
51// There is a cycle of include files between SoBaseKit.h and SoSubKit.h
52// SoBaseKit.h must be included before _SO_SUB_KIT_ is defined. Otherwise,
53// SoBaseKit.h will not compile.
55
56#ifndef _SO_SUB_KIT_
57#define _SO_SUB_KIT_
58
59
64
66//
67// Macros to be called within the class definition header for a SoBaseKit
68// subclass:
69//
70
72//
73// This defines a catalog describing the arrangement
74// of the subgraph for instances of this class
75//
76
77#define SO__KIT_CATALOG_HEADER(className) \
78 private: \
79 /* design of this class */ \
80 static SoNodekitCatalog *nodekitCatalog; \
81 /* parent design */ \
82 static const SoNodekitCatalog **parentNodekitCatalogPtr; \
83 public: \
84 \
85 static const SoNodekitCatalog *getClassNodekitCatalog(); \
86 \
87 virtual const SoNodekitCatalog *getNodekitCatalog() const; \
88 private: \
89 static const SoNodekitCatalog **getClassNodekitCatalogPtr()
90
91#define SO_KIT_HEADER(className) \
92 SO_NODE_HEADER(className); \
93 SO__KIT_CATALOG_HEADER(className)
94
95#define SO_KIT_ABSTRACT_HEADER(className) \
96 SO_NODE_ABSTRACT_HEADER(className); \
97 SO__KIT_CATALOG_HEADER(className)
98
99
101//
102// This defines an SoSFNode field for the catalog part given.
103// The field will always be a (protected) node-pointer field.
104// It will keep track of which (hidden) child is which part.
105//
106
107#define SO_KIT_CATALOG_ENTRY_HEADER(partName) \
108 private: \
109 SoSFNode partName
110
111
113//
114// Macros to be called within the source file for a node subclass:
115//
116
118//
119// This declares the static variables defined in SO__KIT_CATALOG_HEADER.
120//
121
122#define SO__KIT_CATALOG_VARS(className) \
123SoNodekitCatalog *className::nodekitCatalog = NULL; \
124const SoNodekitCatalog **className::parentNodekitCatalogPtr = NULL
125
127//
128// This implements the methods defined in SO__KIT_CATALOG_HEADER.
129//
130
131#define SO__KIT_CATALOG_METHODS(className) \
132const SoNodekitCatalog * \
133className::getNodekitCatalog() const \
134{ \
135 return nodekitCatalog; \
136} \
137 \
138const SoNodekitCatalog * \
139className::getClassNodekitCatalog() \
140{ \
141 return nodekitCatalog; \
142} \
143 \
144const SoNodekitCatalog ** \
145className::getClassNodekitCatalogPtr() \
146{ \
147 return (const SoNodekitCatalog **)&nodekitCatalog; \
148}
149
150
152//
153// These include all the definitions required
154// at file scope
155//
156
157#define SO_KIT_SOURCE(className) \
158 SO_NODE_SOURCE(className) \
159 SO__KIT_CATALOG_VARS(className); \
160 SO__KIT_CATALOG_METHODS(className)
161
162#define SO_KIT_ABSTRACT_SOURCE(className) \
163 SO_NODE_ABSTRACT_SOURCE(className); \
164 SO__KIT_CATALOG_VARS(className); \
165 SO__KIT_CATALOG_METHODS(className)
166
168//
169// Internal initialization macros
170//
171#define SO__KIT_INIT_CLASS(className,classPrintName,parentClass) \
172 SO__NODE_INIT_CLASS(className,classPrintName,parentClass); \
173 parentNodekitCatalogPtr = parentClass::getClassNodekitCatalogPtr()
174
175#define SO__KIT_INIT_ABSTRACT_CLASS(className,classPrintName,parentClass) \
176 SO__NODE_INIT_ABSTRACT_CLASS(className,classPrintName,parentClass); \
177 parentNodekitCatalogPtr = parentClass::getClassNodekitCatalogPtr()
178
179#define SO__KIT_EXIT_CLASS(className) \
180 SO__NODE_EXIT_CLASS(className); \
181 delete nodekitCatalog; nodekitCatalog = NULL;
182
184//
185// This calls SO_NODE_INIT_CLASS to initialize the type
186// identifier variables defined in SO_KIT_HEADER.
187// It should be called from within initClass().
188// The parentClass argument should be the class that this
189// subclass is derived from.
190// The parentNodekitCatalogPtr is also initialized here.
191//
192
193#define SO_KIT_INIT_CLASS(className,parentClass,parentPrintClass) \
194 SO_NODE_INIT_CLASS(className,parentClass,parentPrintClass); \
195 parentNodekitCatalogPtr = parentClass::getClassNodekitCatalogPtr()
196
197#define SO_KIT_INIT_ABSTRACT_CLASS(className,parentClass,parentPrintClass) \
198 SO_NODE_INIT_ABSTRACT_CLASS(className,parentClass,parentPrintClass); \
199 parentNodekitCatalogPtr = parentClass::getClassNodekitCatalogPtr()
200
202//
203// This is an internal macro.
204// It initializes the SoNodekitCatalog structure defined in
205// SO__KIT_CATALOG_HEADER. This macro is automatically called as
206// part of SO_KIT_CONSTRUCTOR
207//
208// This and other macros rely on static member variable "firstInstance"
209// from SoSubNode.h
210//
211
212#define SO__KIT_INHERIT_CATALOG(className) \
213 /* get a copy of the catalog from the base class */ \
214 if (firstInstance) \
215 { \
216 if (parentNodekitCatalogPtr == NULL) /* only true in SoBaseKit */ \
217 nodekitCatalog = new SoNodekitCatalog; \
218 else \
219 nodekitCatalog = (*parentNodekitCatalogPtr)->clone(SoType::fromName(SO__QUOTE(className))); \
220 }
221
223//
224// These are here to complete the set of subclassing macros for nodekits.
225// They are just stubs to call the SO_NODE equivalents, really.
226
227#define SO_KIT_CONSTRUCTOR(className) \
228 SO_NODE_CONSTRUCTOR(className); \
229 SO__KIT_INHERIT_CATALOG(className)
230
231#define SO_KIT_IS_FIRST_INSTANCE() \
232 SO_NODE_IS_FIRST_INSTANCE()
233
234#define SO_KIT_ADD_FIELD(fieldName,defValue) \
235 SO_NODE_ADD_FIELD(fieldName,defValue)
236
237#define SO_KIT_DEFINE_ENUM_VALUE(enumType,enumValue) \
238 SO_NODE_DEFINE_ENUM_VALUE(enumType,enumValue)
239
240#define SO_KIT_SET_MF_ENUM_TYPE(fieldName, enumType) \
241 SO_NODE_SET_MF_ENUM_TYPE(fieldName, enumType)
242
243#define SO_KIT_SET_SF_ENUM_TYPE(fieldName, enumType) \
244 SO_NODE_SET_SF_ENUM_TYPE(fieldName, enumType)
245
247//
248// This adds the info for a single new part to the SoNodekitCatalog.
249// The parameters are as follows:
250//
251// partName: the name used to refer to this part in nodekitCatalog
252// NOTE: do not make an entry for 'this'.
253// 'this' is implicitly the top of the tree when
254// building the catalog.
255// partClassName: the class of node to which this part belongs.
256//
257// nullByDefault: If TRUE, the part is not created during the constructor.
258// (which is the usual case.)
259// If FALSE, then it will be automatically created by the
260// constructor during the call to the
261// macro SO_KIT_INIT_INSTANCE()
262//
263// parentName: the partName of the parent of this part within
264// the nodekitCatalog
265// NOTE: if this node is to be a direct descendant of
266// 'this', then parentName should be given as "this"
267//
268// rightName: the partName of the right sibling of this part
269// within the nodekitCatalog.
270// NOTE: if this part is to be the rightmost child, then
271// the rightName should be given as "" (the empty string).
272//
273// isPublicPart: can a user receive a pointer to this part through
274// getPart? If a part is not a leaf, this property is
275// irrelevant (non-leaf parts are always private ). But if
276// it is a leaf, the user's access can be stopped through
277// this field.
278//
279// For example,
280//
281// SO_KIT_ADD_CATALOG_ENTRY(material,SoMaterial,TRUE,this,, TRUE);
282//
283// adds to the catalog a part named 'material.' This part will be an
284// SoMaterial node that is NOT created by default. It will be a direct
285// child of the nodekit part 'this.' It will be installed as the
286// rightmost child below 'this'.
287// Since it is public, a user will be able to receive a pointer to this
288// part by calling getPart().
289//
290// Another example:
291// if we are making a catalog for a class SoBirdKit, and we have already
292// created the class SoWingKit, then the following macros:
293// SO_KIT_ADD_CATALOG_ENTRY(mainSep,SoSeparator,TRUE,this,, FALSE);
294// SO_KIT_ADD_CATALOG_ENTRY(rightW,SoWingKit,TRUE,mainSep,, TRUE);
295// SO_KIT_ADD_CATALOG_ENTRY(leftW,SoWingKit,TRUE,mainSep,rightWing, TRUE);
296// describe a catalog with this structure:
297//
298// this
299// |
300// mainSep
301// |
302// -------------
303// | |
304// leftW rightW
305
306#define SO_KIT_ADD_CATALOG_ENTRY(partName, partClassName, nullByDefault, parentName, rightName, isPublicPart) \
307 SO_KIT_ADD_FIELD(partName,(NULL)); \
308 if (firstInstance && !nodekitCatalog->addEntry(SO__QUOTE(partName), \
309 SoType::fromName(SO__QUOTE(partClassName)), \
310 SoType::fromName(SO__QUOTE(partClassName)), nullByDefault,\
311 SO__QUOTE(parentName), \
312 SO__QUOTE(rightName), FALSE, SoType::badType(), \
313 SoType::badType(), isPublicPart )) \
314 catalogError()
315
316
318//
319// This adds the info for a new part to the SoNodekitCatalog.
320// 'partName' may be of an abstract node type.
321//
322// The parameters are as follows:
323//
324// partName: same as SO_KIT_ADD_CATALOG_ENTRY
325// partClassName: same as SO_KIT_ADD_CATALOG_ENTRY, except that
326// abstract node classes are acceptable.
327//
328// defaultPartClassName: If the nodekit is asked to construct this part,
329// using getPart, then the 'defaultPartClassName' will
330// specify what type of node to build.
331// This may NOT be an abstract class.
332// This MUST be a subclass of 'partClassName'
333//
334// nullByDefault: same as SO_KIT_ADD_CATALOG_ENTRY
335// parentName: same as SO_KIT_ADD_CATALOG_ENTRY
336// rightName: same as SO_KIT_ADD_CATALOG_ENTRY
337// isPublicPart: same as SO_KIT_ADD_CATALOG_ENTRY
338//
339// For example,
340//
341// SO_KIT_ADD_CATALOG_ABSTRACT_ENTRY(light,SoLight, SoDirectionalLight,
342// TRUE, this,, TRUE);
343//
344// makes a part node refered to as "light".
345// When calling setPart, any node that is a subclass of light can be
346// used (e.g., SoDirectionalLight, SoSpotLight, SoPointLight )
347// However, if the user asks for the node and it has not been created yet,
348// (this happens, for example, in the case where there is currently
349// no 'light' and the user calls
350// SO_GET_PART( myKit, "light", SoLight ),
351// then an SoDirectionalLight will be created and returned.
352//
353
354#define SO_KIT_ADD_CATALOG_ABSTRACT_ENTRY(partName, partClassName, \
355 defaultPartClassName, nullByDefault, parentName, \
356 rightName, isPublicPart ) \
357 SO_KIT_ADD_FIELD(partName,(NULL)); \
358 if (firstInstance && !nodekitCatalog->addEntry(SO__QUOTE(partName), \
359 SoType::fromName(SO__QUOTE(partClassName)), \
360 SoType::fromName(SO__QUOTE(defaultPartClassName)), nullByDefault,\
361 SO__QUOTE(parentName), SO__QUOTE(rightName), FALSE, \
362 SoType::badType(), SoType::badType(), isPublicPart )) \
363 catalogError()
364
366//
367// This adds the info for a new part to the SoNodekitCatalog.
368// 'partName' refers to a part that is a LIST.
369//
370// Any list in a nodekit will automatically be a node of type SoNodeKitListPart.
371// These nodes act like subclasses of group but enforce type checking when
372// you add children to them.
373//
374// The parameters you specify will determine
375// [a] what kind of group node holds the children (SoGroup, SoSeparator,
376// SoSwitch, etc).
377// [b] what single class of node will be allowable as children in the list.
378//
379// Subsequent calls to SO_KIT_ADD_LIST_ITEM_TYPE allow you to add other classes
380// of nodes that will be allowable children for the list.
381//
382// The parameters are as follows:
383//
384// partName: Same as in SO_KIT_ADD_CATALOG_ENTRY
385// listContainerClassName:
386// What class will be used to hold the children in the list?
387// NOTE: since this is going to have children, it MUST
388// be a subclass of SoGroup, such as SoSeparator
389// or SoSwitch.
390// nullByDefault:same as SO_KIT_ADD_CATALOG_ENTRY
391// parentName: Same as in SO_KIT_ADD_CATALOG_ENTRY
392// rightName: Same as in SO_KIT_ADD_CATALOG_ENTRY
393//
394// listItemClassName: The name of the class of node that may appear in
395// the list. Any node class is legal here.
396// isPublicPart: Same as in SO_KIT_ADD_CATALOG_ENTRY
397//
398// For example,
399//
400// SO_KIT_ADD_CATALOG_LIST_ENTRY(subCubes,SoSeparator,TRUE,this,,SoCube, TRUE );
401//
402// makes a list that may contain only SoCubes. An SoSeparator will be used to
403// contain this list of cubes.
404
405#define SO_KIT_ADD_CATALOG_LIST_ENTRY(partName, listContainerClassName,nullByDefault, parentName, rightName, listItemClassName, isPublicPart ) \
406 SO_KIT_ADD_FIELD(partName,(NULL)); \
407 if (firstInstance && !nodekitCatalog->addEntry(SO__QUOTE(partName), \
408 SoNodeKitListPart::getClassTypeId(), \
409 SoNodeKitListPart::getClassTypeId(), nullByDefault, \
410 SO__QUOTE(parentName), SO__QUOTE(rightName), TRUE, \
411 SoType::fromName(SO__QUOTE(listContainerClassName)), \
412 SoType::fromName(SO__QUOTE(listItemClassName)), isPublicPart)) \
413 catalogError()
414
416//
417// Assuming that the part 'partName' was already put in the nodekit catalog,
418// using the macro SO_KIT_ADD_CATALOG_LIST_ENTRY(...)
419// this macro will add 'newListItemClassName' to its listItemTypes.
420//
421// This means that nodes of type 'newListItemClassName' will be permitted
422// in the list, as well as any other parts that are already permitted.
423//
424// Example:
425// The macro:
426// SO_KIT_ADD_CATALOG_LIST_ENTRY(myList, SoSeparator, TRUE,
427// myListParent, , SoCube, TRUE )
428// creates a list called "myList" that accepts cubes.
429// calling:
430// myKit->addChild( "myList", myCube );
431// will work just fine, but:
432// myKit->addChild( "myList", mySphere );
433// will produce an error.
434// If, however, a subsequent call is made to:
435// SO_KIT_ADD_LIST_ITEM_TYPE( myList, SoSphere );
436// then both calls to addChild will be acceptable
437//
438// partName: Name of the part to add the listItemType to
439// newListItemClassName: Name of the class to add to partName's listItemTypes
440
441#define SO_KIT_ADD_LIST_ITEM_TYPE(partName, newListItemClassName ) \
442 if (firstInstance) nodekitCatalog->addListItemType(SO__QUOTE(partName), \
443 SoType::fromName(SO__QUOTE(newListItemClassName)) )
444
446//
447// This changes the class of a part in the nodekit catalog.
448// Both the newPartClassname and the newDefaultPartClassName must be given.
449//
450// Used when creating catalogs for subclasses of other nodekits.
451//
452// The parameters are as follows:
453//
454// partName: Same as SO_KIT_ADD_CATALOG_ENTRY
455//
456// newPartClassName: The name of the new node class describing this part.
457//
458// newDefaultPartClassName:
459// The new defaultPartClassName. If asked to build a
460// new node for this part, a node of type
461// newDefaultPartClassName will be built.
462// For example,
463//
464// The part "shape" is entered in the nodekit catalog as a part for
465// the SoShapeKit using the following macro call in the constructor:
466//
467// SO_KIT_ADD_CATALOG_ABSTRACT_ENTRY(shape, SoShape, SoCube, FALSE,
468// shapeSeparator, , TRUE );
469//
470// If we created a subclass of SoShape, SoVertexShapeKit,
471// then the following command might be used in the SoVertexShapeKit constructor:
472//
473// SO_KIT_CHANGE_ENTRY_TYPE( shape, SoVertexShape, SoFaceSet );
474//
475// This would allow any subclass of SoVertexShape to be inserted as the part
476// "shape." If the SoVertexShapeKit were asked to build the part "shape", it
477// would create it as an SoFaceSet, the default (and non-abstract) type.
478//
479// Continuing further, the class SoFaceSetKit, subclassed from SoVertexShapeKit,
480// might contain this command in its constructor:
481//
482// SO_KIT_CHANGE_ENTRY_TYPE(shape,SoFaceSet, SoFaceSet );
483//
484// This class would allow one and only one type of node for "shape",
485// and that is the type SoFaceSet.
486
487#define SO_KIT_CHANGE_ENTRY_TYPE(partName, newPartClassName, \
488 newDefaultPartClassName) \
489 if (firstInstance) nodekitCatalog->narrowTypes(SO__QUOTE(partName), \
490 SoType::fromName(SO__QUOTE(newPartClassName)), \
491 SoType::fromName(SO__QUOTE(newDefaultPartClassName)))
492
494//
495// This changes whether or not a part is NULL by default.
496// If TRUE, the part is NULL by default.
497// If FALSE, the part is always created during the constructor for the
498// nodekit that uses this catalog. In this case, construction occurs
499// during the call to SO_KIT_INIT_INSTANCE().
500//
501#define SO_KIT_CHANGE_NULL_BY_DEFAULT(partName, newNullByDefault) \
502 if (firstInstance) nodekitCatalog->setNullByDefault(SO__QUOTE(partName), \
503 newNullByDefault)
504
506//
507// This must be called within the constructor of every class of nodekit.
508// It should be called immediately after the catalog is defined.
509//
510// It does 2 things:
511// [1] created the nodekitPartsList, which keeps track of which parts
512// have been created.
513// [2] creates all parts that must be created by default (such as the
514// cube in SoCubeKit) as specified by the nullByDefault parameter
515// in the nodekit catalog
516//
517#define SO_KIT_INIT_INSTANCE() \
518 createNodekitPartsList(); \
519 createDefaultParts()
520
521
522#endif /* _SO_SUB_KIT_ */
523
524