ClassInterface 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. #ifndef OSGDB_CLASSINTERFACE
  14. #define OSGDB_CLASSINTERFACE 1
  15. #include <osgDB/ObjectWrapper>
  16. #include <osgDB/Registry>
  17. #include <osg/ValueObject>
  18. namespace osgDB
  19. {
  20. template<typename T>
  21. static osgDB::BaseSerializer::Type getTypeEnum()
  22. {
  23. return osgDB::BaseSerializer::RW_UNDEFINED;
  24. }
  25. template<typename T>
  26. static osgDB::BaseSerializer::Type getTypeEnumFrom(T)
  27. {
  28. return getTypeEnum<T>();
  29. }
  30. template<typename T>
  31. static const char* getTypeString()
  32. {
  33. return "UNDEFINED";
  34. }
  35. template<typename T>
  36. static const char* getTypeStringFrom(T)
  37. {
  38. return getTypeString<T>();
  39. }
  40. extern OSGDB_EXPORT osgDB::BaseSerializer::Type getTypeEnumFromPtr(const osg::Object*);
  41. extern OSGDB_EXPORT const char* getTypeStringFromPtr(const osg::Object*);
  42. extern OSGDB_EXPORT osgDB::BaseSerializer::Type getTypeEnumFromPtr(const osg::Image*);
  43. extern OSGDB_EXPORT const char* getTypeStringFromPtr(const osg::Image*);
  44. #define DECLARE_TYPE(A,B) \
  45. template<> inline osgDB::BaseSerializer::Type getTypeEnum<A>() { return osgDB::BaseSerializer::RW_##B; } \
  46. template<> inline const char* getTypeString<A>() { return #B; }
  47. DECLARE_TYPE(osg::Image*, IMAGE)
  48. DECLARE_TYPE(osg::Object*, OBJECT)
  49. DECLARE_TYPE(bool, BOOL)
  50. DECLARE_TYPE(char, CHAR)
  51. DECLARE_TYPE(unsigned char, UCHAR)
  52. DECLARE_TYPE(short, SHORT)
  53. DECLARE_TYPE(unsigned short, USHORT)
  54. DECLARE_TYPE(int, INT)
  55. DECLARE_TYPE(unsigned int, UINT)
  56. DECLARE_TYPE(float, FLOAT)
  57. DECLARE_TYPE(double, DOUBLE)
  58. DECLARE_TYPE(osg::Vec2f, VEC2F)
  59. DECLARE_TYPE(osg::Vec2d, VEC2D)
  60. DECLARE_TYPE(osg::Vec3f, VEC3F)
  61. DECLARE_TYPE(osg::Vec3d, VEC3D)
  62. DECLARE_TYPE(osg::Vec4f, VEC4F)
  63. DECLARE_TYPE(osg::Vec4d, VEC4D)
  64. DECLARE_TYPE(osg::Quat, QUAT)
  65. DECLARE_TYPE(osg::Plane, PLANE)
  66. DECLARE_TYPE(osg::Matrixf, MATRIXF)
  67. DECLARE_TYPE(osg::Matrixd, MATRIXD)
  68. DECLARE_TYPE(std::string, STRING)
  69. DECLARE_TYPE(osg::Vec2b, VEC2B)
  70. DECLARE_TYPE(osg::Vec2ub, VEC2UB)
  71. DECLARE_TYPE(osg::Vec2s, VEC2S)
  72. DECLARE_TYPE(osg::Vec2us, VEC2US)
  73. DECLARE_TYPE(osg::Vec2i, VEC2I)
  74. DECLARE_TYPE(osg::Vec2ui, VEC2UI)
  75. DECLARE_TYPE(osg::Vec3b, VEC3B)
  76. DECLARE_TYPE(osg::Vec3ub, VEC3UB)
  77. DECLARE_TYPE(osg::Vec3s, VEC3S)
  78. DECLARE_TYPE(osg::Vec3us, VEC3US)
  79. DECLARE_TYPE(osg::Vec3i, VEC3I)
  80. DECLARE_TYPE(osg::Vec3ui, VEC3UI)
  81. DECLARE_TYPE(osg::Vec4b, VEC4B)
  82. DECLARE_TYPE(osg::Vec4ub, VEC4UB)
  83. DECLARE_TYPE(osg::Vec4s, VEC4S)
  84. DECLARE_TYPE(osg::Vec4us, VEC4US)
  85. DECLARE_TYPE(osg::Vec4i, VEC4I)
  86. DECLARE_TYPE(osg::Vec4ui, VEC4UI)
  87. DECLARE_TYPE(osg::BoundingBoxf, BOUNDINGBOXF)
  88. DECLARE_TYPE(osg::BoundingBoxd, BOUNDINGBOXD)
  89. DECLARE_TYPE(osg::BoundingSpheref, BOUNDINGSPHEREF)
  90. DECLARE_TYPE(osg::BoundingSphered, BOUNDINGSPHERED)
  91. // forward declare
  92. class PropertyOutputIterator;
  93. class PropertyInputIterator;
  94. /** ClassInterface provides a general means of checking for supported properties of classes, and getting/setting those properties.
  95. Uses the osgDB serializers to do the actual object query/get/set.
  96. */
  97. class OSGDB_EXPORT ClassInterface
  98. {
  99. public:
  100. ClassInterface();
  101. /// get the Type of the specified property, return true if property is supported, otherwise false.
  102. bool getPropertyType(const osg::Object* object, const std::string& propertyName, osgDB::BaseSerializer::Type& type) const;
  103. /// return type of two types are compatible
  104. bool areTypesCompatible(osgDB::BaseSerializer::Type lhs, osgDB::BaseSerializer::Type rhs) const;
  105. /** create an object of specified type for provided compound class name in the form libraryName::className. */
  106. osg::Object* createObject(const std::string& compoundClassdName) const;
  107. /// template method for getting property data, return true if property available and the type is compatible, otherwise returns false.
  108. template<typename T>
  109. bool getProperty(const osg::Object* object, const std::string& propertyName, T& value);
  110. /// template method for setting property data, return true if property available and the type is compatible, otherwise returns false.
  111. template<typename T>
  112. bool setProperty(osg::Object* object, const std::string& propertyName, const T& value);
  113. /// get the human readable name of type.
  114. std::string getTypeName(osgDB::BaseSerializer::Type type) const;
  115. /// get the enum value of type given the human readable name.
  116. osgDB::BaseSerializer::Type getType(const std::string& typeName) const;
  117. /// Properties supported for a single class
  118. typedef std::map<std::string, osgDB::BaseSerializer::Type> PropertyMap;
  119. /// Get the list of of properties supported by object
  120. bool getSupportedProperties(const osg::Object* object, PropertyMap& properties, bool searchAssociates=true) const;
  121. /// return true if the object can be cast to the specified class specified by compoundClassName
  122. bool isObjectOfType(const osg::Object* object, const std::string& compoundClassName) const;
  123. /// run method of object
  124. bool run(void* objectPtr, const std::string& compoundClassName, const std::string& methodName, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const;
  125. /// run method of object
  126. bool run(osg::Object* object, const std::string& methodName, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const;
  127. /// checked for support of specified method
  128. bool hasMethod(const std::string& compoundClassName, const std::string& methodName) const;
  129. /// checked for support of specified method
  130. bool hasMethod(const osg::Object* object, const std::string& methodName) const;
  131. /// Properties supported for a range of classes, used for white and black lists
  132. typedef std::map<std::string, PropertyMap> ObjectPropertyMap;
  133. /// Get the list of properties that are explicitly defined as supported
  134. ObjectPropertyMap& getWhiteList() { return _whiteList; }
  135. /// Get the const list of properties that are explicitly defined as supported
  136. const ObjectPropertyMap& getWhiteList() const { return _whiteList; }
  137. /// Get the list of properties that are explicitly defined as not supported
  138. ObjectPropertyMap& getBlackList() { return _blackList; }
  139. /// Get the const list of properties that are explicitly defined as not supported
  140. const ObjectPropertyMap& getBlackList() const { return _blackList; }
  141. osgDB::ObjectWrapper* getObjectWrapper(const osg::Object* object) const;
  142. osgDB::BaseSerializer* getSerializer(const osg::Object* object, const std::string& propertyName, osgDB::BaseSerializer::Type& type) const;
  143. protected:
  144. bool copyPropertyDataFromObject(const osg::Object* object, const std::string& propertyName, void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType);
  145. bool copyPropertyDataToObject(osg::Object* object, const std::string& propertyName, const void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType);
  146. bool copyPropertyObjectFromObject(const osg::Object* object, const std::string& propertyName, void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType);
  147. bool copyPropertyObjectToObject(osg::Object* object, const std::string& propertyName, const void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType);
  148. osgDB::OutputStream _outputStream;
  149. PropertyOutputIterator* _poi;
  150. osgDB::InputStream _inputStream;
  151. PropertyInputIterator* _pii;
  152. typedef std::map<std::string, osgDB::BaseSerializer::Type> TypeNameToTypeMap;
  153. typedef std::map<osgDB::BaseSerializer::Type, std::string> TypeToTypeNameMap;
  154. TypeNameToTypeMap _typeNameToTypeMap;
  155. TypeToTypeNameMap _typeToTypeNameMap;
  156. ObjectPropertyMap _whiteList;
  157. ObjectPropertyMap _blackList;
  158. };
  159. template<typename T>
  160. bool ClassInterface::getProperty(const osg::Object* object, const std::string& propertyName, T& value)
  161. {
  162. if (copyPropertyDataFromObject(object, propertyName, &value, sizeof(T), getTypeEnum<T>())) return true;
  163. else return object->getUserValue(propertyName, value); // fallback to check user data for property
  164. }
  165. template<typename T>
  166. bool ClassInterface::setProperty(osg::Object* object, const std::string& propertyName, const T& value)
  167. {
  168. if (copyPropertyDataToObject(object, propertyName, &value, sizeof(T), getTypeEnum<T>())) return true;
  169. else
  170. {
  171. // fallback to using user data to store property data
  172. object->setUserValue(propertyName, value);
  173. return false;
  174. }
  175. }
  176. typedef osg::Object* ObjectPtr;
  177. template<>
  178. inline bool ClassInterface::getProperty(const osg::Object* object, const std::string& propertyName, ObjectPtr& value)
  179. {
  180. if (copyPropertyObjectFromObject(object, propertyName, &value, sizeof(ObjectPtr), getTypeEnum<ObjectPtr>())) return true;
  181. else
  182. {
  183. OSG_INFO<<"ClassInterface::getProperty("<<propertyName<<", Checking UserDataContainer for object ptr"<<std::endl;
  184. const osg::UserDataContainer* udc = object->getUserDataContainer();
  185. if (udc)
  186. {
  187. OSG_INFO<<" Checking UserDataContainer for object ptr"<<std::endl;
  188. const osg::Object* ptr = udc->getUserObject(propertyName);
  189. if (ptr)
  190. {
  191. value = const_cast<ObjectPtr>(ptr);
  192. return true;
  193. }
  194. }
  195. return false;
  196. }
  197. }
  198. template<>
  199. inline bool ClassInterface::setProperty(osg::Object* object, const std::string& propertyName, const ObjectPtr& value)
  200. {
  201. osgDB::BaseSerializer::Type type = dynamic_cast<osg::Image*>(value) ? osgDB::BaseSerializer::RW_IMAGE : getTypeEnum<ObjectPtr>();
  202. // osgDB::BaseSerializer::Type type = getTypeEnum<ObjectPtr>();
  203. if (copyPropertyObjectToObject(object, propertyName, &value, sizeof(ObjectPtr), type)) return true;
  204. else
  205. {
  206. // fallback to using user data to store property data
  207. osg::UserDataContainer* udc = object->getOrCreateUserDataContainer();
  208. unsigned int objectIndex = udc->getUserObjectIndex(propertyName);
  209. if (objectIndex < udc->getNumUserObjects())
  210. {
  211. const osg::Object* outgoingObject = udc->getUserObject(objectIndex);
  212. if (outgoingObject==value) return true;
  213. OSG_INFO<<"ClassInterface::setProperty("<<propertyName<<", "<<value->className()<<") replace object on UserDataContainer"<<std::endl;
  214. value->setName(propertyName);
  215. udc->setUserObject(objectIndex, value);
  216. }
  217. else
  218. {
  219. OSG_INFO<<"ClassInterface::setProperty("<<propertyName<<", "<<value->className()<<") Adding object to UserDataContainer"<<std::endl;
  220. value->setName(propertyName);
  221. udc->addUserObject(value);
  222. }
  223. return true;
  224. }
  225. }
  226. }
  227. #endif