27 /*! \page PageSystemFieldsNFieldContainers Fields & Field Containers
31 /*! \page PageSystemFieldContainerExt Creating New FieldContainer Classes
35 /*! \page PageSystemFieldsNFieldContainers Fields & Field Containers
37 \latexonly Starter:NewChapter \endlatexonly
39 One central goal in OpenSG's design is easy to use thread-safe data. To do
40 that right, you need to replicate the data so that every thread can have its
41 private copy (called aspect) to work on. At some point these different copies
42 will have to be synchronized, and then the parts that actually changed need to
43 be copied from one aspect to another. To do that, the system needs to know
44 what actually changed. As C++ is not reflective, i.e. the classes cannot tell
45 the system which members they have, OpenSG needs to keep track of the changes.
46 That's what Fields and FieldContainers are for.
48 \section PageSystemFCInstance Creating a FieldContainer instance
50 FieldContainer can be created in two ways: By using the FieldContainerFactory
51 or from the class's prototype. You cannot create instances of FieldContainers
52 neither by creating automatic or static variables nor by calling new. You have
53 to use the mentioned two ways.
55 For generic loaders it is useful to create an object by name, and this is what
56 the factory is for. The factory is a singleton, the single instance can be
57 accessed via FieldContainerFactory::the(), which has functions to create
58 arbitrary field containers, with some special versions to directly create
59 different subsets of field containers (Nodes, NodeCores, Attachments).
61 Creating a new instance of a specific class is done by calling fcPtr
64 \section PageSystemRefCount Reference counting
66 FieldContainers are reference-counted. They are created with a reference count
67 of 0, and the reference count can be manipulated through addRefCP() and
70 The system increases the reference count only when it stores a reference to an
71 object in the system, e.g. when a node is attached to another node. It does
72 not increase the reference counter for every parameter that is passed around,
73 the pointers mentioned in [fcinstance] are not smart pointers.
75 The reference count is decreased when an object is removed from the system,
76 e.g. when a node is detached from another node, or explicitly using
77 subRefCP(). If the reference count goes to or below 0, the object is removed.
78 Note that objects are created with a reference count of zero, so if a new
79 object (refCnt: 0) is attached to a node (increasing the refCnt to 1) and
80 removed later on (decreasing it to 0), it will be destroyed. Increasing the
81 reference count before removing it is needed to prevent the destruction.
83 \section PageSystemFCManip Manipulation
85 The FieldContainer is the basic unit for multi-thread safety. To synchronize
86 changes between different copies of the data the system needs to know when and
89 This has to be done explicitly by the program. Thus, before changing a
90 FieldContainer beginEditCP(fcPtr, fieldMask); has to be called. After the
91 changes to the FieldContainer are done this also has to be communicated by
92 calling endEditCP(fcPtr, fieldMask);. Here, fcPtr is the pointer to the
93 FieldContainer being changed, fieldMask is a bit mask describing the fields
96 Every FieldContainer defines constants for all its fields that can be used to
97 set up this mask. The naming convention is
98 [FieldContainer]::[FieldName]FieldMask, e.g. Geometry::PositionsFieldMask.
99 These masks can be or-ed together to create the full mask of fields that are
102 To simplify the begin/endEdit sequences and make it easier to not forget closing
103 the edit (which can result in pretty surprising error) there is a helper class
106 The CPEditor is an equivalent to the std::auto_ptr in the sense that as it calls
107 the beginEdit as soon as it is created and calls the endEdit as soon as it goes
113 GeoPTypesPtr type = GeoPTypesUI8::create();
115 CPEditor te(type, GeoPTypesUI8::GeoPropDataFieldMask);
117 type->addValue(GL_POLYGON );
118 type->addValue(GL_TRIANGLES);
119 type->addValue(GL_QUADS );
128 \section PageSystemAttachments FieldContainer attachments
130 OpenSG field containers and nodes do not feature an unused pointer to attach
131 data, usually called user data in other systems. Instead, many field
132 containers feature a map to attach specific kinds of field containers called
133 attachments. The most important ones are Nodes and NodeCores, but many other
134 like Window, Viewport, Camera, etc. are derived from AttachmentContainer and,
135 therefore, can carry attachments.
137 Attachments have to be derived from Attachment (see
138 \ref PageSystemFieldContainerExt for
139 details on how to do that). There are also predefined attachments, right now the
140 only one is NameAttachment, which allows assigning a name to the field
143 Every AttachmentContainer can hold an arbitrary number of attachments.
144 Attachments are divided into separate groups, and there can be only one
145 attachment of every group attached to an AC. Most attachments are a group, but
146 if needed new ones can be used as replacements for their parents.
148 \section PageSystemFCThreadsafety Data separation & Thread safety
150 One of the primary design goals of OpenSG is supporting multi-threaded
151 applications. For asynchronous threads that means that every thread might need
152 its private copy of the data. To combine that with easy usability and
153 efficient access we decided to replicate at the field container level.
155 When a field container is created not only one instance is created but
156 multiple, per default 2. These are called aspects, and every running thread is
157 associated with one of them. Whenever data is changed in a thread, only the
158 aspect that's associated with it is changed, the rest is left as is.
162 #if defined(OSG_DO_DOC) || OSG_DOC_LEVEL > 1
164 /*! \page PageSystemFieldContainerExt Creating New FieldContainer Classes
166 Most developers who use OpenSG as a scene-graph library will probable never
167 create their own OpenSG FieldContainer classes. Similar to widget libs (e.g.
168 qt, gtk) people just use instances (the widgets) but never create new
171 However, you can always extend the type system of OpenSG to integrate new
172 cores (e.g. a fancy LOD switch) or application specific FieldContainers.
174 FieldContainers are the system's central mechanisms to deal with any kind of
175 thread safe data (see \ref PageSystemFieldsNFieldContainers). Therefore, the
176 class declaration must include various extra meta information for the field
177 and FieldContainer type handling.
179 In most systems (e.g. Inventor), you would probably start writing a new class
180 or node by just 'copy and paste'-ing an existing implementation. However,
181 since OpenSG needs all this extra meta data it is not a simple but very error
182 prone process to create the field container source by hand. Instead, we
183 provide a graphical tool to create and manage the FieldContainer description
186 The basic idea is that you use the 'field container description editor'
187 ($OSGROOT/Tools/fcdEdit) to create an XML file including the description of
188 your FieldContainer fields and interfaces.
190 The tool is also able to create all necessary C++ source files. The
191 FieldContainer code is split into classes (e.g. for a Foo FieldContainer:
192 FooBase and Foo). This strategy has various advantages:
194 \li Type system changes: If the OpenSG core team decides to change the code
195 interface for the FieldContainer type management we can just recreate the base
196 classes from the XML description. No adaptations 'by hand' are needed.
198 \li Interface changes: If you would like to change the interface of your
199 FieldContainer (e.g. add another field) later on you can just re-edit the XML
200 file in fcdEdit and recreate the base classes. All necessary access methods
201 are created automatically.
203 \section PageSystemFieldContainerExtFCD XML Description (Foo.fcd)
205 Includes all field and meta descriptions for a single FieldContainer. Can be
206 read and written by the fcdEdit tool. You should only change it by hand when
207 you're sure of what you're doing.
209 \section PageSystemFieldContainerExtFieldTypes Field Types (FooFields.h)
211 Include the field and pointer declarations the the FieldContainer to be used
212 in other FieldContainers as reference. You should not change the file by hand.
214 \section PageSystemFieldContainerExtBase Base/Meta Type (FooBase.h, FooBase.inl,
217 Holds all the meta and field information. Do not change it by hand. Use the
218 fcdEdit tool to create the files anew whenever you change the XML
221 \section PageSystemFieldContainerExtUser 'User Code' implementation (Foo.h,
224 Holds the 'user code'. The fcdEdit is able to create a skeleton for your
225 FieldContainer implementation. The code does not include any meta information,
226 therefore, it is not necessary to create it anew whenever you change the
229 Include new action handlers or whatever you need as functionality.
231 \image html fcdEdit-numbered.png "fcdEdit"
233 \image latex fcdEdit-numbered.eps "fcdEdit" width=8cm
235 A quick explanation of the different buttons/input fields:
239 <li>The name of the FieldContainer. Should follow the capitalization rules.</li>
241 <li>Defines whether the FC is a part of the OpenSG system. This mainly
242 influences the way system headers are included (with or without the OpenSG/
245 <li>Defines whether the FC can be decorated. Currentl only used for
246 OSG::CameraDecorator classes, but usable in general. The main effect is to turn
247 all Field access emthods into virtual functions, to allow overriding them, and
248 creating the necessary default Decorator classes.</li>
250 <li>The name of the parent class of the FC.</li>
252 <li>Defines if the parent class is a system component.</li>
254 <li>The name of the library this FC will be included in. If it is only to be
255 used in application programs, just leave it blank and the appropriate code for
256 an application component will be generated.</li>
258 <li>Define whether Field types for pointers to this type of FC should be
261 <li>Defines whether this FC is abstract or concrete (i.e. whether it can be
262 instantiated or not).</li>
264 <li>A general description of this FC. It will be included in the actual FC
265 code. As this code cannot be regenerated changing this description after the
266 code has been generated will not make a difference.</li>
268 <li>A list of the Fields of this FC.</li>
270 <li>The name of the currently selected Field.</li>
272 <li>The type of the currently selected Field. There is a list of predefined
273 types that can be selected from, but it is also possible to just write the type
274 of the Field here.</li>
276 <li>The cardinality of the Field, i.e. if it's a single (OSG::SField) or multi
277 element (OSG::MField) field.</li>
279 <li>The access type of the field: private, protected or public. In general
280 Fields should be public, if they are internal they should be protected.</li>
282 <li>The visibility of the Field mainly influences whether the Field is written
283 to files etc. Fields that have no meaning beyond the current execution of the
284 program should be internal, Fields that hold configuration data should be
287 <li>The header containing the declaration of the Field's type. If left empty a
288 name is guessed, using the name <tt>OSG<type>Fields.h</tt>. For type names
289 ending in \c Ptr (the default for FieldContainerPtr types) the \c Ptr is
290 removed. This works for all system types and for standard user-defined types.
291 For other types, just enter the header file name into this field, excluding the "
294 <li>The default value of the Field. Used to initialize the Field, and put
295 verbatim into the constructor definition for the given Field (e.g. <tt>FC::FC() :
296 Field(default) { }</tt>) </li>
298 <li>The header needed to declare the default value. Useful to access enum or
299 constants from external files (like opengl.h).</li>
301 <li>A short description of the Field's contents and function. Will be put into
302 the code documentation.</li>
304 <li>Creates a new Field.</li>
306 <li>Deletes a Field.</li>
308 <li>Clones a Field.</li>
310 <li>Moves the Field up in the list.</li>
312 <li>Moves the Field down in the list.</li>
314 <li>Clear the whole system, start from scratch.</li>
316 <li>Load an .fcd file.</li>
318 <li>Currently unused.</li>
320 <li>Save the current settings to the .fcd file.</li>
322 <li>Write the FieldContainer Base code. This can also be done by calling
323 fcdEdit with the <tt>-b</tt> command line option and the .fcd file. It is safe
324 to do that, as no user changes should be done to the Base code.</li>
326 <li>Currently unused.</li>
328 <li>Currently unused.</li>
330 <li>Save the current settings to a different .fcd file.</li>
332 <li>Write the actual FieldContainer code. This can also be done by calling
333 fcdEdit with the <tt>-f</tt> command line option and the .fcd file. This will
334 not keep any changes made to the FC code, and thus can quickly destroy whatever
335 work has been done to it. To prevent that from happening on accident, it will not
336 overwrite existing files.</li>
338 <li>Minimal info about the progam.</li>
340 <li>Leave the program.</li>
344 \section PageSystemFieldContainerExtPrototype Prototype Replacement
346 If you create a replacement for a system component, e.g. a smarter DistanceLOD
347 node that can handle predictive LOD selection, and want the system to use your
348 version of the DistanceLOD from now on you can do that. Internally all field
349 container instances are created by cloning a prototype instance. You can
350 access the prototype for a given FieldContainer via its class type which you
351 can access using FC::getClassType(). The class type has a setPrototype()
352 method to assign the prototype.
354 Be careful to only replace the prototype with classes derived from the
355 original class, or the behavior of the system is undefined.
357 \section PageSystemFieldContainerExtInit Initialization / Deinitalization
359 As OpenSG uses object replication for thread-safe data, constructors and
360 destructors are not always the right place for initialisation and deletion
361 anymore. They are called for every aspect, which usually is more than once.
362 For initialisation that should be done only once per object, the onCreate()
363 method can be used. Similarly, onDestroy() is called once, when the object is
366 There is also a difference between the constructors. The copy constructor is
367 called for every aspect of an object, the default constructor is only called
368 once, during the static init phase, to create the initial prototype instance
369 for the class. As code running in the static init phase faces some
370 restrictions (e.g. the order of initializations is undefined, thus any other
371 object might not yet have been initialized) a saver way to do class-global
372 initializations was added. The initMethod() method is called during osgInit(),
373 which is after all static inits are done.
375 As a summary here's a list of when which method is called:
377 \li default constructor: once, during static init, to create the initial
380 \li initMethod(): once, during osgInit()
382 \li copy constructor: during object instance creation, once for every aspect
384 \li onCreate(): during object instance creation, once
386 \li onDestroy(): during object instance deletion, once
388 \li destructor: during object instance deletion, once for every aspect
390 onCreate() and on Destroy() are also called for the initial prototype
391 creation. Not all prototypes might need the resources a real instance needs,
392 and initial prototype creation is run during static init, where it might not
393 be safe to access other classes. To allow a destinction between prototype
394 creation and the standard running state of the system there's a global
395 variable GlobalSystemState, which will be set to Startup during static init
396 and Running after osgInit() is finished. During osgExit() it will be set to