From a6f3e0af78eef2d8b6c429d8e833949afa8f4466 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 31 Oct 2012 16:07:23 +0000 Subject: [PATCH] Added event and update callbacks to pass up changes to the mouse position to the ImageSequence::seek() to control which images is selected based on mouse x position --- include/osgPresentation/SlideEventHandler | 70 ++++++++++++++++++-- include/osgPresentation/SlideShowConstructor | 3 + src/osgPlugins/p3d/ReaderWriterP3D.cpp | 2 +- src/osgPresentation/SlideEventHandler.cpp | 45 ++++++++++--- src/osgPresentation/SlideShowConstructor.cpp | 20 +++++- 5 files changed, 124 insertions(+), 16 deletions(-) diff --git a/include/osgPresentation/SlideEventHandler b/include/osgPresentation/SlideEventHandler index bf53e5400..cfe730532 100644 --- a/include/osgPresentation/SlideEventHandler +++ b/include/osgPresentation/SlideEventHandler @@ -15,6 +15,8 @@ #include #include +#include +#include #include #include @@ -194,6 +196,69 @@ 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: @@ -269,9 +334,6 @@ public: void setRequestReload(bool flag); bool getRequestReload() const { return _requestReload; } - void setNormalizedMousePosition(const osg::Vec2& pos) { _normalizedMousePosition = pos; } - const osg::Vec2& getNormalizedMousePosition() const { return _normalizedMousePosition; } - protected: ~SlideEventHandler() {} @@ -326,8 +388,6 @@ protected: osg::ref_ptr _compileSlideCallback; bool _requestReload; - - osg::Vec2 _normalizedMousePosition; }; } diff --git a/include/osgPresentation/SlideShowConstructor b/include/osgPresentation/SlideShowConstructor index 6e27443c4..25214d9cf 100644 --- a/include/osgPresentation/SlideShowConstructor +++ b/include/osgPresentation/SlideShowConstructor @@ -521,6 +521,9 @@ protected: std::string _presentationName; double _presentationDuration; + osg::ref_ptr _propertyManager; + osg::ref_ptr _propertyEventCallback; + osg::ref_ptr _root; osg::ref_ptr _presentationSwitch; diff --git a/src/osgPlugins/p3d/ReaderWriterP3D.cpp b/src/osgPlugins/p3d/ReaderWriterP3D.cpp index 821e4df02..64d4e2415 100644 --- a/src/osgPlugins/p3d/ReaderWriterP3D.cpp +++ b/src/osgPlugins/p3d/ReaderWriterP3D.cpp @@ -2179,7 +2179,7 @@ osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Inp { osgPresentation::SlideEventHandler* seh = new osgPresentation::SlideEventHandler; seh->set(presentation_node.get()); - presentation_node->setEventCallback(seh); + presentation_node->addEventCallback(seh); } } return presentation_node.release(); diff --git a/src/osgPresentation/SlideEventHandler.cpp b/src/osgPresentation/SlideEventHandler.cpp index aca323866..ef2936189 100644 --- a/src/osgPresentation/SlideEventHandler.cpp +++ b/src/osgPresentation/SlideEventHandler.cpp @@ -57,6 +57,40 @@ void LayerAttributes::callLeaveCallbacks(osg::Node* node) } } +void ImageSequenceUpdateCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) +{ + float x; + if (_propertyManager->getProperty(_propertyName,x)) + { + double xMin = -1.0; + double xMax = 1.0; + double position = ((double)x-xMin)/(xMax-xMin)*_imageSequence->getLength(); + + _imageSequence->seek(position); + } + else + { + OSG_INFO<<"ImageSequenceUpdateCallback::operator() Could not find property : "<<_propertyName<setProperty("mouse.x",ea.getX()); + _propertyManager->setProperty("mouse.x_normalized",ea.getXnormalized()); + _propertyManager->setProperty("mouse.y",ea.getX()); + _propertyManager->setProperty("mouse.y_normalized",ea.getYnormalized()); + + return false; +} + + struct InteractiveImageSequenceOperator : public ObjectOperator { @@ -90,10 +124,7 @@ struct InteractiveImageSequenceOperator : public ObjectOperator void set(SlideEventHandler* seh) { - OSG_NOTICE<<"Mouse x position is : "<getNormalizedMousePosition().x()<(seh->getNormalizedMousePosition().x())+1.0)*0.5*_imageSequence->getLength(); - - _imageSequence->seek(position); + OSG_NOTICE<<"InteractiveImageSequenceOperator::set(..)"< _imageSequence; @@ -694,8 +725,7 @@ SlideEventHandler::SlideEventHandler(osgViewer::Viewer* viewer): _timeDelayOnNewSlideWithMovies(0.25f), _minimumTimeBetweenKeyPresses(0.25), _timeLastKeyPresses(-1.0), - _requestReload(false), - _normalizedMousePosition(0.0f,0.0f) + _requestReload(false) { s_seh = this; } @@ -789,7 +819,6 @@ double SlideEventHandler::getCurrentTimeDelayBetweenSlides() const return _timePerSlide; } - void SlideEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv) { osgGA::EventVisitor* ev = dynamic_cast(nv); @@ -821,8 +850,6 @@ bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction } //else OSG_NOTICE<<"SlideEventHandler::handle() "<getScreenHeight(); _slideWidth = ds->getScreenWidth(); _slideDistance = ds->getScreenDistance(); @@ -263,6 +266,10 @@ void SlideShowConstructor::createPresentation() if (_loopPresentation) _root->addDescription("loop"); if (_autoSteppingActive) _root->addDescription("auto"); + + //_root->addEventCallback(_propertyEventCallback.get()); + + _presentationSwitch->setEventCallback(_propertyEventCallback.get()); } LayerAttributes* SlideShowConstructor::getOrCreateLayerAttributes(osg::Node* node) @@ -1101,6 +1108,12 @@ void SlideShowConstructor::addImage(const std::string& filename, const PositionD pictureStateSet->setMode(GL_BLEND, osg::StateAttribute::ON); } + osg::ImageSequence* imageSequence = dynamic_cast(image.get()); + if (imageSequence && imageData.imageSequenceInteractionMode==ImageData::USE_MOUSE_X_POSITION) + { + subgraph->setUpdateCallback(new osgPresentation::ImageSequenceUpdateCallback(imageSequence, _propertyManager.get(), "mouse.x_normalized")); + } + // attached any rotation if (positionData.rotation[0]!=0.0) { @@ -1116,7 +1129,6 @@ void SlideShowConstructor::addImage(const std::string& filename, const PositionD subgraph = animation_transform; } - // attached any animation osg::AnimationPathCallback* animation = getAnimationPathCallback(positionData); if (animation) @@ -1283,6 +1295,12 @@ void SlideShowConstructor::addStereoImagePair(const std::string& filenameLeft, c subgraph->addChild(pictureLeft); subgraph->addChild(pictureRight); + osg::ImageSequence* imageSequence = dynamic_cast(imageLeft.get()); + if (imageSequence && imageDataLeft.imageSequenceInteractionMode==ImageData::USE_MOUSE_X_POSITION) + { + subgraph->setUpdateCallback(new osgPresentation::ImageSequenceUpdateCallback(imageSequence, _propertyManager.get(), "mouse.x_normalized")); + } + // attach any meterial animation. if (positionData.requiresMaterialAnimation()) subgraph = attachMaterialAnimation(subgraph,positionData)->asGroup();