예제 #1
0
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;
}