diff --git a/examples/osgkeyboardmouse/osgkeyboardmouse.cpp b/examples/osgkeyboardmouse/osgkeyboardmouse.cpp index 900dd1e02..7245190a9 100644 --- a/examples/osgkeyboardmouse/osgkeyboardmouse.cpp +++ b/examples/osgkeyboardmouse/osgkeyboardmouse.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -23,7 +24,7 @@ #include -// Begining of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. +// ----------- Begining of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. class MyKeyboardMouseCallback : public Producer::KeyboardMouseCallback { public: @@ -99,9 +100,166 @@ public: }; -// End of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. +// ----------- End of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. +class CreateModelToSaveVisitor : public osg::NodeVisitor +{ +public: + + CreateModelToSaveVisitor(): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) + { + _group = new osg::Group; + _addToModel = false; + } + + virtual void apply(osg::Node& node) + { + osgFX::Scribe* scribe = dynamic_cast(&node); + if (scribe) + { + for(unsigned int i=0; igetNumChildren(); ++i) + { + _group->addChild(scribe->getChild(i)); + } + } + else + { + traverse(node); + } + } + + osg::ref_ptr _group; + bool _addToModel; +}; + +// class to handle events with a pick +class PickHandler : public osgGA::GUIEventHandler { +public: + + PickHandler(osgUtil::SceneView* sceneView): + _sceneView(sceneView), + _mx(0.0),_my(0.0) {} + + ~PickHandler() {} + + bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) + { + switch(ea.getEventType()) + { + case(osgGA::GUIEventAdapter::KEYUP): + { + if (ea.getKey()=='s') + { + saveSelectedModel(); + } + return false; + } + case(osgGA::GUIEventAdapter::PUSH): + case(osgGA::GUIEventAdapter::MOVE): + { + _mx = ea.getX(); + _my = ea.getY(); + return false; + } + case(osgGA::GUIEventAdapter::RELEASE): + { + if (_mx == ea.getX() && _my == ea.getY()) + { + // only do a pick if the mouse hasn't moved + pick(ea); + } + return true; + } + + default: + return false; + } + } + + void pick(const osgGA::GUIEventAdapter& ea) + { + + osg::Node* scene = _sceneView.valid() ? _sceneView->getSceneData() : 0; + if (!scene) return; + + // remap the mouse x,y into viewport coordinates. + + float mx = _sceneView->getViewport()->x() + (int)((float)_sceneView->getViewport()->width()*(ea.getXnormalized()*0.5f+0.5f)); + float my = _sceneView->getViewport()->y() + (int)((float)_sceneView->getViewport()->height()*(ea.getYnormalized()*0.5f+0.5f)); + + // do the pick traversal. + osgUtil::PickVisitor pick(_sceneView->getViewport(), + _sceneView->getProjectionMatrix(), + _sceneView->getViewMatrix(), mx, my); + scene->accept(pick); + + osgUtil::PickVisitor::LineSegmentHitListMap& segHitList = pick.getSegHitList(); + if (!segHitList.empty() && !segHitList.begin()->second.empty()) + { + std::cout<<"Got hits"<second; + + // just take the first hit - nearest the eye point. + osgUtil::Hit& hit = hits.front(); + + osg::NodePath& nodePath = hit._nodePath; + osg::Node* node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0; + osg::Group* parent = (nodePath.size()>=2)?dynamic_cast(nodePath[nodePath.size()-2]):0; + + if (node) std::cout<<" Hits "<className()<<" nodePath size"<className()<(parent); + if (!parentAsScribe) + { + // node not already picked, so highlight it with an osgFX::Scribe + osgFX::Scribe* scribe = new osgFX::Scribe(); + scribe->addChild(node); + parent->replaceChild(node,scribe); + } + else + { + // node already picked so we want to remove scribe to unpick it. + osg::Node::ParentList parentList = parentAsScribe->getParents(); + for(osg::Node::ParentList::iterator itr=parentList.begin(); + itr!=parentList.end(); + ++itr) + { + (*itr)->replaceChild(parentAsScribe,node); + } + } + } + + } + } + + void saveSelectedModel() + { + CreateModelToSaveVisitor cmtsv; + _sceneView->getSceneData()->accept(cmtsv); + + if (cmtsv._group->getNumChildren()>0) + { + std::cout<<"Writing selected compoents to 'selected_model.osg'"< _sceneView; + float _mx,_my; +}; + int main( int argc, char **argv ) { if (argc<2) @@ -151,6 +309,7 @@ int main( int argc, char **argv ) osg::ref_ptr statesetManipulator = new osgGA::StateSetManipulator; statesetManipulator->setStateSet(sceneView->getGlobalStateSet()); eventHandlers.push_back(statesetManipulator.get()); + eventHandlers.push_back(new PickHandler(sceneView.get())); // create an event visitor to pass the events down to the scene graph nodes osg::ref_ptr eventVisitor = new osgGA::EventVisitor;