Show
Ignore:
Timestamp:
06/12/06 13:32:11 (8 years ago)
Author:
robert
Message:

Revamped osgkeyboardmouse to use the osgGA.

Files:
1 modified

Legend:

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

    r4955 r5173  
    1717#include <osgDB/WriteFile> 
    1818 
     19#include <osgGA/EventQueue> 
     20#include <osgGA/EventVisitor> 
     21#include <osgGA/TrackballManipulator> 
     22#include <osgGA/StateSetManipulator> 
     23 
    1924#include <osgFX/Scribe> 
    2025 
    21  
    22 class CreateModelToSaveVisitor : public osg::NodeVisitor 
    23 { 
    24 public: 
    25  
    26     CreateModelToSaveVisitor(): 
    27         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)         
    28     { 
    29         _group = new osg::Group; 
    30         _addToModel = false; 
    31     } 
    32      
    33     virtual void apply(osg::Node& node) 
    34     { 
    35         osgFX::Scribe* scribe = dynamic_cast<osgFX::Scribe*>(&node); 
    36         if (scribe) 
    37         { 
    38             for(unsigned int i=0; i<scribe->getNumChildren(); ++i) 
    39             { 
    40                 _group->addChild(scribe->getChild(i)); 
    41             } 
    42         } 
    43         else 
    44         { 
    45             traverse(node); 
    46         } 
    47     } 
    48      
    49     osg::ref_ptr<osg::Group> _group; 
    50     bool _addToModel; 
    51 }; 
    52  
     26// Begining of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. 
    5327class MyKeyboardMouseCallback : public Producer::KeyboardMouseCallback 
    5428{ 
    5529public: 
    5630 
    57     MyKeyboardMouseCallback(osgUtil::SceneView* sceneView) : 
    58         Producer::KeyboardMouseCallback(), 
    59         _mx(0.0f),_my(0.0f),_mbutton(0), 
     31    MyKeyboardMouseCallback(osgGA::EventQueue* eventQueue) : 
    6032        _done(false), 
    61         _trackBall(new Producer::Trackball), 
    62         _sceneView(sceneView) 
    63     { 
    64         resetTrackball(); 
    65         _mouseMovingOnPreviousRelease = false; 
     33        _eventQueue(eventQueue) 
     34    { 
     35    } 
     36 
     37    virtual void shutdown() 
     38    { 
     39        _done = true;  
    6640    } 
    6741 
     
    7044        if (key==Producer::KeyChar_Escape) 
    7145                    shutdown(); 
    72     } 
    73  
    74     virtual void shutdown() 
    75     { 
    76         _done = true;  
     46 
     47        _eventQueue->keyPress( (osgGA::GUIEventAdapter::KeySymbol) key ); 
     48    } 
     49 
     50    virtual void specialKeyRelease( Producer::KeyCharacter key ) 
     51    { 
     52        _eventQueue->keyRelease( (osgGA::GUIEventAdapter::KeySymbol) key ); 
    7753    } 
    7854 
    7955    virtual void keyPress( Producer::KeyCharacter key) 
    8056    { 
    81         if (key==' ') resetTrackball(); 
    82         else if (key=='o') saveSelectedModel(); 
     57        _eventQueue->keyPress( (osgGA::GUIEventAdapter::KeySymbol) key ); 
     58    } 
     59 
     60    virtual void keyRelease( Producer::KeyCharacter key) 
     61    { 
     62        _eventQueue->keyRelease( (osgGA::GUIEventAdapter::KeySymbol) key ); 
    8363    } 
    8464 
    8565    virtual void mouseMotion( float mx, float my )  
    8666    { 
    87         _mx = mx; 
    88         _my = my; 
     67        _eventQueue->mouseMotion( mx, my ); 
    8968    } 
    9069 
    9170    virtual void buttonPress( float mx, float my, unsigned int mbutton )  
    9271    { 
    93          _mx = mx; 
    94          _my = my; 
    95          _mbutton |= (1<<(mbutton-1)); 
    96           
    97          _mx_buttonPress = _mx; 
    98          _my_buttonPress = _my; 
    99     } 
     72        _eventQueue->mouseButtonPress(mx, my, mbutton); 
     73    } 
     74     
    10075    virtual void buttonRelease( float mx, float my, unsigned int mbutton )  
    10176    { 
    102         _mx = mx; 
    103         _my = my; 
    104         _mbutton &= ~(1<<(mbutton-1)); 
    105          
    106         if (_mx==_mx_buttonPress && _my_buttonPress==_my) 
    107         { 
    108             if (!_mouseMovingOnPreviousRelease) 
    109             { 
    110                 // button press and release without moving so assume this means 
    111                 // the users wants to pick. 
    112                 pick(_mx,_my); 
    113             } 
    114             _mouseMovingOnPreviousRelease = false; 
    115         } 
    116         else 
    117         { 
    118             _mouseMovingOnPreviousRelease = true; 
    119         } 
     77        _eventQueue->mouseButtonRelease(mx, my, mbutton); 
    12078    } 
    12179 
    12280    bool done() { return _done; } 
    123     float mx()  { return _mx; } 
    124     float my()  { return _my; } 
    125     unsigned int mbutton()  { return _mbutton; } 
    126      
    127     void resetTrackball() 
    128     { 
    129         osg::Node* scene = _sceneView->getSceneData(); 
    130         if (scene) 
    131         { 
    132             const osg::BoundingSphere& bs = scene->getBound(); 
    133             if (bs.valid()) 
    134             { 
    135                 _trackBall->reset(); 
    136                 _trackBall->setOrientation( Producer::Trackball::Z_UP ); 
    137                 _trackBall->setDistance(bs.radius()*2.0f); 
    138                 _trackBall->translate(-bs.center().x(),-bs.center().y(),-bs.center().z()); 
    139             } 
    140         } 
    141     } 
    142      
    143     osg::Matrixd getViewMatrix() 
    144     { 
    145         _trackBall->input( mx(), my(), mbutton() ); 
    146         return osg::Matrixd(_trackBall->getMatrix().ptr()); 
    147     } 
    148      
    149     void pick(float x, float y) 
    150     { 
    151         osg::Node* scene = _sceneView->getSceneData(); 
    152         if (scene) 
    153         { 
    154             std::cout<<"Picking "<<x<<"\t"<<y<<std::endl; 
    155  
    156             int origX, origY, width, height; 
    157             _sceneView->getViewport(origX,origY,width,height); 
    158  
    159             // convert Producer's non dimensional x,y coords back into pixel coords. 
    160             int pixel_x = (int)((x+1.0f)*0.5f*(float)width); 
    161             int pixel_y = (int)((y+1.0f)*0.5f*(float)height); 
    162              
    163              
    164             osgUtil::PickVisitor pick(_sceneView->getViewport(), 
    165                                       _sceneView->getProjectionMatrix(), 
    166                                       _sceneView->getViewMatrix(), 
    167                                       pixel_x, pixel_y); 
    168  
    169             scene->accept(pick); 
    170              
    171             osgUtil::PickVisitor::LineSegmentHitListMap& segHitList = pick.getSegHitList(); 
    172             if (!segHitList.empty() && !segHitList.begin()->second.empty()) 
    173             { 
    174                 std::cout<<"Got hits"<<std::endl; 
    175                  
    176                 // get the hits for the first segment 
    177                 osgUtil::PickVisitor::HitList& hits = segHitList.begin()->second; 
    178                  
    179                 // just take the first hit - nearest the eye point. 
    180                 osgUtil::Hit& hit = hits.front(); 
    181                  
    182                 osg::NodePath& nodePath = hit._nodePath; 
    183                 osg::Node* node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0; 
    184                 osg::Group* parent = (nodePath.size()>=2)?dynamic_cast<osg::Group*>(nodePath[nodePath.size()-2]):0; 
    185  
    186                 if (node) std::cout<<"  Hits "<<node->className()<<" nodePath size"<<nodePath.size()<<std::endl; 
    187  
    188                 // now we try to decorate the hit node by the osgFX::Scribe to show that its been "picked" 
    189                 if (parent && node) 
    190                 { 
    191                  
    192                     std::cout<<"  parent "<<parent->className()<<std::endl; 
    193                      
    194                     osgFX::Scribe* parentAsScribe = dynamic_cast<osgFX::Scribe*>(parent); 
    195                     if (!parentAsScribe) 
    196                     { 
    197                         // node not already picked, so highlight it with an osgFX::Scribe 
    198                         osgFX::Scribe* scribe = new osgFX::Scribe(); 
    199                         scribe->addChild(node); 
    200                         parent->replaceChild(node,scribe); 
    201                     } 
    202                     else 
    203                     { 
    204                         // node already picked so we want to remove scribe to unpick it. 
    205                         osg::Node::ParentList parentList = parentAsScribe->getParents(); 
    206                         for(osg::Node::ParentList::iterator itr=parentList.begin(); 
    207                             itr!=parentList.end(); 
    208                             ++itr) 
    209                         { 
    210                             (*itr)->replaceChild(parentAsScribe,node); 
    211                         } 
    212                     } 
    213                 } 
    214  
    215             } 
    216              
    217         }         
    218          
    219     } 
    220  
    221     void saveSelectedModel() 
    222     { 
    223         CreateModelToSaveVisitor cmtsv; 
    224         _sceneView->getSceneData()->accept(cmtsv); 
    225          
    226         if (cmtsv._group->getNumChildren()>0) 
    227         { 
    228             osgDB::writeNodeFile(*cmtsv._group, "selected_model.osg"); 
    229         } 
    230     } 
    23181 
    23282private: 
    23383 
    234     float                               _mx, _my; 
    235     float                               _mx_buttonPress, _my_buttonPress; 
    236     unsigned int                        _mbutton; 
    237     bool                                _mouseMovingOnPreviousRelease; 
    238      
    23984    bool                                _done; 
    240      
    241     osg::ref_ptr<Producer::Trackball>   _trackBall; 
    242     osg::ref_ptr<osgUtil::SceneView>    _sceneView; 
     85    osg::ref_ptr<osgGA::EventQueue>     _eventQueue; 
    24386}; 
     87 
     88class MyActionAdapter : public osgGA::GUIActionAdapter, public osg::Referenced 
     89{ 
     90public: 
     91    // Override from GUIActionAdapter 
     92    virtual void requestRedraw() {} 
     93 
     94    // Override from GUIActionAdapter 
     95    virtual void requestContinuousUpdate(bool =true) {} 
     96 
     97    // Override from GUIActionAdapter 
     98    virtual void requestWarpPointer(float ,float ) {} 
     99     
     100}; 
     101 
     102// End of glue classes to adapter Producer's keyboard mouse events to osgGA's abstraction events. 
     103 
    244104 
    245105int main( int argc, char **argv ) 
     
    271131    sceneView->setDefaults(); 
    272132    sceneView->setSceneData(loadedModel.get()); 
    273  
     133     
     134    // create the event queue, note that Producer has the y axis increase upwards, like OpenGL, and contary to most Windowing toolkits, so 
     135    // we need to construct the event queue so that it knows about this convention. 
     136    osg::ref_ptr<osgGA::EventQueue> eventQueue = new osgGA::EventQueue(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); 
    274137 
    275138    // set up a KeyboardMouse to manage the events comming in from the RenderSurface 
     
    277140 
    278141    // create a KeyboardMouseCallback to handle the mouse events within this applications 
    279     osg::ref_ptr<MyKeyboardMouseCallback> kbmcb = new MyKeyboardMouseCallback(sceneView.get()); 
    280  
     142    osg::ref_ptr<MyKeyboardMouseCallback> kbmcb = new MyKeyboardMouseCallback(eventQueue.get()); 
     143 
     144    // create a tracball manipulator to move the camera around in response to keyboard/mouse events 
     145    osg::ref_ptr<osgGA::TrackballManipulator> cameraManipulator = new osgGA::TrackballManipulator; 
     146 
     147    // keep a list of event handlers to manipulate the application/scene with in response to keyboard/mouse events 
     148    typedef std::list< osg::ref_ptr<osgGA::GUIEventHandler> > EventHandlers; 
     149    EventHandlers eventHandlers; 
     150     
     151    osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator; 
     152    statesetManipulator->setStateSet(sceneView->getGlobalStateSet()); 
     153    eventHandlers.push_back(statesetManipulator.get()); 
     154     
     155    // create an event visitor to pass the events down to the scene graph nodes 
     156    osg::ref_ptr<osgGA::EventVisitor> eventVisitor = new osgGA::EventVisitor; 
     157 
     158    // create an action adapter to allow event handlers to request actions from the GUI. 
     159    osg::ref_ptr<MyActionAdapter> actionAdapter = new MyActionAdapter; 
    281160 
    282161    // record the timer tick at the start of rendering.     
     
    284163     
    285164    unsigned int frameNum = 0; 
     165 
     166    eventQueue->setStartTick(start_tick); 
     167 
     168    // set the mouse input range (note WindowSize name in appropriate here so osgGA::GUIEventAdapter API really needs looking at, Robert Osfield, June 2006). 
     169    // Producer defaults to using non-dimensional units, so we pass this onto osgGA, most windowing toolkits use pixel coords so use the window size instead. 
     170    eventQueue->getCurrentEventState()->setWindowSize(-1.0, -1.0, 1.0, 1.0); 
     171 
     172 
     173    // home the manipulator. 
     174    osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent =  eventQueue->createEvent(); 
     175    cameraManipulator->setNode(sceneView->getSceneData()); 
     176    cameraManipulator->home(*dummyEvent, *actionAdapter); 
     177 
    286178 
    287179    // main loop (note, window toolkits which take control over the main loop will require a window redraw callback containing the code below.) 
     
    296188        sceneView->setFrameStamp(frameStamp); 
    297189 
    298         // pass any keyboard mouse events onto the local keyboard mouse callback.         
     190        // pass any keyboard mouse events onto the local keyboard mouse callback. 
    299191        kbm->update( *kbmcb ); 
    300192         
    301         // set the view 
    302         sceneView->setViewMatrix(kbmcb->getViewMatrix()); 
     193        // create an event to signal the new frame. 
     194        eventQueue->frame(frameStamp->getReferenceTime()); 
     195 
     196        // get the event since the last frame. 
     197        osgGA::EventQueue::Events events; 
     198        eventQueue->takeEvents(events); 
     199 
     200        if (eventVisitor.valid()) 
     201        { 
     202            eventVisitor->setTraversalNumber(frameStamp->getFrameNumber()); 
     203        } 
     204 
     205        // dispatch the events in order of arrival. 
     206        for(osgGA::EventQueue::Events::iterator event_itr = events.begin(); 
     207            event_itr != events.end(); 
     208            ++event_itr) 
     209        { 
     210            bool handled = false; 
     211 
     212            if (eventVisitor.valid() && sceneView->getSceneData()) 
     213            { 
     214                eventVisitor->reset(); 
     215                eventVisitor->addEvent(event_itr->get()); 
     216                sceneView->getSceneData()->accept(*eventVisitor); 
     217                if (eventVisitor->getEventHandled()) 
     218                    handled = true; 
     219            } 
     220 
     221            if (cameraManipulator.valid() && !handled) 
     222            { 
     223                /*handled =*/ cameraManipulator->handle(*(*event_itr), *actionAdapter); 
     224            } 
     225 
     226            for(EventHandlers::iterator handler_itr=eventHandlers.begin(); 
     227                handler_itr!=eventHandlers.end() && !handled; 
     228                ++handler_itr) 
     229            {    
     230                handled = (*handler_itr)->handle(*(*event_itr),*actionAdapter,0,0); 
     231            } 
     232 
     233            // osg::notify(osg::NOTICE)<<"  Handled event "<<(*event_itr)->getTime()<<" "<< handled<<std::endl; 
     234 
     235        } 
     236 
     237 
     238        // update view matrices 
     239        if (cameraManipulator.valid()) 
     240        { 
     241            sceneView->setViewMatrix(cameraManipulator->getInverseMatrix()); 
     242        } 
    303243 
    304244        // update the viewport dimensions, incase the window has been resized.