diff options
author | Jan Arve Saether <jan-arve.saether@qt.io> | 2016-10-18 11:49:13 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2016-11-20 21:09:33 +0000 |
commit | 542eda976c2767ed6c1eecb4dbcbf838e0ca5a19 (patch) | |
tree | 1128e69b70be26e13f35a2591c297d43c6414592 | |
parent | 0beb79fb0e9ed814b3e9447ccd97a0c099af9e4b (diff) |
Fixed some problems with the centroid in PinchHandler
The centroid was not always mapped to the correct coordinate system
In addition, the return value of startingCentroid() was not always
desirable, because its implementation calls sceneGrabPos(). We therefore
had to get the starting centroid by querying touchPointCentroid() whenever
the handler became active.
Change-Id: I69de6b832b9bda208fda4eb90a8a95cc975405c2
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r-- | src/quick/handlers/qquickpinchhandler.cpp | 67 | ||||
-rw-r--r-- | src/quick/handlers/qquickpinchhandler_p.h | 2 | ||||
-rw-r--r-- | tests/manual/pointer/pinchHandler.qml | 96 |
3 files changed, 93 insertions, 72 deletions
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index 417a45318d..09e4f9f17c 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -202,11 +202,15 @@ void QQuickPinchHandler::onActiveChanged() if (active()) { m_startScale = m_scale; // TODO incompatible with independent x/y scaling m_startRotation = m_rotation; - m_startAngles = angles(touchPointCentroid()); + m_startCentroid = touchPointCentroid(); + m_startAngles = angles(m_startCentroid); + m_startDistance = averageTouchPointDistance(m_startCentroid); m_activeRotation = 0; m_startMatrix = m_transform.matrix(); qCInfo(lcPinchHandler) << "activated with starting scale" << m_startScale << "rotation" << m_startRotation; grabPoints(m_currentPoints); + } else { + qCInfo(lcPinchHandler) << "deactivated with scale" << m_scale << "rotation" << m_rotation; } } @@ -230,16 +234,19 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event) } // TODO check m_pinchOrigin: right now it acts like it's set to PinchCenter - QPointF startCentroid = startingCentroid(); m_centroid = touchPointCentroid(); - m_centroid = QPointF(qBound(m_minimumX, m_centroid.x(), m_maximumX), - qBound(m_minimumY, m_centroid.y(), m_maximumY)); - - + QRectF bounds(m_minimumX, m_minimumY, m_maximumX, m_maximumY); + // avoid mapping the minima and maxima, as they might have unmappable values + // such as -inf/+inf. Because of this we perform the bounding to min/max in local coords. + QPointF centroidLocalPos; + if (target() && target()->parentItem()) { + centroidLocalPos = target()->parentItem()->mapFromScene(m_centroid); + centroidLocalPos = QPointF(qBound(bounds.left(), centroidLocalPos.x(), bounds.right()), + qBound(bounds.top(), centroidLocalPos.y(), bounds.bottom())); + } // 1. scale - qreal startDist = averageStartingDistance(startCentroid); qreal dist = averageTouchPointDistance(m_centroid); - qreal activeScale = dist / startDist; + qreal activeScale = dist / m_startDistance; activeScale = qBound(m_minimumScale/m_startScale, activeScale, m_maximumScale/m_startScale); m_scale = m_startScale * activeScale; @@ -252,26 +259,30 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event) m_activeRotation += (m_rotation - totalRotation); //adjust for the potential bounding above m_startAngles = std::move(newAngles); - // 3. Drag/translate - QPointF activeTranslation(m_centroid - startCentroid); - - // apply rotation + scaling around the centroid - then apply translation. - QMatrix4x4 mat; - QVector3D xlatOrigin(m_centroid - target()->position()); - mat.translate(xlatOrigin); - mat.rotate(m_activeRotation, 0, 0, -1); - mat.scale(activeScale); - mat.translate(-xlatOrigin); - mat.translate(QVector3D(activeTranslation)); - - // TODO some translation inadvertently happens; try to hold the chosen pinch origin in place - - qCDebug(lcPinchHandler) << "startCentroid" << startCentroid << "centroid" << m_centroid << "dist" << dist << "starting dist" << startDist - << "startScale" << m_startScale << "activeRotation" << m_activeRotation - << "scale" << m_scale << "rotation" << m_rotation; - - mat = mat * m_startMatrix; - m_transform.setMatrix(mat); + if (target() && target()->parentItem()) { + // 3. Drag/translate + QPointF activeTranslation(centroidLocalPos - target()->parentItem()->mapFromScene(m_startCentroid)); + + // apply rotation + scaling around the centroid - then apply translation. + QMatrix4x4 mat; + QVector3D xlatOrigin(centroidLocalPos - target()->position()); + mat.translate(xlatOrigin); + mat.rotate(m_activeRotation, 0, 0, -1); + mat.scale(activeScale); + mat.translate(-xlatOrigin); + mat.translate(QVector3D(activeTranslation)); + + // TODO some translation inadvertently happens; try to hold the chosen pinch origin in place + + qCDebug(lcPinchHandler) << "centroid" << m_startCentroid << "->" << m_centroid + << ", distance" << m_startDistance << "->" << dist + << ", startScale" << m_startScale << "->" << m_scale + << ", activeRotation" << m_activeRotation + << ", rotation" << m_rotation; + + mat = mat * m_startMatrix; + m_transform.setMatrix(mat); + } emit updated(); } diff --git a/src/quick/handlers/qquickpinchhandler_p.h b/src/quick/handlers/qquickpinchhandler_p.h index 338b930373..5107a5c50b 100644 --- a/src/quick/handlers/qquickpinchhandler_p.h +++ b/src/quick/handlers/qquickpinchhandler_p.h @@ -155,6 +155,8 @@ private: qreal m_startScale; qreal m_startRotation; qreal m_activeRotation; + QPointF m_startCentroid; + qreal m_startDistance; QVector<PointData> m_startAngles; QMatrix4x4 m_startMatrix; diff --git a/tests/manual/pointer/pinchHandler.qml b/tests/manual/pointer/pinchHandler.qml index d163343a3e..3ab196a10a 100644 --- a/tests/manual/pointer/pinchHandler.qml +++ b/tests/manual/pointer/pinchHandler.qml @@ -42,60 +42,68 @@ import QtQuick 2.8 import Qt.labs.handlers 1.0 Rectangle { - id: root width: 1024; height: 600 - color: "black" - + color: "#eee" Rectangle { - width: 400 - height: 300 - color: "lightsteelblue" - antialiasing: true + id: root + color: "black" + width: 900 + height: 600 + x: 100 - Text { - anchors.centerIn: parent - text: "Pinch with 2 fingers to scale, rotate and translate" - + "\ncurrent rotation: " + pinch2.rotation.toFixed(1) - + "\nscale: " + pinch2.scale.toFixed(1) - + "\ntranslation: " + pinch2.translation - } + Rectangle { + width: 400 + height: 300 + color: "lightsteelblue" + antialiasing: true - PinchHandler { - id: pinch2 - objectName: "2-finger pinch" - minimumRotation: -45 - maximumRotation: 45 - minimumScale: 0.5 - maximumScale: 3 - minimumX: 0 - maximumX: 600 - pointDistanceThreshold: 150 + Text { + anchors.centerIn: parent + text: "Pinch with 2 fingers to scale, rotate and translate" + + "\ncurrent rotation: " + pinch2.rotation.toFixed(1) + + "\nscale: " + pinch2.scale.toFixed(1) + + "\ntranslation: " + pinch2.translation + } + + PinchHandler { + id: pinch2 + objectName: "2-finger pinch" + minimumRotation: -45 + maximumRotation: 45 + minimumScale: 0.5 + maximumScale: 3 + minimumX: 0 + maximumX: 600 + pointDistanceThreshold: 150 + } } - } - Rectangle { - x: 512 - width: 400 - height: 300 - color: "wheat" - antialiasing: true + Rectangle { + x: 500 + width: 400 + height: 300 + color: "wheat" + antialiasing: true - Text { - anchors.centerIn: parent - text: "Pinch with 3 fingers to scale, rotate and translate\nDrag with 1 finger" - + "\ncurrent rotation " + pinch3.rotation.toFixed(1) - } - DragHandler { objectName: "DragHandler" } + Text { + anchors.centerIn: parent + text: "Pinch with 3 fingers to scale, rotate and translate\nDrag with 1 finger" + + "\ncurrent rotation " + pinch3.rotation.toFixed(1) + + "\nscale: " + pinch3.scale.toFixed(1) + + "\ntranslation: " + pinch3.translation + } + DragHandler { objectName: "DragHandler" } - PinchHandler { - id: pinch3 - objectName: "3-finger pinch" - requiredPointCount: 3 - minimumScale: 0.1 - maximumScale: 10 + PinchHandler { + id: pinch3 + objectName: "3-finger pinch" + requiredPointCount: 3 + minimumScale: 0.1 + maximumScale: 10 + } } - } + } Rectangle { id: centroidIndicator property QtObject pincher: pinch2.active ? pinch2 : pinch3 |