diff --git a/include/osgPresentation/PropertyManager b/include/osgPresentation/PropertyManager index 26e0011402c..d9c9ebdd830 100644 --- a/include/osgPresentation/PropertyManager +++ b/include/osgPresentation/PropertyManager @@ -62,7 +62,7 @@ protected: }; -class PropertyAnimation : public osg::NodeCallback +class OSGPRESENTATION_EXPORT PropertyAnimation : public osg::NodeCallback { public: PropertyAnimation(): @@ -93,12 +93,16 @@ public: virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); - virtual void update(); + virtual void update(osg::Node* node); + protected: osg::ref_ptr _pm; + void assign(osg::UserDataContainer* destination, osg::UserDataContainer* source); + void assign(osg::UserDataContainer* udc, osg::Object* obj); + KeyFrameMap _keyFrameMap; double _firstTime; diff --git a/include/osgPresentation/SlideEventHandler b/include/osgPresentation/SlideEventHandler index ea563116a8f..4d6ab3a2b8e 100644 --- a/include/osgPresentation/SlideEventHandler +++ b/include/osgPresentation/SlideEventHandler @@ -22,6 +22,7 @@ #include #include +#include namespace osgPresentation { @@ -237,69 +238,6 @@ protected: }; -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 and gets the value. - * To use this template method you need to include the osg/ValueObject header.*/ - template - bool getProperty(const std::string& name, T& value) const - { - OpenThreads::ScopedLock lock(_mutex); - return getUserValue(name, value); - } - - /** Convinience method that creates the osg::TemplateValueObject 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 - void setProperty(const std::string& name, const T& value) - { - OpenThreads::ScopedLock 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; - -}; - - -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 _imageSequence; - osg::ref_ptr _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; -}; - class OSGPRESENTATION_EXPORT SlideEventHandler : public osgGA::GUIEventHandler { public: diff --git a/include/osgPresentation/SlideShowConstructor b/include/osgPresentation/SlideShowConstructor index 9a6808531df..93d10830978 100644 --- a/include/osgPresentation/SlideShowConstructor +++ b/include/osgPresentation/SlideShowConstructor @@ -30,6 +30,7 @@ #include #include +#include namespace osgPresentation { @@ -436,6 +437,8 @@ public: void layerClickToDoOperation(const std::string& command, Operation operation, const JumpData& jumpData=JumpData()); void layerClickEventOperation(const KeyPosition& keyPos, const JumpData& jumpData=JumpData()); + void addPropertyAnimation(PresentationContext presentationContext, PropertyAnimation* propertyAnimation); + void addToCurrentLayer(osg::Node* subgraph); void addBullet(const std::string& bullet, PositionData& positionData, FontData& fontData); diff --git a/src/osgPlugins/p3d/ReaderWriterP3D.cpp b/src/osgPlugins/p3d/ReaderWriterP3D.cpp index 28797668655..6b7b4025b18 100644 --- a/src/osgPlugins/p3d/ReaderWriterP3D.cpp +++ b/src/osgPlugins/p3d/ReaderWriterP3D.cpp @@ -1,4 +1,4 @@ - /* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield +/* -*-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. @@ -122,6 +122,9 @@ class ReaderWriterP3DXML : public osgDB::ReaderWriter osg::Node* parseXmlGraph(osgDB::XmlNode* root, bool readOnlyHoldingPage, osgDB::Options* options) const; + bool parseProperties(osgDB::XmlNode* root, osg::UserDataContainer& udc) const; + bool parsePropertyAnimation(osgDB::XmlNode* root, osgPresentation::PropertyAnimation& pa) const; + void parseModel(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const; osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename, float scale) const; @@ -196,6 +199,7 @@ class ReaderWriterP3DXML : public osgDB::ReaderWriter bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::FontData& value) const; bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ModelData& value) const; bool getProperties(osgDB::XmlNode*cur, osgPresentation::SlideShowConstructor::ImageData& value) const; + bool getJumpProperties(osgDB::XmlNode*cur, osgPresentation::JumpData& jumpData) const; bool getKeyPositionInner(osgDB::XmlNode*cur, osgPresentation::KeyPosition& keyPosition) const; @@ -967,7 +971,101 @@ bool ReaderWriterP3DXML::getProperties(osgDB::XmlNode*cur, osgPresentation::Slid return propertiesRead; } -bool ReaderWriterP3DXML::getJumpProperties(osgDB::XmlNode*cur, osgPresentation::JumpData& jumpData) const +bool ReaderWriterP3DXML::parseProperties(osgDB::XmlNode* root, osg::UserDataContainer& udc) const +{ + bool readProperties = false; + OSG_NOTICE<<"Doing parseProperties()"<children.begin(); + itr != root->children.end(); + ++itr) + { + osgDB::XmlNode* cur = itr->get(); + + if (cur->name == "property") + { + std::string name; + std::string type; + + getProperty(cur, "name", name); + getProperty(cur, "type", type); + + if (type=="float") + { + float value; + std::stringstream str(cur->contents); + str>>value; + + udc.setUserValue(name, value); + readProperties = true; + + OSG_NOTICE<<"Adding property float "<contents); + str>>value; + + udc.setUserValue(name, value); + readProperties = true; + + OSG_NOTICE<<"Adding property int "<contents); + readProperties = true; + OSG_NOTICE<<"Adding property string "<contents<name<<"] expecting "<children.begin(); + itr != root->children.end(); + ++itr) + { + osgDB::XmlNode* cur = itr->get(); + + if (cur->name == "key_frame") + { + + double time; + if (getProperty(cur, "time", time)) + { + osg::ref_ptr udc = new osg::DefaultUserDataContainer; + if (parseProperties(cur, *udc)) + { + OSG_NOTICE<<"Adding keyframe"<"<name<<"] expecting "<contents.c_str())); } + else if (cur->name == "property_animation") + { + osg::ref_ptr pa = new osgPresentation::PropertyAnimation; + if (parsePropertyAnimation(cur,*pa)) + { + constructor.addPropertyAnimation(osgPresentation::SlideShowConstructor::CURRENT_LAYER, pa.get()); + } + } else if (getKeyPosition(cur, keyPosition)) { constructor.addLayerKey(keyPosition); @@ -1822,6 +1928,14 @@ void ReaderWriterP3DXML::parseSlide (osgPresentation::SlideShowConstructor& cons { constructor.setSlideDuration(osg::asciiToDouble(cur->contents.c_str())); } + else if (cur->name == "property_animation") + { + osg::ref_ptr pa = new osgPresentation::PropertyAnimation; + if (parsePropertyAnimation(cur,*pa)) + { + constructor.addPropertyAnimation(osgPresentation::SlideShowConstructor::CURRENT_SLIDE, pa.get()); + } + } else if (getKeyPosition(cur, keyPosition)) { constructor.addSlideKey(keyPosition); @@ -2518,6 +2632,14 @@ osg::Node* ReaderWriterP3DXML::parseXmlGraph(osgDB::XmlNode* root, bool readOnly std::cout<<"Defining template slide "<name == "property_animation") + { + osg::ref_ptr pa = new osgPresentation::PropertyAnimation; + if (parsePropertyAnimation(cur,*pa)) + { + constructor.addPropertyAnimation(osgPresentation::SlideShowConstructor::CURRENT_PRESENTATION, pa.get()); + } + } } osgDB::getDataFilePathList() = previousPaths; diff --git a/src/osgPresentation/PropertyManager.cpp b/src/osgPresentation/PropertyManager.cpp index 92ed5c25ebb..e0616672680 100644 --- a/src/osgPresentation/PropertyManager.cpp +++ b/src/osgPresentation/PropertyManager.cpp @@ -11,6 +11,7 @@ */ #include +#include using namespace osgPresentation; @@ -61,7 +62,7 @@ void PropertyAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv) { // Only update _firstTime the first time, when its value is still DBL_MAX if (_firstTime==DBL_MAX) _firstTime = time; - update(); + update(node); } } @@ -72,7 +73,8 @@ class MySetValueVisitor : public osg::ValueObject::SetValueVisitor { public: - MySetValueVisitor(double r1, double r2, osg::ValueObject* object2) + MySetValueVisitor(double in_r1, double in_r2, osg::ValueObject* in_object2): + _r1(in_r1), _r2(in_r2), _object2(in_object2) { } @@ -80,22 +82,24 @@ class MySetValueVisitor : public osg::ValueObject::SetValueVisitor void combineRealUserValue(T& value) const { typedef osg::TemplateValueObject UserValueObject; - const UserValueObject* uvo = object2 ? dynamic_cast(object2) : 0; + const UserValueObject* uvo = _object2 ? dynamic_cast(_object2) : 0; if (uvo) { value = value*_r1 + uvo->getValue()*_r2; } + OSG_NOTICE<<"combineRealUserValue r1="<<_r1<<", r2="<<_r2<<", value="< void combineIntegerUserValue(T& value) const { typedef osg::TemplateValueObject UserValueObject; - const UserValueObject* uvo = object2 ? dynamic_cast(object2) : 0; + const UserValueObject* uvo = _object2 ? dynamic_cast(_object2) : 0; if (uvo) { value = static_cast(static_cast(value)*_r1 + static_cast(uvo->getValue())*_r2); } + OSG_NOTICE<<"combineIntegerUserValue "< @@ -104,12 +108,13 @@ class MySetValueVisitor : public osg::ValueObject::SetValueVisitor if (_r1<_r2) // choose value2 if possible { typedef osg::TemplateValueObject UserValueObject; - const UserValueObject* uvo = object2 ? dynamic_cast(object2) : 0; + const UserValueObject* uvo = _object2 ? dynamic_cast(_object2) : 0; if (uvo) { value = uvo->getValue(); } } + OSG_NOTICE<<"combineDiscretUserValue "< @@ -153,14 +158,14 @@ class MySetValueVisitor : public osg::ValueObject::SetValueVisitor virtual void apply(osg::Matrixd& value) { combineMatrixUserValue(value); } double _r1, _r2; - osg::ValueObject* object2; + osg::ValueObject* _object2; }; -void PropertyAnimation::update() +void PropertyAnimation::update(osg::Node* node) { - double time = getAnimationTime(); + OSG_NOTICE<<"PropertyAnimation::update()"< result; + double time = getAnimationTime(); if (_keyFrameMap.empty()) return; @@ -169,7 +174,7 @@ void PropertyAnimation::update() { // need to copy first UserDataContainer OSG_NOTICE<<"PropertyAnimation::update() : copy first UserDataContainer"<second.get(), osg::CopyOp::DEEP_COPY_ALL); + assign(node->getOrCreateUserDataContainer(), itr->second.get()); } else if (itr!=_keyFrameMap.end()) { @@ -186,49 +191,93 @@ void PropertyAnimation::update() } else { - r1 = (time - itr_1->first)/delta_time; - r2 = 1.0-r1; + r2 = (time - itr_1->first)/delta_time; + r1 = 1.0-r2; } osg::UserDataContainer* p1 = itr_1->second.get(); osg::UserDataContainer* p2 = itr_2->second.get(); // clone all the properties from p1; - result = osg::clone(p1, osg::CopyOp::DEEP_COPY_ALL); + + osg::ref_ptr destination = node->getOrCreateUserDataContainer(); + + assign(destination.get(), p1); for(unsigned int i2=0; i2getNumUserObjects(); ++i2) { osg::Object* obj_2 = p2->getUserObject(i2); - unsigned int i1 = result->getUserObjectIndex(obj_2->getName()); - if (i1getNumUserObjects()) + unsigned int i1 = p1->getUserObjectIndex(obj_2->getName()); + if (i1getNumUserObjects()) { - osg::Object* obj_1 = result->getUserObject(i1); + osg::Object* obj_1 = p1->getUserObject(i1); osg::ValueObject* valueobject_1 = dynamic_cast(obj_1); osg::ValueObject* valueobject_2 = dynamic_cast(obj_2); - if (valueobject_1) + if (valueobject_1 && valueobject_2) { + osg::ref_ptr vo = osg::clone(valueobject_1); MySetValueVisitor mySetValue(r1, r2, valueobject_2); - valueobject_1->set(mySetValue); + vo->set(mySetValue); + assign(destination.get(), vo.get()); + } + else if (obj_1) + { + assign(destination.get(), obj_1); + } + else if (obj_2) + { + assign(destination.get(), obj_2); } } else { // need to insert property; - result->addUserObject(obj_2->clone(osg::CopyOp::DEEP_COPY_ALL)); + assign(destination.get(), obj_2); } } - - - OSG_NOTICE<<"PropertyAnimation::update() : Need to interpolate between two UserDataContainer, r1="<second.get(), osg::CopyOp::DEEP_COPY_ALL); + assign(node->getOrCreateUserDataContainer(), _keyFrameMap.rbegin()->second.get()); + } + +} + +void PropertyAnimation::assign(osg::UserDataContainer* destination, osg::UserDataContainer* source) +{ + if (!destination) return; + if (!source) return; + + for(unsigned int i=0; igetNumUserObjects(); ++i) + { + assign(destination, source->getUserObject(i)); + } +} + +void PropertyAnimation::assign(osg::UserDataContainer* udc, osg::Object* obj) +{ + if (!obj) return; + + unsigned int index = udc->getUserObjectIndex(obj); + if (index != udc->getNumUserObjects()) + { + OSG_NOTICE<<"Object already assigned to UserDataContainer"<getUserObjectIndex(obj->getName()); + if (index != udc->getNumUserObjects()) + { + OSG_NOTICE<<"Replacing object in UserDataContainer"<setUserObject(index, obj); + return; + } + + OSG_NOTICE<<"Assigned object to UserDataContainer"<addUserObject(obj); } diff --git a/src/osgPresentation/SlideShowConstructor.cpp b/src/osgPresentation/SlideShowConstructor.cpp index eebcb47d0aa..76741c782f0 100644 --- a/src/osgPresentation/SlideShowConstructor.cpp +++ b/src/osgPresentation/SlideShowConstructor.cpp @@ -624,6 +624,29 @@ void SlideShowConstructor::layerClickEventOperation(const KeyPosition& keyPos, c } +void SlideShowConstructor::addPropertyAnimation(PresentationContext presentationContext, PropertyAnimation* propertyAnimation) +{ + switch(presentationContext) + { + case(CURRENT_PRESENTATION): + OSG_NOTICE<<"Need to add PropertyAnimation to presentation."<addUpdateCallback(propertyAnimation); + break; + case(CURRENT_SLIDE): + OSG_NOTICE<<"Need to add PropertyAnimation to slide."<addUpdateCallback(propertyAnimation); + break; + case(CURRENT_LAYER): + OSG_NOTICE<<"Need to add PropertyAnimation to layer."<addUpdateCallback(propertyAnimation); + break; + } +} + + osg::Node* SlideShowConstructor::decorateSubgraphForPosition(osg::Node* node, PositionData& positionData) { osg::Node* subgraph = node;