1/* -*-c++-*- OpenSceneGraph - Copyright (C) 2011 Robert Osfield
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.
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.
14#ifndef OSG_VALUEOBJECT
15#define OSG_VALUEOBJECT 1
18#include <osg/UserDataContainer>
19#include <osg/BoundingBox>
20#include <osg/BoundingSphere>
26// forward declare core OSG math classes
66class ValueObject : public Object
70 ValueObject() : Object(true) {}
71 ValueObject(const std::string& name) : Object(true) { setName(name); }
72 ValueObject(const ValueObject& rhs, const osg::CopyOp copyop=osg::CopyOp::SHALLOW_COPY): Object(rhs,copyop) {}
74 META_Object(osg, ValueObject)
76 /** Convert 'this' into a ValueObject pointer if Object is a ValueObject, otherwise return 0.
77 * Equivalent to dynamic_cast<ValueObject*>(this).*/
78 virtual ValueObject* asValueObject() { return this; }
80 /** Convert 'this' into a ValueObject pointer if Object is a ValueObject, otherwise return 0.
81 * Equivalent to dynamic_cast<ValueObject*>(this).*/
82 virtual const ValueObject* asValueObject() const { return this; }
87 virtual ~GetValueVisitor() {}
88 virtual void apply(bool /*in_value*/) {}
89 virtual void apply(char /*in_value*/) {}
90 virtual void apply(unsigned char /*in_value*/) {}
91 virtual void apply(short /*in_value*/) {}
92 virtual void apply(unsigned short /*in_value*/) {}
93 virtual void apply(int /*in_value*/) {}
94 virtual void apply(unsigned int /*in_value*/) {}
95 virtual void apply(float /*in_value*/) {}
96 virtual void apply(double /*in_value*/) {}
97 virtual void apply(const std::string& /*in_value*/) {}
99 virtual void apply(const osg::Vec2b& /*in_value*/) {}
100 virtual void apply(const osg::Vec3b& /*in_value*/) {}
101 virtual void apply(const osg::Vec4b& /*in_value*/) {}
103 virtual void apply(const osg::Vec2ub& /*in_value*/) {}
104 virtual void apply(const osg::Vec3ub& /*in_value*/) {}
105 virtual void apply(const osg::Vec4ub& /*in_value*/) {}
107 virtual void apply(const osg::Vec2s& /*in_value*/) {}
108 virtual void apply(const osg::Vec3s& /*in_value*/) {}
109 virtual void apply(const osg::Vec4s& /*in_value*/) {}
111 virtual void apply(const osg::Vec2us& /*in_value*/) {}
112 virtual void apply(const osg::Vec3us& /*in_value*/) {}
113 virtual void apply(const osg::Vec4us& /*in_value*/) {}
115 virtual void apply(const osg::Vec2i& /*in_value*/) {}
116 virtual void apply(const osg::Vec3i& /*in_value*/) {}
117 virtual void apply(const osg::Vec4i& /*in_value*/) {}
119 virtual void apply(const osg::Vec2ui& /*in_value*/) {}
120 virtual void apply(const osg::Vec3ui& /*in_value*/) {}
121 virtual void apply(const osg::Vec4ui& /*in_value*/) {}
123 virtual void apply(const osg::Vec2f& /*in_value*/) {}
124 virtual void apply(const osg::Vec3f& /*in_value*/) {}
125 virtual void apply(const osg::Vec4f& /*in_value*/) {}
127 virtual void apply(const osg::Vec2d& /*in_value*/) {}
128 virtual void apply(const osg::Vec3d& /*in_value*/) {}
129 virtual void apply(const osg::Vec4d& /*in_value*/) {}
131 virtual void apply(const osg::Quat& /*in_value*/) {}
132 virtual void apply(const osg::Plane& /*in_value*/) {}
133 virtual void apply(const osg::Matrixf& /*in_value*/) {}
134 virtual void apply(const osg::Matrixd& /*in_value*/) {}
135 virtual void apply(const osg::BoundingBoxf& /*in_value*/) {}
136 virtual void apply(const osg::BoundingBoxd& /*in_value*/) {}
137 virtual void apply(const osg::BoundingSpheref& /*in_value*/) {}
138 virtual void apply(const osg::BoundingSphered& /*in_value*/) {}
142 class SetValueVisitor
145 virtual ~SetValueVisitor() {}
146 virtual void apply(bool& /*in_value*/) {}
147 virtual void apply(char& /*in_value*/) {}
148 virtual void apply(unsigned char& /*in_value*/) {}
149 virtual void apply(short& /*in_value*/) {}
150 virtual void apply(unsigned short& /*in_value*/) {}
151 virtual void apply(int& /*in_value*/) {}
152 virtual void apply(unsigned int& /*in_value*/) {}
153 virtual void apply(float& /*in_value*/) {}
154 virtual void apply(double& /*in_value*/) {}
155 virtual void apply(std::string& /*in_value*/) {}
157 virtual void apply(osg::Vec2b& /*in_value*/) {}
158 virtual void apply(osg::Vec3b& /*in_value*/) {}
159 virtual void apply(osg::Vec4b& /*in_value*/) {}
161 virtual void apply(osg::Vec2ub& /*in_value*/) {}
162 virtual void apply(osg::Vec3ub& /*in_value*/) {}
163 virtual void apply(osg::Vec4ub& /*in_value*/) {}
165 virtual void apply(osg::Vec2s& /*in_value*/) {}
166 virtual void apply(osg::Vec3s& /*in_value*/) {}
167 virtual void apply(osg::Vec4s& /*in_value*/) {}
169 virtual void apply(osg::Vec2us& /*in_value*/) {}
170 virtual void apply(osg::Vec3us& /*in_value*/) {}
171 virtual void apply(osg::Vec4us& /*in_value*/) {}
173 virtual void apply(osg::Vec2i& /*in_value*/) {}
174 virtual void apply(osg::Vec3i& /*in_value*/) {}
175 virtual void apply(osg::Vec4i& /*in_value*/) {}
177 virtual void apply(osg::Vec2ui& /*in_value*/) {}
178 virtual void apply(osg::Vec3ui& /*in_value*/) {}
179 virtual void apply(osg::Vec4ui& /*in_value*/) {}
181 virtual void apply(osg::Vec2f& /*in_value*/) {}
182 virtual void apply(osg::Vec3f& /*in_value*/) {}
183 virtual void apply(osg::Vec4f& /*in_value*/) {}
185 virtual void apply(osg::Vec2d& /*in_value*/) {}
186 virtual void apply(osg::Vec3d& /*in_value*/) {}
187 virtual void apply(osg::Vec4d& /*in_value*/) {}
189 virtual void apply(osg::Quat& /*in_value*/) {}
190 virtual void apply(osg::Plane& /*in_value*/) {}
191 virtual void apply(osg::Matrixf& /*in_value*/) {}
192 virtual void apply(osg::Matrixd& /*in_value*/) {}
193 virtual void apply(osg::BoundingBoxf& /*in_value*/) {}
194 virtual void apply(osg::BoundingBoxd& /*in_value*/) {}
195 virtual void apply(osg::BoundingSpheref& /*in_value*/) {}
196 virtual void apply(osg::BoundingSphered& /*in_value*/) {}
199 virtual bool get(GetValueVisitor& /*gvv*/) const { return false; }
200 virtual bool set(SetValueVisitor& /*gvv*/) { return false; }
203 bool getScalarValue(T& value) { GetScalarValue<T> gsv; if (get(gsv) && gsv.set) { value = gsv.value; return true; } else return false; }
206 bool setScalarValue(T value) { SetScalarValue<T> ssv(value); return set(ssv) && ssv.set; }
209 virtual ~ValueObject() {}
213class GetScalarValue : public ValueObject::GetValueVisitor
217 GetScalarValue() : set(false), value(0) {}
222 virtual void apply(bool in_value) { value = in_value ? 1 : 0; set = true; }
223 virtual void apply(char in_value) { value = in_value; set = true; }
224 virtual void apply(unsigned char in_value) { value = in_value; set = true; }
225 virtual void apply(short in_value) { value = in_value; set = true; }
226 virtual void apply(unsigned short in_value) { value = in_value; set = true; }
227 virtual void apply(int in_value) { value = in_value; set = true; }
228 virtual void apply(unsigned int in_value) { value = in_value; set = true; }
229 virtual void apply(float in_value) { value = in_value; set = true; }
230 virtual void apply(double in_value) { value = in_value; set = true; }
233class GetScalarValue <bool> : public ValueObject::GetValueVisitor
237 GetScalarValue() : set(false), value(0) {}
242 virtual void apply(bool in_value) { value = in_value; set = true; }
243 virtual void apply(char in_value) { value = in_value != 0; set = true; }
244 virtual void apply(unsigned char in_value) { value = in_value != 0; set = true; }
245 virtual void apply(short in_value) { value = in_value != 0; set = true; }
246 virtual void apply(unsigned short in_value) { value = in_value != 0; set = true; }
247 virtual void apply(int in_value) { value = in_value != 0; set = true; }
248 virtual void apply(unsigned int in_value) { value = in_value != 0; set = true; }
249 virtual void apply(float in_value) { value = in_value != 0.0f; set = true; }
250 virtual void apply(double in_value) { value = in_value != 0.0; set = true; }
254class SetScalarValue : public ValueObject::SetValueVisitor
258 SetScalarValue(T in_value) : set(false), value(in_value) {}
263 virtual void apply(bool& in_value) { in_value=(value!=0); set = true;}
264 virtual void apply(char& in_value) { in_value=value; set = true;}
265 virtual void apply(unsigned char& in_value) { in_value=value; set = true;}
266 virtual void apply(short& in_value) { in_value=value; set = true;}
267 virtual void apply(unsigned short& in_value) { in_value=value; set = true;}
268 virtual void apply(int& in_value) { in_value=value; set = true;}
269 virtual void apply(unsigned int& in_value) { in_value=value; set = true;}
270 virtual void apply(float& in_value) { in_value=value; set = true;}
271 virtual void apply(double& in_value) { in_value=value; set = true;}
274template< typename T >
275struct ValueObjectClassNameTrait
277 static const char* className() { return "TemplateValueObject"; }
281template< typename T >
282class TemplateValueObject : public ValueObject
286 TemplateValueObject():
290 TemplateValueObject(const T& value) :
294 TemplateValueObject(const std::string& name, const T& value) :
298 TemplateValueObject(const TemplateValueObject& rhs, const osg::CopyOp copyop=osg::CopyOp::SHALLOW_COPY) :
299 ValueObject(rhs,copyop),
300 _value(rhs._value) {}
302 virtual Object* cloneType() const { return new TemplateValueObject(); }
303 virtual Object* clone(const CopyOp& copyop) const { return new TemplateValueObject(*this, copyop); }
304 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const TemplateValueObject*>(obj)!=NULL; }
305 virtual const char* libraryName() const { return "osg"; }
306 virtual const char* className() const { return ValueObjectClassNameTrait<T>::className(); }
308 void setValue(const T& value) { _value = value; }
309 const T& getValue() const { return _value; }
311 virtual bool get(GetValueVisitor& gvv) const { gvv.apply(_value); return true; }
312 virtual bool set(SetValueVisitor& svv) { svv.apply(_value); return true; }
316 virtual ~TemplateValueObject() {}
317 static const char* s_TemplateValueObject_className;
322#define META_ValueObject(TYPE,NAME) \
323 template<> struct ValueObjectClassNameTrait<TYPE> { static const char* className() { return #NAME; } }; \
324 typedef TemplateValueObject<TYPE> NAME;
326META_ValueObject(std::string, StringValueObject)
327META_ValueObject(bool, BoolValueObject)
328META_ValueObject(char, CharValueObject)
329META_ValueObject(unsigned char, UCharValueObject)
330META_ValueObject(short, ShortValueObject)
331META_ValueObject(unsigned short, UShortValueObject)
332META_ValueObject(int, IntValueObject)
333META_ValueObject(unsigned int, UIntValueObject)
334META_ValueObject(float, FloatValueObject)
335META_ValueObject(double, DoubleValueObject)
336META_ValueObject(Vec2f, Vec2fValueObject)
337META_ValueObject(Vec3f, Vec3fValueObject)
338META_ValueObject(Vec4f, Vec4fValueObject)
339META_ValueObject(Vec2d, Vec2dValueObject)
340META_ValueObject(Vec3d, Vec3dValueObject)
341META_ValueObject(Vec4d, Vec4dValueObject)
342META_ValueObject(Quat, QuatValueObject)
343META_ValueObject(Plane, PlaneValueObject)
344META_ValueObject(Matrixf, MatrixfValueObject)
345META_ValueObject(Matrixd, MatrixdValueObject)
346META_ValueObject(BoundingBoxf, BoundingBoxfValueObject)
347META_ValueObject(BoundingBoxd, BoundingBoxdValueObject)
348META_ValueObject(BoundingSpheref, BoundingSpherefValueObject)
349META_ValueObject(BoundingSphered, BoundingSpheredValueObject)
351/** provide implementation of osg::Object::getUserValue(..) template*/
353bool osg::Object::getUserValue(const std::string& name, T& value) const
355 typedef TemplateValueObject<T> UserValueObject;
357 const osg::UserDataContainer* udc = asUserDataContainer();
358 if (!udc) udc = _userDataContainer;
360 if (!udc) return false;
362 const Object* obj = udc->getUserObject(name);
363 if (obj && typeid(*obj)==typeid(UserValueObject))
365 const UserValueObject* uvo = static_cast<const UserValueObject*>(obj);
366 value = uvo->getValue();
375/** provide implementation of osg::Object::setUserValue(..) template.*/
377void osg::Object::setUserValue(const std::string& name, const T& value)
379 typedef TemplateValueObject<T> UserValueObject;
381 osg::UserDataContainer* udc = asUserDataContainer();
384 getOrCreateUserDataContainer();
385 udc = _userDataContainer;
388 unsigned int i = udc->getUserObjectIndex(name);
389 if (i<udc->getNumUserObjects())
391 Object* obj = udc->getUserObject(i);
392 if (typeid(*obj)==typeid(UserValueObject))
394 UserValueObject* uvo = static_cast<UserValueObject*>(obj);
395 uvo->setValue(value);
399 udc->setUserObject(i, new UserValueObject(name, value));
404 udc->addUserObject(new UserValueObject(name,value));
409template<class P, class T>
410T* getOrCreateUserObjectOfType(P* parent)
413 const char* name = typeid(T).name();
414 osg::UserDataContainer* udc = parent->getOrCreateUserDataContainer();
415 unsigned int index = udc->getUserObjectIndex(name);
416 if (index<udc->getNumUserObjects())
418 osg::Object* userObject = udc->getUserObject(index);
419 if (typeid(*userObject)==typeid(T))
421 object = static_cast<T*>(userObject);
422 // OSG_NOTICE<<"Reusing "<<name<<std::endl;
426 // OSG_NOTICE<<"Replacing "<<name<<", original object "<<userObject->className()<<std::endl;
429 object->setName(name);
430 udc->setUserObject(index, object);
436 object->setName(name);
437 udc->addUserObject(object);
438 // OSG_NOTICE<<"Creating new "<<name<<std::endl;