void AnnotationEventCallback::operator()( osg::Node* node, osg::NodeVisitor* nv ) { osgGA::EventVisitor* ev = static_cast<osgGA::EventVisitor*>(nv); osgGA::EventVisitor::EventList& events = ev->getEvents(); osgViewer::View* view = static_cast<osgViewer::View*>(ev->getActionAdapter()); for( osgGA::EventVisitor::EventList::const_iterator e = events.begin(); e != events.end(); ++e ) { osgGA::GUIEventAdapter* ea = e->get(); if ( ea->getEventType() == osgGA::GUIEventAdapter::MOVE || ea->getEventType() == osgGA::GUIEventAdapter::DRAG ) { _args.x = ea->getX(); _args.y = ea->getY(); } else if ( ea->getEventType() == osgGA::GUIEventAdapter::PUSH ) { _mouseDown = true; _args.x = ea->getX(); _args.y = ea->getY(); _args.buttons = ea->getButtonMask(); _args.modkeys = ea->getModKeyMask(); Picker picker( view, node ); Picker::Hits hits; if ( picker.pick( _args.x, _args.y, hits ) ) { std::set<AnnotationNode*> fired; // prevent multiple hits on the same instance for( Picker::Hits::const_iterator h = hits.begin(); h != hits.end(); ++h ) { AnnotationNode* anno = picker.getNode<AnnotationNode>( *h ); if ( anno && fired.find(anno) == fired.end() ) { fireEvent( &AnnotationEventHandler::onClick, anno ); fired.insert( anno ); //break; } } } } else if ( ea->getEventType() == osgGA::GUIEventAdapter::RELEASE ) { _mouseDown = false; } else if ( ea->getEventType() == osgGA::GUIEventAdapter::FRAME && _hoverEnabled && !_mouseDown ) { //Insert all the currently hovered annotations into a set to be unhoverd std::set<AnnotationNode*> toUnHover; for( std::set<AnnotationNode*>::iterator i = _hovered.begin(); i != _hovered.end(); ++i ) { toUnHover.insert( *i ); } Picker picker( view, node ); Picker::Hits hits; if ( picker.pick( _args.x, _args.y, hits ) ) { for( Picker::Hits::const_iterator h = hits.begin(); h != hits.end(); ++h ) { const Picker::Hit& hit = *h; AnnotationNode* anno = picker.getNode<AnnotationNode>( hit ); if ( anno ) { //If the annotation ins't current hovered, add it to the list of new hovered items if ( _hovered.find(anno) == _hovered.end() ) { _hovered.insert( anno ); fireEvent( &AnnotationEventHandler::onHoverEnter, anno ); } //It's still hovered, so don't unhover it toUnHover.erase( anno ); //break; } } } //The unhovered list now contains all the annotations that were hovered on the previous frame that need to be unhovered //and removed from the previous hover list for( std::set<AnnotationNode*>::iterator i = toUnHover.begin(); i != toUnHover.end(); ++i ) { _hovered.erase( *i ); fireEvent( &AnnotationEventHandler::onHoverLeave, *i ); } } } traverse(node,nv); }
bool FeatureQueryTool::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) { bool handled = false; bool attempt; if ( _inputPredicate.valid() ) { attempt = _inputPredicate->accept(ea); } else { attempt = ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && _mouseDown && fabs(ea.getX()-_mouseDownX) <= 3.0 && fabs(ea.getY()-_mouseDownY) <= 3.0; } if ( attempt ) { osg::View* view = aa.asView(); Picker picker( dynamic_cast<osgViewer::View*>(view), _mapNode->getModelLayerGroup() ); Picker::Hits hits; if ( picker.pick( ea.getX(), ea.getY(), hits ) ) { // find the closest indexed feature to the camera. It must be a feature // that is not only closest, but exists in the index as well. FeatureSourceIndexNode* closestIndex = 0L; FeatureID closestFID; double closestDistance = DBL_MAX; osg::Vec3d closestWorldPt; for(Picker::Hits::iterator hit = hits.begin(); hit != hits.end(); ++hit ) { FeatureSourceIndexNode* index = picker.getNode<FeatureSourceIndexNode>( *hit ); if ( index && (hit->distance < closestDistance) ) { FeatureID fid; if ( index->getFID( hit->drawable, hit->primitiveIndex, fid ) ) { closestIndex = index; closestFID = fid; closestDistance = hit->distance; closestWorldPt = hit->matrix.valid() ? hit->localIntersectionPoint * (*hit->matrix.get()) : hit->localIntersectionPoint; } } } if ( closestIndex ) { OE_DEBUG << LC << "HIT: feature ID = " << (unsigned)closestFID << std::endl; Callback::EventArgs args; args._ea = &ea; args._aa = &aa; args._worldPoint = closestWorldPt; for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ) { if ( i->valid() ) { i->get()->onHit( closestIndex, closestFID, args ); ++i; } else { i = _callbacks.erase( i ); } } handled = true; } } if ( !handled ) { OE_DEBUG << LC << "miss" << std::endl; Callback::EventArgs args; args._ea = &ea; args._aa = &aa; for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ) { if ( i->valid() ) { i->get()->onMiss( args ); ++i; } else { i = _callbacks.erase( i ); } } } _mouseDown = false; } // unmodified left mouse click else if ( ea.getEventType() == osgGA::GUIEventAdapter::PUSH && ea.getModKeyMask() == 0 && ea.getButtonMask() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) { _mouseDown = true; _mouseDownX = ea.getX(); _mouseDownY = ea.getY(); } return handled; }