summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/input
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-09-25 15:04:44 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-09-26 10:06:52 +0300
commit0ab45b018fa98e9ef6cffd70178f208eb4f16550 (patch)
tree77d324f47ccb52cc543df9e8990153b82ead2688 /src/datavisualization/input
parent36bc54f5720bddb9899e64d665117ac1e1b5bc94 (diff)
Implement zooming to cursor
Zooming to cursor is now default operating mode of the default input handler. Task-number: QTRD-3263 Change-Id: I5699fc0ce7393059538972cd52f31f06d87e3d8d Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src/datavisualization/input')
-rw-r--r--src/datavisualization/input/q3dinputhandler.cpp122
-rw-r--r--src/datavisualization/input/q3dinputhandler.h4
-rw-r--r--src/datavisualization/input/q3dinputhandler_p.h19
-rw-r--r--src/datavisualization/input/qtouch3dinputhandler.cpp22
-rw-r--r--src/datavisualization/input/qtouch3dinputhandler_p.h9
5 files changed, 160 insertions, 16 deletions
diff --git a/src/datavisualization/input/q3dinputhandler.cpp b/src/datavisualization/input/q3dinputhandler.cpp
index e6f3de24..0bed3cb9 100644
--- a/src/datavisualization/input/q3dinputhandler.cpp
+++ b/src/datavisualization/input/q3dinputhandler.cpp
@@ -18,13 +18,16 @@
#include "datavisualizationglobal_p.h"
#include "q3dinputhandler_p.h"
+#include "abstract3dcontroller_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-const int minZoomLevel = 10;
-const int halfSizeZoomLevel = 50;
-const int oneToOneZoomLevel = 100;
-const int maxZoomLevel = 500;
+const int minZoomLevel = 10;
+const int halfSizeZoomLevel = 50;
+const int oneToOneZoomLevel = 100;
+const int maxZoomLevel = 500;
+const int driftTowardCenterLevel = 175;
+const float wheelZoomDrift = 0.1f;
const int nearZoomRangeDivider = 12;
const int midZoomRangeDivider = 60;
@@ -84,6 +87,7 @@ const float rotationSpeed = 100.0f;
* \since QtDataVisualization 1.2
*
* This property specifies if this input handler allows graph rotation.
+ * Defaults to \c{true}.
*/
/*!
@@ -91,6 +95,7 @@ const float rotationSpeed = 100.0f;
* \since QtDataVisualization 1.2
*
* This property specifies if this input handler allows graph zooming.
+ * Defaults to \c{true}.
*/
/*!
@@ -98,6 +103,16 @@ const float rotationSpeed = 100.0f;
* \since QtDataVisualization 1.2
*
* This property specifies if this input handler allows selection from the graph.
+ * Defaults to \c{true}.
+ */
+
+/*!
+ * \qmlproperty bool InputHandler3D::zoomAtTargetEnabled
+ * \since QtDataVisualization 1.2
+ *
+ * This property specifies if zooming changes the camera target to the position of the input
+ * at the time of the zoom.
+ * Defaults to \c{true}.
*/
/*!
@@ -236,7 +251,16 @@ void Q3DInputHandler::wheelEvent(QWheelEvent *event)
else if (zoomLevel < minZoomLevel)
zoomLevel = minZoomLevel;
- scene()->activeCamera()->setZoomLevel(zoomLevel);
+ if (isZoomAtTargetEnabled()) {
+ scene()->setGraphPositionQuery(event->pos());
+ d_ptr->m_zoomAtTargetPending = true;
+ // If zoom at target is enabled, we don't want to zoom yet, as that causes
+ // jitter. Instead, we zoom next frame, when we apply the camera position.
+ d_ptr->m_requestedZoomLevel = zoomLevel;
+ d_ptr->m_driftMultiplier = wheelZoomDrift;
+ } else {
+ scene()->activeCamera()->setZoomLevel(zoomLevel);
+ }
}
}
@@ -245,6 +269,7 @@ void Q3DInputHandler::wheelEvent(QWheelEvent *event)
* \since QtDataVisualization 1.2
*
* This property specifies if this input handler allows graph rotation.
+ * Defaults to \c{true}.
*/
void Q3DInputHandler::setRotationEnabled(bool enable)
{
@@ -264,6 +289,7 @@ bool Q3DInputHandler::isRotationEnabled() const
* \since QtDataVisualization 1.2
*
* This property specifies if this input handler allows graph zooming.
+ * Defaults to \c{true}.
*/
void Q3DInputHandler::setZoomEnabled(bool enable)
{
@@ -283,6 +309,7 @@ bool Q3DInputHandler::isZoomEnabled() const
* \since QtDataVisualization 1.2
*
* This property specifies if this input handler allows selection from the graph.
+ * Defaults to \c{true}.
*/
void Q3DInputHandler::setSelectionEnabled(bool enable)
{
@@ -297,17 +324,100 @@ bool Q3DInputHandler::isSelectionEnabled() const
return d_ptr->m_selectionEnabled;
}
+/*!
+ * \property Q3DInputHandler::zoomAtTargetEnabled
+ * \since QtDataVisualization 1.2
+ *
+ * This property specifies if zooming should change the camera target so that the zoomed point
+ * of the graph stays at the same location after the zoom.
+ * Defaults to \c{true}.
+ */
+void Q3DInputHandler::setZoomAtTargetEnabled(bool enable)
+{
+ if (d_ptr->m_zoomAtTargetEnabled != enable) {
+ d_ptr->m_zoomAtTargetEnabled = enable;
+ emit zoomAtTargetEnabledChanged(enable);
+ }
+}
+
+bool Q3DInputHandler::isZoomAtTargetEnabled() const
+{
+ return d_ptr->m_zoomAtTargetEnabled;
+}
+
Q3DInputHandlerPrivate::Q3DInputHandlerPrivate(Q3DInputHandler *q)
: q_ptr(q),
m_inputState(QAbstract3DInputHandlerPrivate::InputStateNone),
m_rotationEnabled(true),
m_zoomEnabled(true),
- m_selectionEnabled(true)
+ m_selectionEnabled(true),
+ m_zoomAtTargetEnabled(true),
+ m_zoomAtTargetPending(false),
+ m_controller(0),
+ m_requestedZoomLevel(0.0f),
+ m_driftMultiplier(0.0f)
{
+ QObject::connect(q, &QAbstract3DInputHandler::sceneChanged,
+ this, &Q3DInputHandlerPrivate::handleSceneChange);
}
Q3DInputHandlerPrivate::~Q3DInputHandlerPrivate()
{
}
+void Q3DInputHandlerPrivate::handleSceneChange(Q3DScene *scene)
+{
+ if (scene) {
+ if (m_controller) {
+ QObject::disconnect(m_controller, &Abstract3DController::queriedGraphPositionChanged,
+ this, &Q3DInputHandlerPrivate::handleQueriedGraphPositionChange);
+ }
+
+ m_controller = qobject_cast<Abstract3DController *>(scene->parent());
+
+ if (m_controller) {
+ QObject::connect(m_controller, &Abstract3DController::queriedGraphPositionChanged,
+ this, &Q3DInputHandlerPrivate::handleQueriedGraphPositionChange);
+ }
+ }
+}
+
+void Q3DInputHandlerPrivate::handleQueriedGraphPositionChange()
+{
+ if (m_zoomAtTargetPending) {
+ // Check if the zoom point is on graph
+ QVector3D newTarget = m_controller->queriedGraphPosition();
+ float currentZoom = m_requestedZoomLevel;
+ float previousZoom = q_ptr->scene()->activeCamera()->zoomLevel();
+ q_ptr->scene()->activeCamera()->setZoomLevel(currentZoom);
+ float diffAdj = 0.0f;
+
+ // If zooming in/out outside the graph, or zooming out after certain point,
+ // move towards the center.
+ if ((qAbs(newTarget.x()) > 1.0f
+ || qAbs(newTarget.y()) > 1.0f
+ || qAbs(newTarget.z()) > 1.0f)
+ || (previousZoom > currentZoom && currentZoom <= driftTowardCenterLevel)) {
+ newTarget = zeroVector;
+ // Add some extra correction so that we actually reach the center eventually
+ diffAdj = m_driftMultiplier;
+ if (previousZoom > currentZoom)
+ diffAdj *= 2.0f; // Correct towards center little more when zooming out
+ }
+
+ float zoomFraction = 1.0f - (previousZoom / currentZoom);
+
+ // Adjust camera towards the zoom point, attempting to keep the cursor at same graph point
+ QVector3D oldTarget = q_ptr->scene()->activeCamera()->target();
+ QVector3D origDiff = newTarget - oldTarget;
+ QVector3D diff = origDiff * zoomFraction + (origDiff.normalized() * diffAdj);
+ if (diff.length() > origDiff.length())
+ diff = origDiff;
+ q_ptr->scene()->activeCamera()->setTarget(oldTarget + diff);
+
+ if (q_ptr->scene()->selectionQueryPosition() == Q3DScene::invalidSelectionPoint())
+ m_zoomAtTargetPending = false;
+ }
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/input/q3dinputhandler.h b/src/datavisualization/input/q3dinputhandler.h
index 9afeb945..5423b4ea 100644
--- a/src/datavisualization/input/q3dinputhandler.h
+++ b/src/datavisualization/input/q3dinputhandler.h
@@ -31,6 +31,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DInputHandler : public QAbstract3DInputHandl
Q_PROPERTY(bool rotationEnabled READ isRotationEnabled WRITE setRotationEnabled NOTIFY rotationEnabledChanged)
Q_PROPERTY(bool zoomEnabled READ isZoomEnabled WRITE setZoomEnabled NOTIFY zoomEnabledChanged)
Q_PROPERTY(bool selectionEnabled READ isSelectionEnabled WRITE setSelectionEnabled NOTIFY selectionEnabledChanged)
+ Q_PROPERTY(bool zoomAtTargetEnabled READ isZoomAtTargetEnabled WRITE setZoomAtTargetEnabled NOTIFY zoomAtTargetEnabledChanged)
public:
explicit Q3DInputHandler(QObject *parent = 0);
@@ -42,6 +43,8 @@ public:
bool isZoomEnabled() const;
void setSelectionEnabled(bool enable);
bool isSelectionEnabled() const;
+ void setZoomAtTargetEnabled(bool enable);
+ bool isZoomAtTargetEnabled() const;
// Input event listeners
virtual void mousePressEvent(QMouseEvent *event, const QPoint &mousePos);
@@ -53,6 +56,7 @@ signals:
void rotationEnabledChanged(bool enable);
void zoomEnabledChanged(bool enable);
void selectionEnabledChanged(bool enable);
+ void zoomAtTargetEnabledChanged(bool enable);
private:
Q_DISABLE_COPY(Q3DInputHandler)
diff --git a/src/datavisualization/input/q3dinputhandler_p.h b/src/datavisualization/input/q3dinputhandler_p.h
index a3ed8c9c..79b1c8dd 100644
--- a/src/datavisualization/input/q3dinputhandler_p.h
+++ b/src/datavisualization/input/q3dinputhandler_p.h
@@ -34,19 +34,34 @@
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-class Q3DInputHandlerPrivate
+class Abstract3DController;
+
+class Q3DInputHandlerPrivate : public QObject
{
+ Q_OBJECT
public:
Q3DInputHandlerPrivate(Q3DInputHandler *q);
~Q3DInputHandlerPrivate();
-protected:
+public slots:
+ void handleSceneChange(Q3DScene *scene);
+ void handleQueriedGraphPositionChange();
+
+private:
Q3DInputHandler *q_ptr;
+protected:
QAbstract3DInputHandlerPrivate::InputState m_inputState;
bool m_rotationEnabled;
bool m_zoomEnabled;
bool m_selectionEnabled;
+ bool m_zoomAtTargetEnabled;
+ bool m_zoomAtTargetPending;
+
+ Abstract3DController *m_controller; // Not owned
+
+ float m_requestedZoomLevel;
+ float m_driftMultiplier;
friend class Q3DInputHandler;
};
diff --git a/src/datavisualization/input/qtouch3dinputhandler.cpp b/src/datavisualization/input/qtouch3dinputhandler.cpp
index 5d62922b..b811548b 100644
--- a/src/datavisualization/input/qtouch3dinputhandler.cpp
+++ b/src/datavisualization/input/qtouch3dinputhandler.cpp
@@ -33,6 +33,7 @@ const int tapAndHoldTime = 250;
const float rotationSpeed = 200.0f;
const int minZoomLevel = 10;
const int maxZoomLevel = 500;
+const float touchZoomDrift = 0.02f;
/*!
* \class QTouch3DInputHandler
@@ -113,7 +114,8 @@ void QTouch3DInputHandler::touchEvent(QTouchEvent *event)
if (!scene()->isSlicingActive() && points.count() == 2) {
d_ptr->m_holdTimer->stop();
QPointF distance = points.at(0).pos() - points.at(1).pos();
- d_ptr->handlePinchZoom(distance.manhattanLength());
+ QPoint midPoint = ((points.at(0).pos() + points.at(1).pos()) / 2.0).toPoint();
+ d_ptr->handlePinchZoom(distance.manhattanLength(), midPoint);
} else if (points.count() == 1) {
QPointF pointerPos = points.at(0).pos();
if (event->type() == QEvent::TouchBegin) {
@@ -165,7 +167,8 @@ void QTouch3DInputHandler::touchEvent(QTouchEvent *event)
}
QTouch3DInputHandlerPrivate::QTouch3DInputHandlerPrivate(QTouch3DInputHandler *q)
- : q_ptr(q),
+ : Q3DInputHandlerPrivate(q),
+ q_ptr(q),
m_holdTimer(0),
m_inputState(QAbstract3DInputHandlerPrivate::InputStateNone)
{
@@ -181,7 +184,7 @@ QTouch3DInputHandlerPrivate::~QTouch3DInputHandlerPrivate()
delete m_holdTimer;
}
-void QTouch3DInputHandlerPrivate::handlePinchZoom(float distance)
+void QTouch3DInputHandlerPrivate::handlePinchZoom(float distance, const QPoint &pos)
{
if (q_ptr->isZoomEnabled()) {
int newDistance = distance;
@@ -200,7 +203,18 @@ void QTouch3DInputHandlerPrivate::handlePinchZoom(float distance)
zoomLevel = maxZoomLevel;
else if (zoomLevel < minZoomLevel)
zoomLevel = minZoomLevel;
- camera->setZoomLevel(zoomLevel);
+
+ if (q_ptr->isZoomAtTargetEnabled()) {
+ q_ptr->scene()->setGraphPositionQuery(pos);
+ m_zoomAtTargetPending = true;
+ // If zoom at target is enabled, we don't want to zoom yet, as that causes
+ // jitter. Instead, we zoom next frame, when we apply the camera position.
+ m_requestedZoomLevel = zoomLevel;
+ m_driftMultiplier = touchZoomDrift;
+ } else {
+ camera->setZoomLevel(zoomLevel);
+ }
+
q_ptr->setPrevDistance(newDistance);
}
}
diff --git a/src/datavisualization/input/qtouch3dinputhandler_p.h b/src/datavisualization/input/qtouch3dinputhandler_p.h
index 613b5f28..b01904ca 100644
--- a/src/datavisualization/input/qtouch3dinputhandler_p.h
+++ b/src/datavisualization/input/qtouch3dinputhandler_p.h
@@ -19,7 +19,7 @@
#ifndef QTOUCH3DINPUTHANDLER_P_H
#define QTOUCH3DINPUTHANDLER_P_H
-#include "qabstract3dinputhandler_p.h"
+#include "q3dinputhandler_p.h"
#include "qtouch3dinputhandler.h"
class QTimer;
@@ -28,7 +28,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class QAbstract3DInputHandler;
-class QTouch3DInputHandlerPrivate : public QObject
+class QTouch3DInputHandlerPrivate : public Q3DInputHandlerPrivate
{
Q_OBJECT
@@ -36,13 +36,14 @@ public:
QTouch3DInputHandlerPrivate(QTouch3DInputHandler *q);
~QTouch3DInputHandlerPrivate();
- void handlePinchZoom(float distance);
+ void handlePinchZoom(float distance, const QPoint &pos);
void handleTapAndHold();
void handleSelection(const QPointF &position);
void handleRotation(const QPointF &position);
-public:
+private:
QTouch3DInputHandler *q_ptr;
+public:
QTimer *m_holdTimer;
QAbstract3DInputHandlerPrivate::InputState m_inputState;
QPointF m_startHoldPos;