Show
Ignore:
Timestamp:
06/12/06 16:04:40 (9 years ago)
Author:
robert
Message:

Added pick handler.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgkeyboardmouse/osgkeyboardmouse.cpp

    r5173 r5174  
    1010#include <osg/Timer> 
    1111#include <osg/io_utils> 
     12#include <osg/observer_ptr> 
    1213 
    1314#include <osgUtil/SceneView> 
     
    2425#include <osgFX/Scribe> 
    2526 
    26 // Begining of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. 
     27// ----------- Begining of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. 
    2728class MyKeyboardMouseCallback : public Producer::KeyboardMouseCallback 
    2829{ 
     
    100101}; 
    101102 
    102 // End of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. 
    103  
     103// ----------- End of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. 
     104 
     105 
     106class CreateModelToSaveVisitor : public osg::NodeVisitor 
     107{ 
     108public: 
     109 
     110    CreateModelToSaveVisitor(): 
     111        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)         
     112    { 
     113        _group = new osg::Group; 
     114        _addToModel = false; 
     115    } 
     116     
     117    virtual void apply(osg::Node& node) 
     118    { 
     119        osgFX::Scribe* scribe = dynamic_cast<osgFX::Scribe*>(&node); 
     120        if (scribe) 
     121        { 
     122            for(unsigned int i=0; i<scribe->getNumChildren(); ++i) 
     123            { 
     124                _group->addChild(scribe->getChild(i)); 
     125            } 
     126        } 
     127        else 
     128        { 
     129            traverse(node); 
     130        } 
     131    } 
     132     
     133    osg::ref_ptr<osg::Group> _group; 
     134    bool _addToModel; 
     135}; 
     136 
     137// class to handle events with a pick 
     138class PickHandler : public osgGA::GUIEventHandler { 
     139public:  
     140 
     141    PickHandler(osgUtil::SceneView* sceneView): 
     142        _sceneView(sceneView), 
     143        _mx(0.0),_my(0.0) {} 
     144 
     145    ~PickHandler() {} 
     146 
     147    bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) 
     148    { 
     149        switch(ea.getEventType()) 
     150        { 
     151            case(osgGA::GUIEventAdapter::KEYUP): 
     152            { 
     153                if (ea.getKey()=='s') 
     154                { 
     155                    saveSelectedModel(); 
     156                } 
     157                return false; 
     158            } 
     159            case(osgGA::GUIEventAdapter::PUSH): 
     160            case(osgGA::GUIEventAdapter::MOVE): 
     161            { 
     162                _mx = ea.getX(); 
     163                _my = ea.getY(); 
     164                return false; 
     165            } 
     166            case(osgGA::GUIEventAdapter::RELEASE): 
     167            { 
     168                if (_mx == ea.getX() && _my == ea.getY()) 
     169                { 
     170                    // only do a pick if the mouse hasn't moved 
     171                    pick(ea); 
     172                } 
     173                return true; 
     174            }     
     175 
     176            default: 
     177                return false; 
     178        } 
     179    } 
     180 
     181    void pick(const osgGA::GUIEventAdapter& ea) 
     182    { 
     183 
     184        osg::Node* scene = _sceneView.valid() ? _sceneView->getSceneData() : 0; 
     185        if (!scene) return; 
     186 
     187        // remap the mouse x,y into viewport coordinates. 
     188         
     189        float mx = _sceneView->getViewport()->x() + (int)((float)_sceneView->getViewport()->width()*(ea.getXnormalized()*0.5f+0.5f)); 
     190        float my = _sceneView->getViewport()->y() + (int)((float)_sceneView->getViewport()->height()*(ea.getYnormalized()*0.5f+0.5f)); 
     191    
     192        // do the pick traversal. 
     193        osgUtil::PickVisitor pick(_sceneView->getViewport(), 
     194                                  _sceneView->getProjectionMatrix(),  
     195                                  _sceneView->getViewMatrix(), mx, my); 
     196        scene->accept(pick); 
     197 
     198        osgUtil::PickVisitor::LineSegmentHitListMap& segHitList = pick.getSegHitList(); 
     199        if (!segHitList.empty() && !segHitList.begin()->second.empty()) 
     200        { 
     201            std::cout<<"Got hits"<<std::endl; 
     202 
     203            // get the hits for the first segment 
     204            osgUtil::PickVisitor::HitList& hits = segHitList.begin()->second; 
     205 
     206            // just take the first hit - nearest the eye point. 
     207            osgUtil::Hit& hit = hits.front(); 
     208 
     209            osg::NodePath& nodePath = hit._nodePath; 
     210            osg::Node* node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0; 
     211            osg::Group* parent = (nodePath.size()>=2)?dynamic_cast<osg::Group*>(nodePath[nodePath.size()-2]):0; 
     212 
     213            if (node) std::cout<<"  Hits "<<node->className()<<" nodePath size"<<nodePath.size()<<std::endl; 
     214 
     215            // now we try to decorate the hit node by the osgFX::Scribe to show that its been "picked" 
     216            if (parent && node) 
     217            { 
     218 
     219                std::cout<<"  parent "<<parent->className()<<std::endl; 
     220 
     221                osgFX::Scribe* parentAsScribe = dynamic_cast<osgFX::Scribe*>(parent); 
     222                if (!parentAsScribe) 
     223                { 
     224                    // node not already picked, so highlight it with an osgFX::Scribe 
     225                    osgFX::Scribe* scribe = new osgFX::Scribe(); 
     226                    scribe->addChild(node); 
     227                    parent->replaceChild(node,scribe); 
     228                } 
     229                else 
     230                { 
     231                    // node already picked so we want to remove scribe to unpick it. 
     232                    osg::Node::ParentList parentList = parentAsScribe->getParents(); 
     233                    for(osg::Node::ParentList::iterator itr=parentList.begin(); 
     234                        itr!=parentList.end(); 
     235                        ++itr) 
     236                    { 
     237                        (*itr)->replaceChild(parentAsScribe,node); 
     238                    } 
     239                } 
     240            } 
     241 
     242        } 
     243    } 
     244 
     245    void saveSelectedModel() 
     246    { 
     247        CreateModelToSaveVisitor cmtsv; 
     248        _sceneView->getSceneData()->accept(cmtsv); 
     249         
     250        if (cmtsv._group->getNumChildren()>0) 
     251        { 
     252            std::cout<<"Writing selected compoents to 'selected_model.osg'"<<std::endl; 
     253            osgDB::writeNodeFile(*cmtsv._group, "selected_model.osg"); 
     254        } 
     255    } 
     256 
     257protected: 
     258 
     259    osg::observer_ptr<osgUtil::SceneView> _sceneView; 
     260    float _mx,_my; 
     261}; 
    104262 
    105263int main( int argc, char **argv ) 
     
    152310    statesetManipulator->setStateSet(sceneView->getGlobalStateSet()); 
    153311    eventHandlers.push_back(statesetManipulator.get()); 
     312    eventHandlers.push_back(new PickHandler(sceneView.get())); 
    154313     
    155314    // create an event visitor to pass the events down to the scene graph nodes