From Kristofer Tingdahl, "I and my team have gone over the code again, and we feel that we are comfortable in our current proposal for change. It goes deeper than it did before, and I explain why:
There was code in the osgViewer/Viewer.cpp and osgViewer/CompositeViewer.cpp that transformed the Y-coordinates of an event. The code in the composite viewer did however miss the touch-data of the event. I thought that it should really be the GUIEventAdapter that should know about this, and hence I added the GUIEventAdapter::setMouseYOrientationAndUpdateCoords which is re-computing the coordinates. First I simply added a boolean to the setMouseYOrientation function: setMouseYOrientation( MouseYOrientation, bool updatecooreds=false ); but then the serializer complained. This function is called from both the Viewer and the CompositeViewer. We have not tested from the viewer, but I cannot see it would not work from visual inspection. The other change is in MultiTouchTrackballManipulator::handleMultiTouchDrag. I have removed the normalisation. The reason for that is that it normalised into screen coordinates from 0,0 to 1,1. The problem with that is that if you have a pinch event and you keep the distance say 300 pixels between your fingers, these 300 pixels represent 0.20 of the screen in the horizontal domain, but 0.3 of the screen in the vertical domain. A rotation of the pinch-fingers will hence result in a zoom in, as the normalised distance is changing between them. A consequence of this is that I have changed the pan-code to use the same algorithm as the middle-mouse-pan. The rest of it is very similar from previous revision, and there has been some fine-tuning here and there. "
This commit is contained in:
parent
6f2d003bc5
commit
bc5575f83a
@ -5,7 +5,7 @@
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/MultiTouchTrackballManipulator>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
@ -57,8 +57,8 @@ public:
|
||||
|
||||
view->setSceneData( scene );
|
||||
view->addEventHandler( new osgViewer::StatsHandler );
|
||||
view->setCameraManipulator( new osgGA::TrackballManipulator );
|
||||
|
||||
view->setCameraManipulator( new osgGA::MultiTouchTrackballManipulator );
|
||||
gw->setTouchEventsEnabled( true );
|
||||
return gw->getGLWidget();
|
||||
}
|
||||
|
||||
|
@ -602,6 +602,9 @@ public:
|
||||
/// get mouse-Y orientation (mouse-Y increases upwards or downwards).
|
||||
MouseYOrientation getMouseYOrientation() const { return _mouseYOrientation; }
|
||||
|
||||
/// set mouse-Y orientation (mouse-Y increases upwards or downwards) and recompute variables
|
||||
void setMouseYOrientationAndUpdateCoords(MouseYOrientation myo);
|
||||
|
||||
/// set current mouse button state.
|
||||
void setButtonMask(int mask) { _buttonMask = mask; }
|
||||
|
||||
|
@ -23,8 +23,10 @@
|
||||
#include <QEvent>
|
||||
#include <QQueue>
|
||||
#include <QSet>
|
||||
#include <QGLWidget>
|
||||
|
||||
class QInputEvent;
|
||||
class QGestureEvent;
|
||||
|
||||
namespace osgViewer {
|
||||
class ViewerBase;
|
||||
@ -66,6 +68,9 @@ public:
|
||||
|
||||
inline bool getForwardKeyEvents() const { return _forwardKeyEvents; }
|
||||
virtual void setForwardKeyEvents( bool f ) { _forwardKeyEvents = f; }
|
||||
|
||||
inline bool getTouchEventsEnabled() const { return _touchEventsEnabled; }
|
||||
void setTouchEventsEnabled( bool e );
|
||||
|
||||
void setKeyboardModifiers( QInputEvent* event );
|
||||
|
||||
@ -76,6 +81,7 @@ public:
|
||||
virtual void mouseDoubleClickEvent( QMouseEvent* event );
|
||||
virtual void mouseMoveEvent( QMouseEvent* event );
|
||||
virtual void wheelEvent( QWheelEvent* event );
|
||||
virtual bool gestureEvent( QGestureEvent* event );
|
||||
|
||||
protected:
|
||||
|
||||
@ -109,6 +115,8 @@ protected:
|
||||
QQueue<QEvent::Type> _deferredEventQueue;
|
||||
QSet<QEvent::Type> _eventCompressor;
|
||||
|
||||
bool _touchEventsEnabled;
|
||||
|
||||
bool _forwardKeyEvents;
|
||||
qreal _devicePixelRatio;
|
||||
|
||||
@ -157,6 +165,9 @@ public:
|
||||
virtual std::string getWindowName();
|
||||
virtual void useCursor( bool cursorOn );
|
||||
virtual void setCursor( MouseCursor cursor );
|
||||
inline bool getTouchEventsEnabled() const { return _widget->getTouchEventsEnabled(); }
|
||||
virtual void setTouchEventsEnabled( bool e ) { _widget->setTouchEventsEnabled(e); }
|
||||
|
||||
|
||||
virtual bool valid() const;
|
||||
virtual bool realizeImplementation();
|
||||
|
@ -132,3 +132,20 @@ void GUIEventAdapter::copyPointerDataFrom(const osgGA::GUIEventAdapter& sourceEv
|
||||
setMouseYOrientation(sourceEvent.getMouseYOrientation());
|
||||
setPointerDataList(sourceEvent.getPointerDataList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GUIEventAdapter::setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::MouseYOrientation myo)
|
||||
{
|
||||
if ( myo==_mouseYOrientation )
|
||||
return;
|
||||
|
||||
setMouseYOrientation( myo );
|
||||
|
||||
_my = _Ymax - _my + _Ymin;
|
||||
if( isMultiTouchEvent() )
|
||||
{
|
||||
for( TouchData::iterator itr = getTouchData()->begin(); itr != getTouchData()->end(); itr++ )
|
||||
itr->y = _Ymax - itr->y + _Ymin;
|
||||
}
|
||||
}
|
||||
|
@ -37,29 +37,28 @@ MultiTouchTrackballManipulator::MultiTouchTrackballManipulator( const MultiTouch
|
||||
|
||||
void MultiTouchTrackballManipulator::handleMultiTouchDrag(const GUIEventAdapter* now, const GUIEventAdapter* last, const double eventTimeDelta)
|
||||
{
|
||||
osg::Vec2 pt_1_now(now->getTouchPointNormalizedX(0),now->getTouchPointNormalizedY(0));
|
||||
osg::Vec2 pt_2_now(now->getTouchPointNormalizedX(1),now->getTouchPointNormalizedY(1));
|
||||
osg::Vec2 pt_1_last(last->getTouchPointNormalizedX(0),last->getTouchPointNormalizedY(0));
|
||||
osg::Vec2 pt_2_last(last->getTouchPointNormalizedX(1),last->getTouchPointNormalizedY(1));
|
||||
const osg::Vec2 pt_1_now( now->getTouchData()->get(0).x, now->getTouchData()->get(0).y);
|
||||
const osg::Vec2 pt_2_now( now->getTouchData()->get(1).x, now->getTouchData()->get(1).y);
|
||||
const osg::Vec2 pt_1_last( last->getTouchData()->get(0).x, last->getTouchData()->get(0).y);
|
||||
const osg::Vec2 pt_2_last( last->getTouchData()->get(1).x, last->getTouchData()->get(1).y);
|
||||
|
||||
|
||||
|
||||
float gap_now((pt_1_now - pt_2_now).length());
|
||||
float gap_last((pt_1_last - pt_2_last).length());
|
||||
const float gap_now((pt_1_now - pt_2_now).length());
|
||||
const float gap_last((pt_1_last - pt_2_last).length());
|
||||
|
||||
// osg::notify(osg::ALWAYS) << gap_now << " " << gap_last << std::endl;
|
||||
|
||||
const float relativeChange = (gap_last - gap_now)/gap_last;
|
||||
|
||||
|
||||
// zoom gesture
|
||||
if (fabs(gap_last - gap_now) > 0.02)
|
||||
zoomModel( (gap_last - gap_now) , true );
|
||||
if (fabs(relativeChange) > 0.02)
|
||||
zoomModel( relativeChange , true );
|
||||
|
||||
// drag gesture
|
||||
osg::Vec2 delta = ((pt_1_last - pt_1_now) + (pt_2_last - pt_2_now)) / 2.0f;
|
||||
const osg::Vec2 delta = ((pt_1_last - pt_1_now) + (pt_2_last - pt_2_now)) / 2.0f;
|
||||
|
||||
float scale = _distance / 3.0f;
|
||||
|
||||
// osg::notify(osg::ALWAYS) << "drag: " << delta << " scale: " << scale << std::endl;
|
||||
const float scale = -0.3f * _distance * getThrowScale( eventTimeDelta );
|
||||
//osg::notify(osg::ALWAYS) << "drag: " << delta << " scale: " << scale << std::endl;
|
||||
|
||||
panModel( delta.x() * scale, delta.y() * scale);
|
||||
}
|
||||
|
@ -11,12 +11,17 @@
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#include <osgQt/GraphicsWindowQt>
|
||||
|
||||
#include <osg/DeleteHandler>
|
||||
#include <osgQt/GraphicsWindowQt>
|
||||
#include <osgViewer/ViewerBase>
|
||||
#include <QInputEvent>
|
||||
|
||||
#if (QT_VERSION>=QT_VERSION_CHECK(4, 6, 0))
|
||||
# define USE_GESTURES
|
||||
# include <QGestureEvent>
|
||||
# include <QGesture>
|
||||
#endif
|
||||
|
||||
using namespace osgQt;
|
||||
|
||||
|
||||
@ -136,7 +141,8 @@ static HeartBeat heartBeat;
|
||||
GLWidget::GLWidget( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, bool forwardKeyEvents )
|
||||
: QGLWidget(parent, shareWidget, f),
|
||||
_gw( NULL ),
|
||||
_forwardKeyEvents( forwardKeyEvents )
|
||||
_forwardKeyEvents( forwardKeyEvents ),
|
||||
_touchEventsEnabled( false )
|
||||
{
|
||||
_devicePixelRatio = GETDEVICEPIXELRATIO();
|
||||
}
|
||||
@ -145,7 +151,8 @@ GLWidget::GLWidget( QGLContext* context, QWidget* parent, const QGLWidget* share
|
||||
bool forwardKeyEvents )
|
||||
: QGLWidget(context, parent, shareWidget, f),
|
||||
_gw( NULL ),
|
||||
_forwardKeyEvents( forwardKeyEvents )
|
||||
_forwardKeyEvents( forwardKeyEvents ),
|
||||
_touchEventsEnabled( false )
|
||||
{
|
||||
_devicePixelRatio = GETDEVICEPIXELRATIO();
|
||||
}
|
||||
@ -154,7 +161,8 @@ GLWidget::GLWidget( const QGLFormat& format, QWidget* parent, const QGLWidget* s
|
||||
bool forwardKeyEvents )
|
||||
: QGLWidget(format, parent, shareWidget, f),
|
||||
_gw( NULL ),
|
||||
_forwardKeyEvents( forwardKeyEvents )
|
||||
_forwardKeyEvents( forwardKeyEvents ),
|
||||
_touchEventsEnabled( false )
|
||||
{
|
||||
_devicePixelRatio = GETDEVICEPIXELRATIO();
|
||||
}
|
||||
@ -170,6 +178,25 @@ GLWidget::~GLWidget()
|
||||
}
|
||||
}
|
||||
|
||||
void GLWidget::setTouchEventsEnabled(bool e)
|
||||
{
|
||||
#ifdef USE_GESTURES
|
||||
if (e==_touchEventsEnabled)
|
||||
return;
|
||||
|
||||
_touchEventsEnabled = e;
|
||||
|
||||
if (_touchEventsEnabled)
|
||||
{
|
||||
grabGesture(Qt::PinchGesture);
|
||||
}
|
||||
else
|
||||
{
|
||||
ungrabGesture(Qt::PinchGesture);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLWidget::processDeferredEvents()
|
||||
{
|
||||
QQueue<QEvent::Type> deferredEventQueueCopy;
|
||||
@ -189,6 +216,10 @@ void GLWidget::processDeferredEvents()
|
||||
|
||||
bool GLWidget::event( QEvent* event )
|
||||
{
|
||||
#ifdef USE_GESTURES
|
||||
if ( event->type()==QEvent::Gesture )
|
||||
return gestureEvent(static_cast<QGestureEvent*>(event));
|
||||
#endif
|
||||
|
||||
// QEvent::Hide
|
||||
//
|
||||
@ -361,6 +392,85 @@ void GLWidget::wheelEvent( QWheelEvent* event )
|
||||
(event->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT) );
|
||||
}
|
||||
|
||||
#ifdef USE_GESTURES
|
||||
static osgGA::GUIEventAdapter::TouchPhase translateQtGestureState( Qt::GestureState state )
|
||||
{
|
||||
osgGA::GUIEventAdapter::TouchPhase touchPhase;
|
||||
switch ( state )
|
||||
{
|
||||
case Qt::GestureStarted:
|
||||
touchPhase = osgGA::GUIEventAdapter::TOUCH_BEGAN;
|
||||
break;
|
||||
case Qt::GestureUpdated:
|
||||
touchPhase = osgGA::GUIEventAdapter::TOUCH_MOVED;
|
||||
break;
|
||||
case Qt::GestureFinished:
|
||||
case Qt::GestureCanceled:
|
||||
touchPhase = osgGA::GUIEventAdapter::TOUCH_ENDED;
|
||||
break;
|
||||
default:
|
||||
touchPhase = osgGA::GUIEventAdapter::TOUCH_UNKNOWN;
|
||||
};
|
||||
|
||||
return touchPhase;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool GLWidget::gestureEvent( QGestureEvent* qevent )
|
||||
{
|
||||
#ifndef USE_GESTURES
|
||||
return false;
|
||||
#else
|
||||
|
||||
bool accept = false;
|
||||
|
||||
if ( QPinchGesture* pinch = static_cast<QPinchGesture *>(qevent->gesture(Qt::PinchGesture) ) )
|
||||
{
|
||||
const QPointF qcenterf = pinch->centerPoint();
|
||||
const float angle = pinch->totalRotationAngle();
|
||||
const float scale = pinch->totalScaleFactor();
|
||||
|
||||
const QPoint pinchCenterQt = mapFromGlobal(qcenterf.toPoint());
|
||||
const osg::Vec2 pinchCenter( pinchCenterQt.x(), pinchCenterQt.y() );
|
||||
|
||||
//We don't have absolute positions of the two touches, only a scale and rotation
|
||||
//Hence we create pseudo-coordinates which are reasonable, and centered around the
|
||||
//real position
|
||||
const float radius = (width()+height())/4;
|
||||
const osg::Vec2 vector( scale*cos(angle)*radius, scale*sin(angle)*radius);
|
||||
const osg::Vec2 p0 = pinchCenter+vector;
|
||||
const osg::Vec2 p1 = pinchCenter-vector;
|
||||
|
||||
osg::ref_ptr<osgGA::GUIEventAdapter> event = 0;
|
||||
const osgGA::GUIEventAdapter::TouchPhase touchPhase = translateQtGestureState( pinch->state() );
|
||||
if ( touchPhase==osgGA::GUIEventAdapter::TOUCH_BEGAN )
|
||||
{
|
||||
event = _gw->getEventQueue()->touchBegan(0 , touchPhase, p0[0], p0[1] );
|
||||
}
|
||||
else if ( touchPhase==osgGA::GUIEventAdapter::TOUCH_MOVED )
|
||||
{
|
||||
event = _gw->getEventQueue()->touchMoved( 0, touchPhase, p0[0], p0[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
event = _gw->getEventQueue()->touchEnded( 0, touchPhase, p0[0], p0[1], 1 );
|
||||
}
|
||||
|
||||
if ( event )
|
||||
{
|
||||
event->addTouchPoint( 1, touchPhase, p1[0], p1[1] );
|
||||
accept = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( accept )
|
||||
qevent->accept();
|
||||
|
||||
return accept;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
GraphicsWindowQt::GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f )
|
||||
|
@ -1008,11 +1008,7 @@ void CompositeViewer::eventTraversal()
|
||||
event->setInputRange(pd->xMin, pd->yMin, pd->xMax, pd->yMax);
|
||||
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
|
||||
#else
|
||||
if (event->getMouseYOrientation()!=osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
|
||||
{
|
||||
event->setY((event->getYmax()-event->getY())+event->getYmin());
|
||||
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
|
||||
}
|
||||
event->setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
|
||||
#endif
|
||||
|
||||
_previousEvent = event;
|
||||
|
@ -929,16 +929,7 @@ void Viewer::eventTraversal()
|
||||
event->setInputRange(pd->xMin, pd->yMin, pd->xMax, pd->yMax);
|
||||
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
|
||||
#else
|
||||
if (event->getMouseYOrientation()!=osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
|
||||
{
|
||||
event->setY((event->getYmax()-event->getY())+event->getYmin());
|
||||
event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
|
||||
if(event->isMultiTouchEvent()) {
|
||||
for(osgGA::GUIEventAdapter::TouchData::iterator itr = event->getTouchData()->begin(); itr != event->getTouchData()->end(); itr++) {
|
||||
itr->y = event->getYmax() - itr->y + event->getYmin();
|
||||
}
|
||||
}
|
||||
}
|
||||
event->setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
|
||||
#endif
|
||||
|
||||
eventState->copyPointerDataFrom(*event);
|
||||
|
Loading…
Reference in New Issue
Block a user