summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/input/q3dinputhandler.cpp
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/q3dinputhandler.cpp
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/q3dinputhandler.cpp')
-rw-r--r--src/datavisualization/input/q3dinputhandler.cpp122
1 files changed, 116 insertions, 6 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