/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield * * This software is open source and may be redistributed and/or modified under * the terms of the GNU General Public License (GPL) version 2.0. * The full license is in LICENSE.txt file included with this distribution,. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * include LICENSE.txt for more details. */ #ifndef PROPERTYMANAGER #define PROPERTYMANAGER 1 #include <osg/UserDataContainer> #include <osg/ValueObject> #include <osg/NodeCallback> #include <osg/ImageSequence> #include <osgGA/GUIEventHandler> #include <osgPresentation/Export> #include <sstream> namespace osgPresentation { class PropertyManager : protected osg::Object { public: PropertyManager() {} PropertyManager(const PropertyManager& pm, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): osg::Object(pm,copyop) {} META_Object(osgPresentation, PropertyManager) /** Convinience method that casts the named UserObject to osg::TemplateValueObject<T> and gets the value. * To use this template method you need to include the osg/ValueObject header.*/ template<typename T> bool getProperty(const std::string& name, T& value) const { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); return getUserValue(name, value); } /** Convinience method that creates the osg::TemplateValueObject<T> to store the * specified value and adds it as a named UserObject. * To use this template method you need to include the osg/ValueObject header. */ template<typename T> void setProperty(const std::string& name, const T& value) { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); return setUserValue(name, value); } int ref() const { return osg::Referenced::ref(); } int unref() const { return osg::Referenced::unref(); } protected: mutable OpenThreads::Mutex _mutex; }; extern OSGPRESENTATION_EXPORT const osg::Object* getUserObject(const osg::NodePath& nodepath, const std::string& name); template<typename T> bool getUserValue(const osg::NodePath& nodepath, const std::string& name, T& value) { typedef osg::TemplateValueObject<T> UserValueObject; const osg::Object* object = getUserObject(nodepath, name); const UserValueObject* uvo = dynamic_cast<const UserValueObject*>(object); if (uvo) { value = uvo->getValue(); return true; } else { return false; } } extern OSGPRESENTATION_EXPORT bool containsPropertyReference(const std::string& str); struct PropertyReader { PropertyReader(const osg::NodePath& nodePath, const std::string& str): _errorGenerated(false), _nodePath(nodePath), _sstream(str) {} template<typename T> bool read(T& value) { // skip white space. while(!_sstream.fail() && _sstream.peek()==' ') _sstream.ignore(); // check to see if a &propertyName is used. if (_sstream.peek()=='$') { std::string propertyName; _sstream.ignore(1); _sstream >> propertyName; OSG_NOTICE<<"Reading propertyName="<<propertyName<<std::endl; if (!_sstream.fail() && !propertyName.empty()) return getUserValue(_nodePath, propertyName, value); else return false; } else { _sstream >> value; OSG_NOTICE<<"Reading value="<<value<<std::endl; return !_sstream.fail(); } } template<typename T> PropertyReader& operator>>( T& value ) { if (!read(value)) _errorGenerated=true; return *this; } bool ok() { return !_sstream.fail() && !_errorGenerated; } bool fail() { return _sstream.fail() || _errorGenerated; } bool _errorGenerated; osg::NodePath _nodePath; std::istringstream _sstream; }; class OSGPRESENTATION_EXPORT PropertyAnimation : public osg::NodeCallback { public: PropertyAnimation(): _firstTime(DBL_MAX), _latestTime(0.0), _pause(false), _pauseTime(0.0) {} void setPropertyManager(PropertyManager* pm) { _pm = pm; } PropertyManager* getPropertyManager() const { return _pm.get(); } typedef std::map<double, osg::ref_ptr<osg::UserDataContainer> > KeyFrameMap; KeyFrameMap& getKeyFrameMap() { return _keyFrameMap; } const KeyFrameMap& getKeyFrameMap() const { return _keyFrameMap; } void addKeyFrame(double time, osg::UserDataContainer* udc) { _keyFrameMap[time] = udc; } virtual void reset(); void setPause(bool pause); bool getPause() const { return _pause; } double getAnimationTime() const; virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); virtual void update(osg::Node& node); protected: osg::ref_ptr<PropertyManager> _pm; void assign(osg::UserDataContainer* destination, osg::UserDataContainer* source); void assign(osg::UserDataContainer* udc, osg::Object* obj); KeyFrameMap _keyFrameMap; double _firstTime; double _latestTime; bool _pause; double _pauseTime; }; struct OSGPRESENTATION_EXPORT ImageSequenceUpdateCallback : public osg::NodeCallback { ImageSequenceUpdateCallback(osg::ImageSequence* is, PropertyManager* pm, const std::string& propertyName): _imageSequence(is), _propertyManager(pm), _propertyName(propertyName) {} virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); osg::ref_ptr<osg::ImageSequence> _imageSequence; osg::ref_ptr<PropertyManager> _propertyManager; std::string _propertyName; }; struct OSGPRESENTATION_EXPORT PropertyEventCallback : public osgGA::GUIEventHandler { PropertyEventCallback(PropertyManager* pm): _propertyManager(pm) {} virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&); osg::ref_ptr<PropertyManager> _propertyManager; }; } #endif