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 #ifndef COIN_SOSUBNODEENGINE_H
34 #define COIN_SOSUBNODEENGINE_H
35 
36 #include <Inventor/nodes/SoSubNode.h>
37 #include <Inventor/engines/SoSubEngine.h>
38 
39 #define SO_NODEENGINE_ABSTRACT_HEADER(_class_) \
40   SO_NODE_ABSTRACT_HEADER(_class_); \
41 protected: \
42   static const SoEngineOutputData ** getOutputDataPtr(void); \
43 public: \
44   virtual const SoEngineOutputData * getOutputData(void) const; \
45 private: \
46   static void atexit_cleanupnodeengine(void); \
47   static SoEngineOutputData * outputdata; \
48   static const SoEngineOutputData ** parentoutputdata
49 
50 #define SO_NODEENGINE_HEADER(_class_) \
51   SO_NODEENGINE_ABSTRACT_HEADER(_class_); \
52   public: \
53     static void * createInstance(void)
54 
55 #define SO_NODEENGINE_ABSTRACT_SOURCE(_class_) \
56 SO_NODE_ABSTRACT_SOURCE(_class_); \
57 SoEngineOutputData * _class_::outputdata = NULL; \
58 const SoEngineOutputData ** _class_::parentoutputdata = NULL; \
59  \
60 const SoEngineOutputData ** \
61 _class_::getOutputDataPtr(void) \
62 { \
63   return (const SoEngineOutputData**)&_class_::outputdata; \
64 } \
65  \
66 const SoEngineOutputData * \
67 _class_::getOutputData(void) const \
68 { \
69   return _class_::outputdata; \
70 } \
71  \
72 void \
73 _class_::atexit_cleanupnodeengine(void) { \
74   delete _class_::outputdata; \
75   _class_::outputdata = NULL; \
76   _class_::parentoutputdata = NULL; \
77   _class_::classTypeId STATIC_SOTYPE_INIT; \
78 }
79 
80 #define SO_NODEENGINE_SOURCE(_class_) \
81 SO_NODEENGINE_ABSTRACT_SOURCE(_class_); \
82  \
83 void * \
84 _class_::createInstance(void) \
85 { \
86   return new _class_; \
87 }
88 
89 #define SO_NODEENGINE_CONSTRUCTOR(_class_) \
90   do { \
91     SoBase::staticDataLock(); \
92     _class_::classinstances++; \
93     /* Catch attempts to use an engine class which has not been initialized. */ \
94     assert(_class_::classTypeId != SoType::badType()); \
95     /* Initialize a inputdata container for the class only once. */ \
96     if (!_class_::fieldData) { \
97       _class_::fieldData = \
98         new SoFieldData(_class_::parentFieldData ? \
99                         *_class_::parentFieldData : NULL); \
100       _class_::outputdata = \
101         new SoEngineOutputData(_class_::parentoutputdata ? \
102                                *_class_::parentoutputdata : NULL); \
103     } \
104     /* Extension classes from the application programmers should not be */ \
105     /* considered native. This is important to get the export code to do */ \
106     /* the Right Thing. */ \
107     this->isBuiltIn = FALSE; \
108     SoBase::staticDataUnlock(); \
109   } WHILE_0
110 
111 #define PRIVATE_COMMON_NODEENGINE_INIT_CODE(_class_, _classname_, _createfunc_, _parentclass_) \
112   do { \
113     /* Make sure we only initialize once. */ \
114     assert(_class_::classTypeId == SoType::badType() && "don't init() twice!"); \
115     /* Make sure superclass gets initialized before subclass. */ \
116     assert(_parentclass_::getClassTypeId() != SoType::badType() && "you forgot init() on parentclass!"); \
117  \
118     /* Set up entry in the type system. */ \
119     _class_::classTypeId = \
120       SoType::createType(_parentclass_::getClassTypeId(), \
121                          _classname_, \
122                          _createfunc_, \
123                          SoNode::getNextActionMethodIndex()); \
124     SoNode::incNextActionMethodIndex(); \
125  \
126     /* Store parent's fielddata pointer for later use in the constructor. */ \
127     _class_::parentFieldData = _parentclass_::getFieldDataPtr(); \
128     _class_::parentoutputdata = _parentclass_::getOutputDataPtr(); \
129   } WHILE_0
130 
131 #define SO_NODEENGINE_INIT_CLASS(_class_, _parentclass_, _parentname_) \
132   do { \
133     const char * classname = SO__QUOTE(_class_); \
134     PRIVATE_COMMON_INIT_CODE(_class_, classname, &_class_::createInstance, _parentclass_); \
135   } WHILE_0
136 
137 #define SO_NODEENGINE_EXIT_CLASS(_class_) \
138   _class_::atexit_cleanupnodeengine();
139 
140 #define SO_NODEENGINE_INIT_ABSTRACT_CLASS(_class_, _parentclass_, _parentname_) \
141   do { \
142     const char * classname = SO__QUOTE(_class_); \
143     PRIVATE_COMMON_INIT_CODE(_class_, classname, NULL, _parentclass_); \
144   } WHILE_0
145 
146 #define SO_NODEENGINE_ADD_OUTPUT(_output_, _type_) \
147   do { \
148     outputdata->addOutput(this, SO__QUOTE(_output_), \
149                           &this->_output_, \
150                           _type_::getClassTypeId()); \
151     this->_output_.setNodeContainer(this); \
152   } WHILE_0
153 
154 #endif // COIN_SOSUBNODEENGINE_H
155