openscenegraph
ClassInterface
Go to the documentation of this file.
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14
15#ifndef OSGDB_CLASSINTERFACE
16#define OSGDB_CLASSINTERFACE 1
17
18#include <osgDB/ObjectWrapper>
19#include <osgDB/Registry>
20#include <osg/ValueObject>
21
22namespace osgDB
23{
24
25template<typename T>
26static osgDB::BaseSerializer::Type getTypeEnum()
27{
28 return osgDB::BaseSerializer::RW_UNDEFINED;
29}
30
31template<typename T>
32static osgDB::BaseSerializer::Type getTypeEnumFrom(T)
33{
34 return getTypeEnum<T>();
35}
36
37template<typename T>
38static const char* getTypeString()
39{
40 return "UNDEFINED";
41}
42
43template<typename T>
44static const char* getTypeStringFrom(T)
45{
46 return getTypeString<T>();
47}
48
49extern OSGDB_EXPORT osgDB::BaseSerializer::Type getTypeEnumFromPtr(const osg::Object*);
50extern OSGDB_EXPORT const char* getTypeStringFromPtr(const osg::Object*);
51
52extern OSGDB_EXPORT osgDB::BaseSerializer::Type getTypeEnumFromPtr(const osg::Image*);
53extern OSGDB_EXPORT const char* getTypeStringFromPtr(const osg::Image*);
54
55
56#define DECLARE_TYPE(A,B) \
57 template<> inline osgDB::BaseSerializer::Type getTypeEnum<A>() { return osgDB::BaseSerializer::RW_##B; } \
58 template<> inline const char* getTypeString<A>() { return #B; }
59
60DECLARE_TYPE(osg::Image*, IMAGE)
61DECLARE_TYPE(osg::Object*, OBJECT)
62
63DECLARE_TYPE(bool, BOOL)
64DECLARE_TYPE(char, CHAR)
65DECLARE_TYPE(unsigned char, UCHAR)
66DECLARE_TYPE(short, SHORT)
67DECLARE_TYPE(unsigned short, USHORT)
68DECLARE_TYPE(int, INT)
69DECLARE_TYPE(unsigned int, UINT)
70DECLARE_TYPE(float, FLOAT)
71DECLARE_TYPE(double, DOUBLE)
72
73DECLARE_TYPE(osg::Vec2f, VEC2F)
74DECLARE_TYPE(osg::Vec2d, VEC2D)
75DECLARE_TYPE(osg::Vec3f, VEC3F)
76DECLARE_TYPE(osg::Vec3d, VEC3D)
77DECLARE_TYPE(osg::Vec4f, VEC4F)
78DECLARE_TYPE(osg::Vec4d, VEC4D)
79DECLARE_TYPE(osg::Quat, QUAT)
80DECLARE_TYPE(osg::Plane, PLANE)
81
82DECLARE_TYPE(osg::Matrixf, MATRIXF)
83DECLARE_TYPE(osg::Matrixd, MATRIXD)
84DECLARE_TYPE(std::string, STRING)
85
86DECLARE_TYPE(osg::Vec2b, VEC2B)
87DECLARE_TYPE(osg::Vec2ub, VEC2UB)
88DECLARE_TYPE(osg::Vec2s, VEC2S)
89DECLARE_TYPE(osg::Vec2us, VEC2US)
90DECLARE_TYPE(osg::Vec2i, VEC2I)
91DECLARE_TYPE(osg::Vec2ui, VEC2UI)
92
93DECLARE_TYPE(osg::Vec3b, VEC3B)
94DECLARE_TYPE(osg::Vec3ub, VEC3UB)
95DECLARE_TYPE(osg::Vec3s, VEC3S)
96DECLARE_TYPE(osg::Vec3us, VEC3US)
97DECLARE_TYPE(osg::Vec3i, VEC3I)
98DECLARE_TYPE(osg::Vec3ui, VEC3UI)
99
100DECLARE_TYPE(osg::Vec4b, VEC4B)
101DECLARE_TYPE(osg::Vec4ub, VEC4UB)
102DECLARE_TYPE(osg::Vec4s, VEC4S)
103DECLARE_TYPE(osg::Vec4us, VEC4US)
104DECLARE_TYPE(osg::Vec4i, VEC4I)
105DECLARE_TYPE(osg::Vec4ui, VEC4UI)
106
107DECLARE_TYPE(osg::BoundingBoxf, BOUNDINGBOXF)
108DECLARE_TYPE(osg::BoundingBoxd, BOUNDINGBOXD)
109
110DECLARE_TYPE(osg::BoundingSpheref, BOUNDINGSPHEREF)
111DECLARE_TYPE(osg::BoundingSphered, BOUNDINGSPHERED)
112
113// forward declare
114class PropertyOutputIterator;
115class PropertyInputIterator;
116
117
118/** ClassInterface provides a general means of checking for supported properties of classes, and getting/setting those properties.
119 Uses the osgDB serializers to do the actual object query/get/set.
120*/
121class OSGDB_EXPORT ClassInterface
122{
123public:
124 ClassInterface();
125
126
127 /// get the Type of the specified property, return true if property is supported, otherwise false.
128 bool getPropertyType(const osg::Object* object, const std::string& propertyName, osgDB::BaseSerializer::Type& type) const;
129
130 /// return type of two types are compatible
131 bool areTypesCompatible(osgDB::BaseSerializer::Type lhs, osgDB::BaseSerializer::Type rhs) const;
132
133
134 /** create an object of specified type for provided compound class name in the form libraryName::className. */
135 osg::Object* createObject(const std::string& compoundClassdName) const;
136
137 /// template method for getting property data, return true if property available and the type is compatible, otherwise returns false.
138 template<typename T>
139 bool getProperty(const osg::Object* object, const std::string& propertyName, T& value);
140
141 /// template method for setting property data, return true if property available and the type is compatible, otherwise returns false.
142 template<typename T>
143 bool setProperty(osg::Object* object, const std::string& propertyName, const T& value);
144
145
146 /// get the human readable name of type.
147 std::string getTypeName(osgDB::BaseSerializer::Type type) const;
148
149 /// get the enum value of type given the human readable name.
150 osgDB::BaseSerializer::Type getType(const std::string& typeName) const;
151
152
153 /// Properties supported for a single class
154 typedef std::map<std::string, osgDB::BaseSerializer::Type> PropertyMap;
155
156 /// Get the list of of properties supported by object
157 bool getSupportedProperties(const osg::Object* object, PropertyMap& properties, bool searchAssociates=true) const;
158
159 /// return true if the object can be cast to the specified class specified by compoundClassName
160 bool isObjectOfType(const osg::Object* object, const std::string& compoundClassName) const;
161
162
163 /// run method of object
164 bool run(void* objectPtr, const std::string& compoundClassName, const std::string& methodName, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const;
165
166 /// run method of object
167 bool run(osg::Object* object, const std::string& methodName, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const;
168
169 /// checked for support of specified method
170 bool hasMethod(const std::string& compoundClassName, const std::string& methodName) const;
171
172 /// checked for support of specified method
173 bool hasMethod(const osg::Object* object, const std::string& methodName) const;
174
175
176 /// Properties supported for a range of classes, used for white and black lists
177 typedef std::map<std::string, PropertyMap> ObjectPropertyMap;
178
179 /// Get the list of properties that are explicitly defined as supported
180 ObjectPropertyMap& getWhiteList() { return _whiteList; }
181
182 /// Get the const list of properties that are explicitly defined as supported
183 const ObjectPropertyMap& getWhiteList() const { return _whiteList; }
184
185 /// Get the list of properties that are explicitly defined as not supported
186 ObjectPropertyMap& getBlackList() { return _blackList; }
187
188 /// Get the const list of properties that are explicitly defined as not supported
189 const ObjectPropertyMap& getBlackList() const { return _blackList; }
190
191 osgDB::ObjectWrapper* getObjectWrapper(const osg::Object* object) const;
192
193 osgDB::BaseSerializer* getSerializer(const osg::Object* object, const std::string& propertyName, osgDB::BaseSerializer::Type& type) const;
194
195protected:
196
197 bool copyPropertyDataFromObject(const osg::Object* object, const std::string& propertyName, void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType);
198
199 bool copyPropertyDataToObject(osg::Object* object, const std::string& propertyName, const void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType);
200
201 bool copyPropertyObjectFromObject(const osg::Object* object, const std::string& propertyName, void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType);
202
203 bool copyPropertyObjectToObject(osg::Object* object, const std::string& propertyName, const void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType);
204
205
206
207 osgDB::OutputStream _outputStream;
208 PropertyOutputIterator* _poi;
209
210 osgDB::InputStream _inputStream;
211 PropertyInputIterator* _pii;
212
213 typedef std::map<std::string, osgDB::BaseSerializer::Type> TypeNameToTypeMap;
214 typedef std::map<osgDB::BaseSerializer::Type, std::string> TypeToTypeNameMap;
215
216 TypeNameToTypeMap _typeNameToTypeMap;
217 TypeToTypeNameMap _typeToTypeNameMap;
218
219 ObjectPropertyMap _whiteList;
220 ObjectPropertyMap _blackList;
221};
222
223
224template<typename T>
225bool ClassInterface::getProperty(const osg::Object* object, const std::string& propertyName, T& value)
226{
227 if (copyPropertyDataFromObject(object, propertyName, &value, sizeof(T), getTypeEnum<T>())) return true;
228 else return object->getUserValue(propertyName, value); // fallback to check user data for property
229}
230
231template<typename T>
232bool ClassInterface::setProperty(osg::Object* object, const std::string& propertyName, const T& value)
233{
234 if (copyPropertyDataToObject(object, propertyName, &value, sizeof(T), getTypeEnum<T>())) return true;
235 else
236 {
237 // fallback to using user data to store property data
238 object->setUserValue(propertyName, value);
239 return false;
240 }
241}
242
243typedef osg::Object* ObjectPtr;
244
245template<>
246inline bool ClassInterface::getProperty(const osg::Object* object, const std::string& propertyName, ObjectPtr& value)
247{
248 if (copyPropertyObjectFromObject(object, propertyName, &value, sizeof(ObjectPtr), getTypeEnum<ObjectPtr>())) return true;
249 else
250 {
251 OSG_INFO<<"ClassInterface::getProperty("<<propertyName<<", Checking UserDataContainer for object ptr"<<std::endl;
252 const osg::UserDataContainer* udc = object->getUserDataContainer();
253 if (udc)
254 {
255 OSG_INFO<<" Checking UserDataContainer for object ptr"<<std::endl;
256 const osg::Object* ptr = udc->getUserObject(propertyName);
257 if (ptr)
258 {
259 value = const_cast<ObjectPtr>(ptr);
260 return true;
261 }
262 }
263 return false;
264 }
265}
266
267template<>
268inline bool ClassInterface::setProperty(osg::Object* object, const std::string& propertyName, const ObjectPtr& value)
269{
270 osgDB::BaseSerializer::Type type = dynamic_cast<osg::Image*>(value) ? osgDB::BaseSerializer::RW_IMAGE : getTypeEnum<ObjectPtr>();
271 // osgDB::BaseSerializer::Type type = getTypeEnum<ObjectPtr>();
272 if (copyPropertyObjectToObject(object, propertyName, &value, sizeof(ObjectPtr), type)) return true;
273 else
274 {
275 // fallback to using user data to store property data
276 osg::UserDataContainer* udc = object->getOrCreateUserDataContainer();
277 unsigned int objectIndex = udc->getUserObjectIndex(propertyName);
278 if (objectIndex < udc->getNumUserObjects())
279 {
280 const osg::Object* outgoingObject = udc->getUserObject(objectIndex);
281 if (outgoingObject==value) return true;
282
283 OSG_INFO<<"ClassInterface::setProperty("<<propertyName<<", "<<value->className()<<") replace object on UserDataContainer"<<std::endl;
284 value->setName(propertyName);
285 udc->setUserObject(objectIndex, value);
286 }
287 else
288 {
289 OSG_INFO<<"ClassInterface::setProperty("<<propertyName<<", "<<value->className()<<") Adding object to UserDataContainer"<<std::endl;
290 value->setName(propertyName);
291 udc->addUserObject(value);
292 }
293 return true;
294 }
295}
296
297
298}
299
300#endif