2012-11-15 20:11:19 +08:00
|
|
|
/* -*-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
|
|
|
|
|
2012-11-16 23:40:41 +08:00
|
|
|
#include <osg/UserDataContainer>
|
2012-11-15 20:11:19 +08:00
|
|
|
#include <osg/ValueObject>
|
|
|
|
#include <osg/ImageSequence>
|
|
|
|
#include <osgGA/GUIEventHandler>
|
|
|
|
|
|
|
|
#include <osgPresentation/Export>
|
|
|
|
|
2012-11-30 22:21:45 +08:00
|
|
|
#include <sstream>
|
|
|
|
|
2012-11-15 20:11:19 +08:00
|
|
|
namespace osgPresentation
|
|
|
|
{
|
|
|
|
|
|
|
|
class PropertyManager : protected osg::Object
|
|
|
|
{
|
|
|
|
public:
|
2014-06-06 00:26:13 +08:00
|
|
|
|
2012-11-15 20:11:19 +08:00
|
|
|
PropertyManager() {}
|
|
|
|
PropertyManager(const PropertyManager& pm, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
|
|
|
|
osg::Object(pm,copyop) {}
|
|
|
|
|
|
|
|
META_Object(osgPresentation, PropertyManager)
|
2014-06-06 00:26:13 +08:00
|
|
|
|
2012-11-15 20:11:19 +08:00
|
|
|
/** 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(); }
|
2014-06-06 00:26:13 +08:00
|
|
|
|
2012-11-15 20:11:19 +08:00
|
|
|
protected:
|
|
|
|
|
|
|
|
mutable OpenThreads::Mutex _mutex;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2012-12-02 19:45:57 +08:00
|
|
|
extern OSGPRESENTATION_EXPORT const osg::Object* getUserObject(const osg::NodePath& nodepath, const std::string& name);
|
2012-11-30 22:21:45 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-02 19:45:57 +08:00
|
|
|
extern OSGPRESENTATION_EXPORT bool containsPropertyReference(const std::string& str);
|
2012-11-30 22:21:45 +08:00
|
|
|
|
|
|
|
struct PropertyReader
|
|
|
|
{
|
|
|
|
PropertyReader(const osg::NodePath& nodePath, const std::string& str):
|
2013-01-11 19:30:44 +08:00
|
|
|
_errorGenerated(false),
|
2012-11-30 22:21:45 +08:00
|
|
|
_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>
|
2013-01-11 19:30:44 +08:00
|
|
|
PropertyReader& operator>>( T& value ) { if (!read(value)) _errorGenerated=true; return *this; }
|
2012-11-30 22:21:45 +08:00
|
|
|
|
2013-01-11 19:30:44 +08:00
|
|
|
bool ok() { return !_sstream.fail() && !_errorGenerated; }
|
|
|
|
bool fail() { return _sstream.fail() || _errorGenerated; }
|
2012-11-30 22:21:45 +08:00
|
|
|
|
2013-01-11 19:30:44 +08:00
|
|
|
bool _errorGenerated;
|
2012-11-30 22:21:45 +08:00
|
|
|
osg::NodePath _nodePath;
|
2014-06-06 00:26:13 +08:00
|
|
|
std::istringstream _sstream;
|
2012-11-30 22:21:45 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-11-27 23:09:44 +08:00
|
|
|
class OSGPRESENTATION_EXPORT PropertyAnimation : public osg::NodeCallback
|
2012-11-16 23:40:41 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2012-11-30 23:43:31 +08:00
|
|
|
virtual void update(osg::Node& node);
|
2012-11-27 23:09:44 +08:00
|
|
|
|
2012-11-16 23:40:41 +08:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
osg::ref_ptr<PropertyManager> _pm;
|
|
|
|
|
2012-11-27 23:09:44 +08:00
|
|
|
void assign(osg::UserDataContainer* destination, osg::UserDataContainer* source);
|
|
|
|
void assign(osg::UserDataContainer* udc, osg::Object* obj);
|
|
|
|
|
2012-11-16 23:40:41 +08:00
|
|
|
KeyFrameMap _keyFrameMap;
|
|
|
|
|
|
|
|
double _firstTime;
|
|
|
|
double _latestTime;
|
|
|
|
bool _pause;
|
|
|
|
double _pauseTime;
|
2014-06-06 00:26:13 +08:00
|
|
|
|
2012-11-16 23:40:41 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-15 20:11:19 +08:00
|
|
|
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
|