bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { if (ea.getHandled()) return false; osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); if (!view) return false; if (!_mapNode.valid()) return false; if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH) { Picker picker( view, this ); Picker::Hits hits; if ( picker.pick( ea.getX(), ea.getY(), hits ) ) { _dragging = true; //Check for and handle vertical dragging if necessary bool pressedAlt = _modKeyMask && (ea.getModKeyMask() & _modKeyMask) > 0; _elevationDragging = (_defaultMode == Dragger::DRAGMODE_VERTICAL && !pressedAlt) || (_defaultMode == Dragger::DRAGMODE_HORIZONTAL && pressedAlt); if (_elevationDragging) { _pointer.reset(); // set movement range // TODO: values 0.0 and 300000.0 are rather experimental GeoPoint posStart(_position.getSRS(), _position.x(), _position.y(), 0.0, ALTMODE_ABSOLUTE); osg::Vec3d posStartXYZ; posStart.toWorld(posStartXYZ); GeoPoint posEnd(_position.getSRS(), _position.x(), _position.y(), 300000.0, ALTMODE_ABSOLUTE); osg::Vec3d posEndXYZ; posEnd.toWorld(posEndXYZ); _projector->setLine(posStartXYZ, posEndXYZ); // set camera osgUtil::LineSegmentIntersector::Intersections intersections; osg::Node::NodeMask intersectionMask = 0xffffffff; osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); if (view->computeIntersections(ea.getX(),ea.getY(),intersections, intersectionMask)) { for (osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr != intersections.end(); ++hitr) { _pointer.addIntersection(hitr->nodePath, hitr->getLocalIntersectPoint()); } bool draggerFound = false; for (osgManipulator::PointerInfo::IntersectionList::iterator piit = _pointer._hitList.begin(); piit != _pointer._hitList.end(); ++piit) { for (osg::NodePath::iterator itr = piit->first.begin(); itr != piit->first.end(); ++itr) { Dragger* dragger = dynamic_cast<Dragger*>(*itr); if (dragger==this) { draggerFound = true; osg::Camera *rootCamera = view->getCamera(); osg::NodePath nodePath = _pointer._hitList.front().first; osg::NodePath::reverse_iterator ritr; for (ritr = nodePath.rbegin(); ritr != nodePath.rend(); ++ritr) { osg::Camera* camera = dynamic_cast<osg::Camera*>(*ritr); if (camera && (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty())) { rootCamera = camera; break; } } _pointer.setCamera(rootCamera); _pointer.setMousePosition(ea.getX(), ea.getY()); break; } } if (draggerFound) break; } } } aa.requestRedraw(); return true; } } else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) { _elevationDragging = false; if ( _dragging ) { _dragging = false; firePositionChanged(); } aa.requestRedraw(); } else if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG) { if (_elevationDragging) { _pointer._hitIter = _pointer._hitList.begin(); _pointer.setMousePosition(ea.getX(), ea.getY()); if (_projector->project(_pointer, _startProjectedPoint)) { //Get the absolute mapPoint that they've drug it to. GeoPoint projectedPos; projectedPos.fromWorld(_position.getSRS(), _startProjectedPoint); // make sure point is not dragged down below // TODO: think of a better solution / HeightAboveTerrain performance issues? if (projectedPos.z() >= _verticalMinimum) { //If the current position is relative, we need to convert the absolute world point to relative. //If the point is absolute then just emit the absolute point. if (_position.altitudeMode() == ALTMODE_RELATIVE) { projectedPos.transformZ(ALTMODE_RELATIVE, getMapNode()->getTerrain()); } setPosition( projectedPos ); aa.requestRedraw(); } } return true; } if (_dragging) { osg::Vec3d world; if ( getMapNode() && getMapNode()->getTerrain()->getWorldCoordsUnderMouse(view, ea.getX(), ea.getY(), world) ) { //Get the absolute mapPoint that they've drug it to. GeoPoint mapPoint; mapPoint.fromWorld( getMapNode()->getMapSRS(), world ); //_mapNode->getMap()->worldPointToMapPoint(world, mapPoint); //If the current position is relative, we need to convert the absolute world point to relative. //If the point is absolute then just emit the absolute point. if (_position.altitudeMode() == ALTMODE_RELATIVE) { mapPoint.alt() = _position.alt(); mapPoint.altitudeMode() = ALTMODE_RELATIVE; } setPosition( mapPoint ); aa.requestRedraw(); return true; } } } else if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE) { Picker picker( view, this ); Picker::Hits hits; if ( picker.pick( ea.getX(), ea.getY(), hits ) ) { setHover( true ); } else { setHover( false ); } aa.requestRedraw(); } return false; }