1 #ifndef SH_PROPERTYBASE_H 2 #define SH_PROPERTYBASE_H 3 4 #include <string> 5 #include <map> 6 7 #include <boost/shared_ptr.hpp> 8 9 namespace sh 10 { 11 class StringValue; 12 class PropertySetGet; 13 class LinkedValue; 14 15 enum ValueType 16 { 17 VT_String, 18 VT_Int, 19 VT_Float, 20 VT_Vector2, 21 VT_Vector3, 22 VT_Vector4 23 }; 24 25 class PropertyValue 26 { 27 public: PropertyValue()28 PropertyValue() {} 29 ~PropertyValue()30 virtual ~PropertyValue() {} 31 _getStringValue()32 std::string _getStringValue() { return mStringValue; } 33 34 virtual std::string serialize() = 0; 35 36 protected: 37 std::string mStringValue; ///< this will possibly not contain anything in the specialised classes 38 }; 39 typedef boost::shared_ptr<PropertyValue> PropertyValuePtr; 40 41 class StringValue : public PropertyValue 42 { 43 public: 44 StringValue (const std::string& in); get() const45 std::string get() const { return mStringValue; } 46 47 virtual std::string serialize(); 48 }; 49 50 /** 51 * @brief Used for retrieving a named property from a context 52 */ 53 class LinkedValue : public PropertyValue 54 { 55 public: 56 LinkedValue (const std::string& in); 57 58 std::string get(PropertySetGet* context) const; 59 60 virtual std::string serialize(); 61 }; 62 63 class FloatValue : public PropertyValue 64 { 65 public: 66 FloatValue (float in); 67 FloatValue (const std::string& in); get() const68 float get() const { return mValue; } 69 70 virtual std::string serialize(); 71 private: 72 float mValue; 73 }; 74 75 class IntValue : public PropertyValue 76 { 77 public: 78 IntValue (int in); 79 IntValue (const std::string& in); get() const80 int get() const { return mValue; } 81 82 virtual std::string serialize(); 83 private: 84 int mValue; 85 }; 86 87 class BooleanValue : public PropertyValue 88 { 89 public: 90 BooleanValue (bool in); 91 BooleanValue (const std::string& in); get() const92 bool get() const { return mValue; } 93 94 virtual std::string serialize(); 95 private: 96 bool mValue; 97 }; 98 99 class Vector2 : public PropertyValue 100 { 101 public: 102 Vector2 (float x, float y); 103 Vector2 (const std::string& in); 104 105 float mX, mY; 106 107 virtual std::string serialize(); 108 }; 109 110 class Vector3 : public PropertyValue 111 { 112 public: 113 Vector3 (float x, float y, float z); 114 Vector3 (const std::string& in); 115 116 float mX, mY, mZ; 117 118 virtual std::string serialize(); 119 }; 120 121 class Vector4 : public PropertyValue 122 { 123 public: 124 Vector4 (float x, float y, float z, float w); 125 Vector4 (const std::string& in); 126 127 float mX, mY, mZ, mW; 128 129 virtual std::string serialize(); 130 }; 131 132 /// \brief base class that allows setting properties with any kind of value-type 133 class PropertySet 134 { 135 public: ~PropertySet()136 virtual ~PropertySet() {} 137 void setProperty (const std::string& name, PropertyValuePtr& value, PropertySetGet* context); 138 139 protected: 140 virtual bool setPropertyOverride (const std::string& name, PropertyValuePtr& value, PropertySetGet* context); 141 ///< @return \a true if the specified property was found, or false otherwise 142 }; 143 144 typedef std::map<std::string, PropertyValuePtr> PropertyMap; 145 146 /// \brief base class that allows setting properties with any kind of value-type and retrieving them 147 class PropertySetGet 148 { 149 public: 150 PropertySetGet (PropertySetGet* parent); 151 PropertySetGet (); 152 ~PropertySetGet()153 virtual ~PropertySetGet() {} 154 155 void save (std::ofstream& stream, const std::string& indentation); 156 157 void copyAll (PropertySet* target, PropertySetGet* context, bool copyParent=true); 158 ///< call setProperty for each property/value pair stored in \a this 159 void copyAll (PropertySetGet* target, PropertySetGet* context, bool copyParent=true); 160 ///< call setProperty for each property/value pair stored in \a this 161 162 void setParent (PropertySetGet* parent); getParent()163 PropertySetGet* getParent () { return mParent; } 164 void setContext (PropertySetGet* context); 165 PropertySetGet* getContext(); 166 167 virtual void setProperty (const std::string& name, PropertyValuePtr value); 168 PropertyValuePtr& getProperty (const std::string& name); 169 170 void deleteProperty (const std::string& name); 171 listProperties()172 const PropertyMap& listProperties() { return mProperties; } 173 174 bool hasProperty (const std::string& name) const; 175 176 private: 177 PropertyMap mProperties; 178 179 protected: 180 PropertySetGet* mParent; 181 ///< the parent can provide properties as well (when they are retrieved via getProperty) \n 182 /// multiple levels of inheritance are also supported \n 183 /// children can override properties of their parents 184 185 PropertySetGet* mContext; 186 ///< used to retrieve linked property values 187 }; 188 189 template <typename T> retrieveValue(boost::shared_ptr<PropertyValue> & value,PropertySetGet * context)190 static T retrieveValue (boost::shared_ptr<PropertyValue>& value, PropertySetGet* context) 191 { 192 if (typeid(*value).name() == typeid(LinkedValue).name()) 193 { 194 std::string v = static_cast<LinkedValue*>(value.get())->get(context); 195 PropertyValuePtr newVal = PropertyValuePtr (new StringValue(v)); 196 return retrieveValue<T>(newVal, NULL); 197 } 198 if (typeid(T).name() == typeid(*value).name()) 199 { 200 // requested type is the same as source type, only have to cast it 201 return *static_cast<T*>(value.get()); 202 } 203 204 if ((typeid(T).name() == typeid(StringValue).name()) 205 && typeid(*value).name() != typeid(StringValue).name()) 206 { 207 // if string type is requested and value is not string, use serialize method to convert to string 208 T* ptr = new T (value->serialize()); // note that T is always StringValue here, but we can't use it here 209 value = boost::shared_ptr<PropertyValue> (static_cast<PropertyValue*>(ptr)); 210 return *ptr; 211 } 212 213 { 214 // remaining case: deserialization from string by passing the string to constructor of class T 215 T* ptr = new T(value->_getStringValue()); 216 PropertyValuePtr newVal (static_cast<PropertyValue*>(ptr)); 217 value = newVal; 218 return *ptr; 219 } 220 } 221 ///< 222 /// @brief alternate version that supports linked values (use of $variables in parent material) 223 /// @note \a value is changed in-place to the converted object 224 /// @return converted object \n 225 226 /// Create a property from a string makeProperty(const std::string & prop)227 inline PropertyValuePtr makeProperty (const std::string& prop) 228 { 229 if (prop.size() > 1 && prop[0] == '$') 230 return PropertyValuePtr (static_cast<PropertyValue*>(new LinkedValue(prop))); 231 else 232 return PropertyValuePtr (static_cast<PropertyValue*> (new StringValue(prop))); 233 } 234 235 template <typename T> 236 /// Create a property of any type 237 /// Example: sh::makeProperty (new sh::Vector4(1, 1, 1, 1)) makeProperty(T * p)238 inline PropertyValuePtr makeProperty (T* p) 239 { 240 return PropertyValuePtr ( static_cast<PropertyValue*>(p) ); 241 } 242 } 243 244 #endif 245