aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Arve Saether <jan-arve.saether@qt.io>2016-10-18 11:49:13 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2016-11-20 21:09:33 +0000
commit542eda976c2767ed6c1eecb4dbcbf838e0ca5a19 (patch)
tree1128e69b70be26e13f35a2591c297d43c6414592
parent0beb79fb0e9ed814b3e9447ccd97a0c099af9e4b (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.cpp67
-rw-r--r--src/quick/handlers/qquickpinchhandler_p.h2
-rw-r--r--tests/manual/pointer/pinchHandler.qml96
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