I've been asked to add some tool tips to objects in a 3D scene, and I
wonder if there is anything existing in OSG that would facilitate an
implementation.
I figured it out myself - and I think I got that done with quite minimal effort.
We're already integrating Qt and OpenSceneGraph by means of a
QGraphicsView which displays a QGraphicsScene. The OSG scene graph is
rendered in the drawBackground() implementation of the QGraphicsScene,
and as an added bonus it is even possible to display floating Qt
windows (encapsulated as QGraphicsItems) on top of the scene.
So here's how I integrated Qt's existing tool tip system with the
scene graph. I am overriding the QGraphicsView's event() handler, so
whenever a tool tip is requested by Qt, I will ask the underlying
QGraphicsScene implementation whether a tool tip is required at the
mouse position and display that. Otherwise I fall back to the default
event handler.
bool MyGraphicsView::event(QEvent* e)
{
QHelpEvent *he = static_castQHelpEvent*(e);
QMouseEvent *me = static_castQMouseEvent*(e);
if(he he-type() == QEvent::ToolTip)
{
QString tip;
bool handle =
((MyGraphicsScene*)scene())-toolTipAt((qreal)he-pos().x(),
(qreal)he-pos().y(), tip);
if (handle)
{
QToolTip::showText(he-globalPos(), tip);
e-accept();
return true;
}
else QToolTip::hideText();
}
else if (me)
{
QToolTip::hideText();
}
return QGraphicsView::event(e);
}
The QGraphicsScene provides a hint as to whether a tool tip is
supposed to be shown by first checking whether a QGraphicsItem under
the mouse position - if not it means that the mouse is hovering over
content rendered by OSG. So it will shoot an intersector into the
scene graph under the mouse position. Our OpenGLScene implementation
also implements an osg::Viewer instance through multiple inheritance -
so I can just cast our object pointer to osgViewer::View and use the
computeIntersections() member. But for some unknown reason I had to
invert the vertical coordinate.
For now I display the osg geode's name (if defines) as tool tip (if it
is defined). Other uses like context sensitive pop up menus are now
within reach. Cool!
bool MyGraphicsScene::toolTipAt(qreal x, qreal y, QString tmp)
{
QGraphicsItem *item;
// first make sure we're not hovering over a displayed QGraphicsItem
if ((item = itemAt(x, y)) == NULL)
{
osgUtil::LineSegmentIntersector::Intersections intersections;
osgViewer::Viewer* viewer = dynamic_castosgViewer::Viewer*(this);
osgViewer::View* view = dynamic_castosgViewer::View*(viewer);
// compute intersections with geometry cylinders
if (view-computeIntersections(x, sceneRect().height()-y,
intersections, 4))
{
for(osgUtil::LineSegmentIntersector::Intersections::iterator
hitr = intersections.begin();
hitr != intersections.end();
++hitr)
{
std::ostringstream os;
if (!hitr-nodePath.empty()
!(hitr-nodePath.back()-getName().empty()))
{
tmp = QString(hitr-nodePath.back()-getName().c_str());
return true;
}
}
}
}
return false;
}
I hope this code is of some use to other people, so I am posting it here.
Ciao,
Christian
___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org