diff options
-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 |