summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/datavisualization/volumetric/volumetric.cpp4
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc22
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp33
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h7
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp124
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h19
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp20
-rw-r--r--src/datavisualization/engine/engine.qrc3
-rw-r--r--src/datavisualization/engine/q3dscene.cpp62
-rw-r--r--src/datavisualization/engine/q3dscene.h5
-rw-r--r--src/datavisualization/engine/q3dscene_p.h3
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.cpp27
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.h4
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp10
-rw-r--r--src/datavisualization/engine/shaders/position.vert (renamed from src/datavisualization/engine/shaders/colorandposition.vert)0
-rw-r--r--src/datavisualization/engine/shaders/positionmap.frag11
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp17
-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
-rw-r--r--src/datavisualization/utils/texturehelper.cpp25
-rw-r--r--src/datavisualization/utils/texturehelper_p.h2
-rw-r--r--src/datavisualizationqml2/abstractdeclarative.cpp7
-rw-r--r--src/datavisualizationqml2/abstractdeclarative_p.h4
-rw-r--r--src/datavisualizationqml2/datavisualizationqml2_plugin.cpp2
-rw-r--r--tests/barstest/chart.cpp6
-rw-r--r--tests/barstest/chart.h1
-rw-r--r--tests/barstest/main.cpp7
-rw-r--r--tests/scattertest/scatterchart.cpp6
-rw-r--r--tests/surfacetest/graphmodifier.cpp25
-rw-r--r--tests/surfacetest/graphmodifier.h5
-rw-r--r--tests/surfacetest/main.cpp2
-rw-r--r--tests/volumetrictest/volumetrictest.pro4
35 files changed, 583 insertions, 60 deletions
diff --git a/examples/datavisualization/volumetric/volumetric.cpp b/examples/datavisualization/volumetric/volumetric.cpp
index cbbaf2a1..65599c31 100644
--- a/examples/datavisualization/volumetric/volumetric.cpp
+++ b/examples/datavisualization/volumetric/volumetric.cpp
@@ -23,6 +23,7 @@
#include <QtDataVisualization/q3dtheme.h>
#include <QtDataVisualization/qcustom3dlabel.h>
#include <QtDataVisualization/q3dscatter.h>
+#include <QtDataVisualization/q3dinputhandler.h>
#include <QtCore/qmath.h>
#include <QtWidgets/QLabel>
#include <QtWidgets/QRadioButton>
@@ -86,6 +87,9 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
//! [6]
m_graph->activeTheme()->setBackgroundEnabled(false);
+ // Only allow zooming at the center to avoid clipping issues
+ static_cast<Q3DInputHandler *>(m_graph->activeInputHandler())->setZoomAtTargetEnabled(false);
+
toggleAreaAll(true);
#if !defined(QT_OPENGL_ES_2)
diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc
index 5f06d404..3dc5beea 100644
--- a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc
+++ b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc
@@ -385,3 +385,25 @@
*
* \sa ValueAxis3D::labelFormat
*/
+
+/*!
+ * \qmlproperty vector3d AbstractGraph3D::queriedGraphPosition
+ * \since QtDataVisualization 1.2
+ *
+ * This read-only property contains the latest graph position values along each axis queried using
+ * Scene3D::graphPositionQuery. The values are normalized to range \c{[-1, 1]}.
+ * If the queried position was outside the graph bounds, the values
+ * will not reflect the real position, but will instead be some undefined position outside
+ * the range \c{[-1, 1]}. The value will be undefined before any queries are made.
+ *
+ * There isn't a single correct 3D coordinate to match to each specific screen position, so to be
+ * consistent, the queries are always done against the inner sides of an invisible box surrounding
+ * the graph.
+ *
+ * \note Bar graphs only allow querying graph position at the graph floor level,
+ * so the Y-value is always zero for bar graphs and the valid queries can be only made at
+ * screen positions that contain the floor of the graph.
+ *
+ * \sa Scene3D::graphPositionQuery
+ */
+
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp
index e2f8c1ad..c1d27bab 100644
--- a/src/datavisualization/engine/abstract3dcontroller.cpp
+++ b/src/datavisualization/engine/abstract3dcontroller.cpp
@@ -62,6 +62,7 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen
{
if (!m_scene)
m_scene = new Q3DScene;
+ m_scene->setParent(this);
// Set initial theme
Q3DTheme *defaultTheme = new Q3DTheme(Q3DTheme::ThemeQt);
@@ -165,7 +166,12 @@ void Abstract3DController::synchDataToRenderer()
{
// Subclass implementations check for renderer validity already, so no need to check here.
- // If there is a pending click from renderer, handle that first.
+ // If there are pending queries, handle those first
+ if (m_renderer->isGraphPositionQueryPending()) {
+ handlePendingGraphPositionQuery();
+ m_renderer->clearGraphPositionQueryPending();
+ }
+
if (m_renderer->isClickPending()) {
handlePendingClick();
m_renderer->clearClickPending();
@@ -804,14 +810,15 @@ void Abstract3DController::setActiveInputHandler(QAbstract3DInputHandler *inputH
addInputHandler(inputHandler);
m_activeInputHandler = inputHandler;
- if (m_activeInputHandler)
+ if (m_activeInputHandler) {
m_activeInputHandler->setScene(m_scene);
- // Connect the input handler
- QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::inputViewChanged, this,
- &Abstract3DController::handleInputViewChanged);
- QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::positionChanged, this,
- &Abstract3DController::handleInputPositionChanged);
+ // Connect the input handler
+ QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::inputViewChanged, this,
+ &Abstract3DController::handleInputViewChanged);
+ QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::positionChanged, this,
+ &Abstract3DController::handleInputPositionChanged);
+ }
// Notify change of input handler
emit activeInputHandlerChanged(m_activeInputHandler);
@@ -1468,6 +1475,12 @@ void Abstract3DController::handlePendingClick()
emit elementSelected(type);
}
+void Abstract3DController::handlePendingGraphPositionQuery()
+{
+ m_queriedGraphPosition = m_renderer->queriedGraphPosition();
+ emit queriedGraphPositionChanged(m_queriedGraphPosition);
+}
+
int Abstract3DController::selectedLabelIndex() const
{
int index = m_renderer->m_selectedLabelIndex;
@@ -1659,4 +1672,10 @@ QLocale Abstract3DController::locale() const
return m_locale;
}
+QVector3D Abstract3DController::queriedGraphPosition() const
+{
+ return m_queriedGraphPosition;
+}
+
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h
index 03061a13..125e9885 100644
--- a/src/datavisualization/engine/abstract3dcontroller_p.h
+++ b/src/datavisualization/engine/abstract3dcontroller_p.h
@@ -173,6 +173,7 @@ private:
bool m_reflectionEnabled;
qreal m_reflectivity;
QLocale m_locale;
+ QVector3D m_queriedGraphPosition;
protected:
Q3DScene *m_scene;
@@ -302,6 +303,8 @@ public:
void setLocale(const QLocale &locale);
QLocale locale() const;
+ QVector3D queriedGraphPosition() const;
+
void emitNeedRender();
virtual void clearSelection() = 0;
@@ -327,7 +330,8 @@ public:
virtual void handleAxisTitleVisibilityChangedBySender(QObject *sender);
virtual void handleAxisTitleFixedChangedBySender(QObject *sender);
virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
- virtual void handlePendingClick() = 0;
+ virtual void handlePendingClick();
+ virtual void handlePendingGraphPositionQuery();
virtual void adjustAxisRanges() = 0;
void markSeriesItemLabelsDirty();
@@ -384,6 +388,7 @@ signals:
void reflectionChanged(bool enabled);
void reflectivityChanged(qreal reflectivity);
void localeChanged(const QLocale &locale);
+ void queriedGraphPositionChanged(const QVector3D &data);
protected:
virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation);
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index d0f3c04b..a5e1bc9b 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -54,8 +54,11 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_devicePixelRatio(1.0f),
m_selectionLabelDirty(true),
m_clickPending(false),
+ m_graphPositionQueryPending(false),
m_clickedSeries(0),
m_clickedType(QAbstract3DGraph::ElementNone),
+ m_selectedLabelIndex(-1),
+ m_selectedCustomItemIndex(-1),
m_selectionLabelItem(0),
m_visibleSeriesCount(0),
m_customItemShader(0),
@@ -64,6 +67,9 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_volumeTextureSliceShader(0),
m_volumeSliceFrameShader(0),
m_labelShader(0),
+ m_cursorPositionShader(0),
+ m_cursorPositionFrameBuffer(0),
+ m_cursorPositionTexture(0),
m_useOrthoProjection(false),
m_xFlipped(false),
m_yFlipped(false),
@@ -72,6 +78,7 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_backgroundObj(0),
m_gridLineObj(0),
m_labelObj(0),
+ m_positionMapperObj(0),
m_graphAspectRatio(2.0f),
m_graphHorizontalAspectRatio(0.0f),
m_polarGraph(false),
@@ -110,6 +117,7 @@ Abstract3DRenderer::~Abstract3DRenderer()
delete m_volumeSliceFrameShader;
delete m_volumeTextureSliceShader;
delete m_labelShader;
+ delete m_cursorPositionShader;
foreach (SeriesRenderCache *cache, m_renderCacheList) {
cache->cleanup(m_textureHelper);
@@ -127,9 +135,15 @@ Abstract3DRenderer::~Abstract3DRenderer()
ObjectHelper::releaseObjectHelper(this, m_backgroundObj);
ObjectHelper::releaseObjectHelper(this, m_gridLineObj);
ObjectHelper::releaseObjectHelper(this, m_labelObj);
+ ObjectHelper::releaseObjectHelper(this, m_positionMapperObj);
if (m_textureHelper) {
m_textureHelper->deleteTexture(&m_depthTexture);
+ m_textureHelper->deleteTexture(&m_cursorPositionTexture);
+
+ if (QOpenGLContext::currentContext())
+ m_textureHelper->glDeleteFramebuffers(1, &m_cursorPositionFrameBuffer);
+
delete m_textureHelper;
}
}
@@ -157,6 +171,12 @@ void Abstract3DRenderer::initializeOpenGL()
initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
+
+ initCursorPositionShaders(QStringLiteral(":/shaders/vertexPosition"),
+ QStringLiteral(":/shaders/fragmentPositionMap"));
+
+ loadLabelMesh();
+ loadPositionMapperMesh();
}
void Abstract3DRenderer::render(const GLuint defaultFboHandle)
@@ -191,11 +211,6 @@ void Abstract3DRenderer::updateSelectionState(SelectionState state)
m_selectionState = state;
}
-void Abstract3DRenderer::updateInputPosition(const QPoint &position)
-{
- m_inputPosition = position;
-}
-
void Abstract3DRenderer::initGradientShaders(const QString &vertexShader,
const QString &fragmentShader)
{
@@ -244,6 +259,27 @@ void Abstract3DRenderer::initLabelShaders(const QString &vertexShader, const QSt
m_labelShader->initialize();
}
+void Abstract3DRenderer::initCursorPositionShaders(const QString &vertexShader,
+ const QString &fragmentShader)
+{
+ // Init the shader
+ delete m_cursorPositionShader;
+ m_cursorPositionShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_cursorPositionShader->initialize();
+}
+
+void Abstract3DRenderer::initCursorPositionBuffer()
+{
+ m_textureHelper->deleteTexture(&m_cursorPositionTexture);
+
+ if (m_primarySubViewport.size().isEmpty())
+ return;
+
+ m_cursorPositionTexture =
+ m_textureHelper->createCursorPositionTexture(m_primarySubViewport.size(),
+ m_cursorPositionFrameBuffer);
+}
+
void Abstract3DRenderer::updateTheme(Q3DTheme *theme)
{
// Synchronize the controller theme with renderer
@@ -270,8 +306,12 @@ void Abstract3DRenderer::updateScene(Q3DScene *scene)
}
QPoint logicalPixelPosition = scene->selectionQueryPosition();
- updateInputPosition(QPoint(logicalPixelPosition.x() * m_devicePixelRatio,
- logicalPixelPosition.y() * m_devicePixelRatio));
+ m_inputPosition = QPoint(logicalPixelPosition.x() * m_devicePixelRatio,
+ logicalPixelPosition.y() * m_devicePixelRatio);
+
+ QPoint logicalGraphPosition = scene->graphPositionQuery();
+ m_graphPositionQuery = QPoint(logicalGraphPosition.x() * m_devicePixelRatio,
+ logicalGraphPosition.y() * m_devicePixelRatio);
// Synchronize the renderer scene to controller scene
scene->d_ptr->sync(*m_cachedScene->d_ptr);
@@ -296,6 +336,11 @@ void Abstract3DRenderer::updateScene(Q3DScene *scene)
updateSelectionState(SelectOnScene);
}
}
+
+ if (Q3DScene::invalidSelectionPoint() != logicalGraphPosition) {
+ m_graphPositionQueryPending = true;
+ scene->setGraphPositionQuery(Q3DScene::invalidSelectionPoint());
+ }
}
void Abstract3DRenderer::updateTextures()
@@ -347,7 +392,7 @@ void Abstract3DRenderer::reInitShaders()
QStringLiteral(":/shaders/fragmentTexture3D"),
QStringLiteral(":/shaders/fragmentTexture3DLowDef"),
QStringLiteral(":/shaders/fragmentTexture3DSlice"),
- QStringLiteral(":/shaders/colorAndPosition"),
+ QStringLiteral(":/shaders/vertexPosition"),
QStringLiteral(":/shaders/fragment3DSliceFrames"));
#else
if (m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic)
@@ -434,6 +479,8 @@ void Abstract3DRenderer::handleResize()
// Re-init depth buffer
updateDepthBuffer();
#endif
+
+ initCursorPositionBuffer();
}
void Abstract3DRenderer::calculateZoomLevel()
@@ -929,6 +976,12 @@ void Abstract3DRenderer::loadLabelMesh()
QStringLiteral(":/defaultMeshes/plane"));
}
+void Abstract3DRenderer::loadPositionMapperMesh()
+{
+ ObjectHelper::resetObjectHelper(this, m_positionMapperObj,
+ QStringLiteral(":/defaultMeshes/barFull"));
+}
+
void Abstract3DRenderer::generateBaseColorTexture(const QColor &color, GLuint *texture)
{
m_textureHelper->deleteTexture(texture);
@@ -1305,7 +1358,7 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
// Check that the render item is visible, and skip drawing if not
// Also check if reflected item is on the "wrong" side, and skip drawing if it is
if (!item->isVisible() || ((m_reflectionEnabled && reflection < 0.0f)
- && (m_yFlipped == item->translation().y() >= 0.0))) {
+ && (m_yFlipped == (item->translation().y() >= 0.0)))) {
continue;
}
if (loopCount == 0) {
@@ -1627,6 +1680,59 @@ void Abstract3DRenderer::drawVolumeSliceFrame(const CustomRenderItem *item, Qt::
}
+void Abstract3DRenderer::queriedGraphPosition(const QMatrix4x4 &projectionViewMatrix,
+ const QVector3D &scaling,
+ GLuint defaultFboHandle)
+{
+ m_cursorPositionShader->bind();
+
+ // Set up mapper framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, m_cursorPositionFrameBuffer);
+ glViewport(0, 0,
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
+ glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_DITHER); // Dither may affect colors if enabled
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+
+ // Draw a cube scaled to the graph dimensions
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ modelMatrix.scale(scaling);
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+ m_cursorPositionShader->setUniformValue(m_cursorPositionShader->MVP(), MVPMatrix);
+ m_drawer->drawObject(m_cursorPositionShader, m_positionMapperObj);
+
+ QVector4D dataColor = Utils::getSelection(m_graphPositionQuery,
+ m_primarySubViewport.height());
+ if (dataColor.w() > 0.0f) {
+ // If position is outside the graph, set the position well outside the graph boundaries
+ dataColor = QVector4D(-10000.0f, -10000.0f, -10000.0f, 0.0f);
+ } else {
+ // Normalize to range [0.0, 1.0]
+ dataColor /= 255.0f;
+ }
+
+ // Restore state
+ glEnable(GL_DITHER);
+ glCullFace(GL_BACK);
+ glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
+
+ QVector3D normalizedValues = dataColor.toVector3D() * 2.0f;
+ normalizedValues -= oneVector;
+ m_queriedGraphPosition = QVector3D(normalizedValues.x(),
+ normalizedValues.y(),
+ normalizedValues.z());
+}
+
void Abstract3DRenderer::calculatePolarXZ(const QVector3D &dataPos, float &x, float &z) const
{
// x is angular, z is radial
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index a46e6176..6d134ee3 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -80,7 +80,6 @@ public:
virtual void updateTextures();
virtual void initSelectionBuffer() = 0;
virtual void updateSelectionState(SelectionState state);
- virtual void updateInputPosition(const QPoint &position);
#if !defined(QT_OPENGL_ES_2)
virtual void updateDepthBuffer() = 0;
@@ -99,6 +98,9 @@ public:
const QString &sliceFrameVertexShader,
const QString &sliceFrameShader);
virtual void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
+ virtual void initCursorPositionShaders(const QString &vertexShader,
+ const QString &fragmentShader);
+ virtual void initCursorPositionBuffer();
virtual void updateAxisType(QAbstract3DAxis::AxisOrientation orientation,
QAbstract3DAxis::AxisType type);
@@ -120,7 +122,7 @@ public:
virtual void updateAxisLabelAutoRotation(QAbstract3DAxis::AxisOrientation orientation,
float angle);
virtual void updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientation orientation,
- bool visible);
+ bool visible);
virtual void updateAxisTitleFixed(QAbstract3DAxis::AxisOrientation orientation,
bool fixed);
virtual void modifiedSeriesList(const QVector<QAbstract3DSeries *> &seriesList);
@@ -145,6 +147,9 @@ public:
inline void clearClickPending() { m_clickPending = false; }
inline QAbstract3DSeries *clickedSeries() const { return m_clickedSeries; }
inline QAbstract3DGraph::ElementType clickedType() { return m_clickedType; }
+ inline bool isGraphPositionQueryPending() { return m_graphPositionQueryPending; }
+ inline void clearGraphPositionQueryPending() { m_graphPositionQueryPending = false; }
+ inline QVector3D queriedGraphPosition() const { return m_queriedGraphPosition; }
LabelItem &selectionLabelItem();
void setSelectionLabel(const QString &label);
@@ -199,6 +204,7 @@ protected:
void loadGridLineMesh();
void loadLabelMesh();
+ void loadPositionMapperMesh();
void drawRadialGrid(ShaderHelper *shader, float yFloorLinePos,
const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthMatrix);
@@ -213,6 +219,8 @@ protected:
virtual void getVisibleItemBounds(QVector3D &minBounds, QVector3D &maxBounds) = 0;
void drawVolumeSliceFrame(const CustomRenderItem *item, Qt::Axis axis,
const QMatrix4x4 &projectionViewMatrix);
+ void queriedGraphPosition(const QMatrix4x4 &projectionViewMatrix, const QVector3D &scaling,
+ GLuint defaultFboHandle);
bool m_hasNegativeValues;
Q3DTheme *m_cachedTheme;
@@ -241,10 +249,13 @@ protected:
float m_devicePixelRatio;
bool m_selectionLabelDirty;
bool m_clickPending;
+ bool m_graphPositionQueryPending;
QAbstract3DSeries *m_clickedSeries;
QAbstract3DGraph::ElementType m_clickedType;
int m_selectedLabelIndex;
int m_selectedCustomItemIndex;
+ QVector3D m_queriedGraphPosition;
+ QPoint m_graphPositionQuery;
QString m_selectionLabel;
LabelItem *m_selectionLabelItem;
@@ -256,6 +267,9 @@ protected:
ShaderHelper *m_volumeTextureSliceShader;
ShaderHelper *m_volumeSliceFrameShader;
ShaderHelper *m_labelShader;
+ ShaderHelper *m_cursorPositionShader;
+ GLuint m_cursorPositionFrameBuffer;
+ GLuint m_cursorPositionTexture;
bool m_useOrthoProjection;
bool m_xFlipped;
@@ -266,6 +280,7 @@ protected:
ObjectHelper *m_backgroundObj; // Shared reference
ObjectHelper *m_gridLineObj; // Shared reference
ObjectHelper *m_labelObj; // Shared reference
+ ObjectHelper *m_positionMapperObj; // Shared reference
float m_graphAspectRatio;
float m_graphHorizontalAspectRatio;
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index 9f3c2e2a..2d394d57 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -122,9 +122,6 @@ void Bars3DRenderer::initializeOpenGL()
// Load grid line mesh
loadGridLineMesh();
- // Load label mesh
- loadLabelMesh();
-
// Load background mesh (we need to be initialized first)
loadBackgroundMesh();
}
@@ -1161,6 +1158,16 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
#endif
+ // Do position mapping when necessary
+ if (m_graphPositionQueryPending) {
+ QVector3D graphDimensions(m_xScaleFactor, 0.0f, m_zScaleFactor);
+ queriedGraphPosition(projectionViewMatrix, graphDimensions, defaultFboHandle);
+
+ // Y is always at floor level
+ m_queriedGraphPosition.setY(0.0f);
+ emit needRender();
+ }
+
// Skip selection mode drawing if we're slicing or have no selection mode
if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
&& m_selectionState == SelectOnScene
@@ -2732,8 +2739,11 @@ void Bars3DRenderer::updateSlicingActive(bool isSlicing)
m_cachedIsSlicingActivated = isSlicing;
- if (!m_cachedIsSlicingActivated)
- initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize
+ if (!m_cachedIsSlicingActivated) {
+ // We need to re-init selection buffer in case there has been a resize
+ initSelectionBuffer();
+ initCursorPositionBuffer();
+ }
#if !defined(QT_OPENGL_ES_2)
updateDepthBuffer(); // Re-init depth buffer as well
diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc
index af759ba3..8c234a3b 100644
--- a/src/datavisualization/engine/engine.qrc
+++ b/src/datavisualization/engine/engine.qrc
@@ -67,6 +67,7 @@
<file alias="fragmentTexture3DLowDef">shaders/texture3dlowdef.frag</file>
<file alias="vertexPointES2_UV">shaders/point_ES2_UV.vert</file>
<file alias="fragment3DSliceFrames">shaders/3dsliceframes.frag</file>
- <file alias="colorAndPosition">shaders/colorandposition.vert</file>
+ <file alias="vertexPosition">shaders/position.vert</file>
+ <file alias="fragmentPositionMap">shaders/positionmap.frag</file>
</qresource>
</RCC>
diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp
index 08721b97..87826a8b 100644
--- a/src/datavisualization/engine/q3dscene.cpp
+++ b/src/datavisualization/engine/q3dscene.cpp
@@ -96,6 +96,26 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty point Scene3D::graphPositionQuery
+ *
+ * This property contains the coordinates for the user input that should be processed
+ * by the scene as a graph position query. If this is set to value other than
+ * invalidSelectionPoint, the graph tries to match a graph position to the given \a point
+ * within the primary viewport.
+ * After the rendering pass this property is returned to its default state of
+ * invalidSelectionPoint. The queried graph position can be read from
+ * AbstractGraph3D::queriedGraphPosition property after the next render pass.
+ *
+ * There isn't a single correct 3D coordinate to match to each specific screen position, so to be
+ * consistent, the queries are always done against the inner sides of an invisible box surrounding
+ * the graph.
+ *
+ * \note Bar graphs allow graph position queries only at the graph floor level.
+ *
+ * \sa AbstractGraph3D::queriedGraphPosition
+ */
+
+/*!
* \qmlproperty bool Scene3D::slicingActive
*
* This property contains whether 2D slicing view is currently active or not. If setting it, you
@@ -258,7 +278,7 @@ void Q3DScene::setSecondarySubViewport(const QRect &secondarySubViewport)
* \property Q3DScene::selectionQueryPosition
*
* This property contains the coordinates for the user input that should be processed
- * by the scene as selection. If this is set to value other than invalidSelectionPoint() the
+ * by the scene as a selection. If this is set to value other than invalidSelectionPoint(), the
* graph tries to select a data item, axis label, or a custom item at the given \a point within
* the primary viewport.
* After the rendering pass the property is returned to its default state of
@@ -293,6 +313,42 @@ QPoint Q3DScene::invalidSelectionPoint()
}
/*!
+ * \property Q3DScene::graphPositionQuery
+ *
+ * This property contains the coordinates for the user input that should be processed
+ * by the scene as a graph position query. If this is set to value other than
+ * invalidSelectionPoint(), the graph tries to match a graph position to the given \a point
+ * within the primary viewport.
+ * After the rendering pass this property is returned to its default state of
+ * invalidSelectionPoint(). The queried graph position can be read from
+ * QAbstract3DGraph::queriedGraphPosition property after the next render pass.
+ *
+ * There isn't a single correct 3D coordinate to match to each specific screen position, so to be
+ * consistent, the queries are always done against the inner sides of an invisible box surrounding
+ * the graph.
+ *
+ * \note Bar graphs allow graph position queries only at the graph floor level.
+ *
+ * \sa QAbstract3DGraph::queriedGraphPosition
+ */
+void Q3DScene::setGraphPositionQuery(const QPoint &point)
+{
+ if (point != d_ptr->m_graphPositionQueryPosition) {
+ d_ptr->m_graphPositionQueryPosition = point;
+ d_ptr->m_changeTracker.graphPositionQueryPositionChanged = true;
+ d_ptr->m_sceneDirty = true;
+
+ emit graphPositionQueryChanged(point);
+ emit d_ptr->needRender();
+ }
+}
+
+QPoint Q3DScene::graphPositionQuery() const
+{
+ return d_ptr->m_graphPositionQueryPosition;
+}
+
+/*!
* \property Q3DScene::slicingActive
*
* This property contains whether 2D slicing view is currently active or not. If setting it, you
@@ -453,7 +509,9 @@ Q3DScenePrivate::Q3DScenePrivate(Q3DScene *q) :
m_light(),
m_isUnderSideCameraEnabled(false),
m_isSlicingActive(false),
- m_selectionQueryPosition(Q3DScene::invalidSelectionPoint())
+ m_selectionQueryPosition(Q3DScene::invalidSelectionPoint()),
+ m_graphPositionQueryPosition(Q3DScene::invalidSelectionPoint()),
+ m_sceneDirty(true)
{
}
diff --git a/src/datavisualization/engine/q3dscene.h b/src/datavisualization/engine/q3dscene.h
index 1699b125..a46b4d7b 100644
--- a/src/datavisualization/engine/q3dscene.h
+++ b/src/datavisualization/engine/q3dscene.h
@@ -41,6 +41,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DScene : public QObject
Q_PROPERTY(Q3DCamera* activeCamera READ activeCamera WRITE setActiveCamera NOTIFY activeCameraChanged)
Q_PROPERTY(Q3DLight* activeLight READ activeLight WRITE setActiveLight NOTIFY activeLightChanged)
Q_PROPERTY(float devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged)
+ Q_PROPERTY(QPoint graphPositionQuery READ graphPositionQuery WRITE setGraphPositionQuery NOTIFY graphPositionQueryChanged REVISION 1)
public:
Q3DScene(QObject *parent = 0);
@@ -60,6 +61,9 @@ public:
QPoint selectionQueryPosition() const;
static QPoint invalidSelectionPoint();
+ void setGraphPositionQuery(const QPoint &point);
+ QPoint graphPositionQuery() const;
+
void setSlicingActive(bool isSlicing);
bool isSlicingActive() const;
@@ -85,6 +89,7 @@ signals:
void activeLightChanged(Q3DLight *light);
void devicePixelRatioChanged(float pixelRatio);
void selectionQueryPositionChanged(const QPoint &position);
+ Q_REVISION(1) void graphPositionQueryChanged(const QPoint &position);
private:
QScopedPointer<Q3DScenePrivate> d_ptr;
diff --git a/src/datavisualization/engine/q3dscene_p.h b/src/datavisualization/engine/q3dscene_p.h
index c86a0ec1..b7321c25 100644
--- a/src/datavisualization/engine/q3dscene_p.h
+++ b/src/datavisualization/engine/q3dscene_p.h
@@ -47,6 +47,7 @@ struct Q3DSceneChangeBitField {
bool slicingActivatedChanged : 1;
bool devicePixelRatioChanged : 1;
bool selectionQueryPositionChanged : 1;
+ bool graphPositionQueryPositionChanged : 1;
bool windowSizeChanged : 1;
Q3DSceneChangeBitField()
@@ -59,6 +60,7 @@ struct Q3DSceneChangeBitField {
slicingActivatedChanged(true),
devicePixelRatioChanged(true),
selectionQueryPositionChanged(false),
+ graphPositionQueryPositionChanged(false),
windowSizeChanged(true)
{
}
@@ -108,6 +110,7 @@ public:
bool m_isUnderSideCameraEnabled;
bool m_isSlicingActive;
QPoint m_selectionQueryPosition;
+ QPoint m_graphPositionQueryPosition;
QSize m_windowSize;
QRect m_glViewport;
QRect m_glPrimarySubViewport;
diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp
index 8ced09fe..0249478f 100644
--- a/src/datavisualization/engine/qabstract3dgraph.cpp
+++ b/src/datavisualization/engine/qabstract3dgraph.cpp
@@ -786,6 +786,31 @@ QLocale QAbstract3DGraph::locale() const
}
/*!
+ * \property QAbstract3DGraph::queriedGraphPosition
+ * \since QtDataVisualization 1.2
+ *
+ * This read-only property contains the latest graph position values along each axis queried using
+ * Q3DScene::graphPositionQuery. The values are normalized to range \c{[-1, 1]}.
+ * If the queried position was outside the graph bounds, the values
+ * will not reflect the real position, but will instead be some undefined position outside
+ * the range \c{[-1, 1]}. The value will be undefined before any queries are made.
+ *
+ * There isn't a single correct 3D coordinate to match to each specific screen position, so to be
+ * consistent, the queries are always done against the inner sides of an invisible box surrounding
+ * the graph.
+ *
+ * \note Bar graphs only allow querying graph position at the graph floor level,
+ * so the Y-value is always zero for bar graphs and the valid queries can be only made at
+ * screen positions that contain the floor of the graph.
+ *
+ * \sa Q3DScene::graphPositionQuery
+ */
+QVector3D QAbstract3DGraph::queriedGraphPosition() const
+{
+ return d_ptr->m_visualController->queriedGraphPosition();
+}
+
+/*!
* \internal
*/
bool QAbstract3DGraph::event(QEvent *event)
@@ -948,6 +973,8 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll
&QAbstract3DGraph::reflectivityChanged);
QObject::connect(m_visualController, &Abstract3DController::localeChanged, q_ptr,
&QAbstract3DGraph::localeChanged);
+ QObject::connect(m_visualController, &Abstract3DController::queriedGraphPositionChanged, q_ptr,
+ &QAbstract3DGraph::queriedGraphPositionChanged);
}
void QAbstract3DGraphPrivate::handleDevicePixelRatioChange()
diff --git a/src/datavisualization/engine/qabstract3dgraph.h b/src/datavisualization/engine/qabstract3dgraph.h
index 2d76f780..4a6de4f2 100644
--- a/src/datavisualization/engine/qabstract3dgraph.h
+++ b/src/datavisualization/engine/qabstract3dgraph.h
@@ -57,6 +57,7 @@ class QT_DATAVISUALIZATION_EXPORT QAbstract3DGraph : public QWindow, protected Q
Q_PROPERTY(bool reflection READ isReflection WRITE setReflection NOTIFY reflectionChanged)
Q_PROPERTY(qreal reflectivity READ reflectivity WRITE setReflectivity NOTIFY reflectivityChanged)
Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged)
+ Q_PROPERTY(QVector3D queriedGraphPosition READ queriedGraphPosition NOTIFY queriedGraphPositionChanged)
protected:
explicit QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format,
@@ -175,6 +176,8 @@ public:
void setLocale(const QLocale &locale);
QLocale locale() const;
+ QVector3D queriedGraphPosition() const;
+
protected:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *event);
@@ -204,6 +207,7 @@ signals:
void reflectionChanged(bool enabled);
void reflectivityChanged(qreal reflectivity);
void localeChanged(const QLocale &locale);
+ void queriedGraphPositionChanged(const QVector3D &data);
private:
Q_DISABLE_COPY(QAbstract3DGraph)
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index e9e395be..d1dca8c6 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -117,9 +117,6 @@ void Scatter3DRenderer::initializeOpenGL()
loadGridLineMesh();
#endif
- // Load label mesh
- loadLabelMesh();
-
// Set view port
glViewport(m_primarySubViewport.x(),
m_primarySubViewport.y(),
@@ -651,6 +648,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#endif
ShaderHelper *selectionShader = m_selectionShader;
+ // Do position mapping when necessary
+ if (m_graphPositionQueryPending) {
+ QVector3D graphDimensions(m_scaleX, m_scaleY, m_scaleZ);
+ queriedGraphPosition(projectionViewMatrix, graphDimensions, defaultFboHandle);
+ emit needRender();
+ }
+
// Skip selection mode drawing if we have no selection mode
if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
&& SelectOnScene == m_selectionState
diff --git a/src/datavisualization/engine/shaders/colorandposition.vert b/src/datavisualization/engine/shaders/position.vert
index 34849eae..34849eae 100644
--- a/src/datavisualization/engine/shaders/colorandposition.vert
+++ b/src/datavisualization/engine/shaders/position.vert
diff --git a/src/datavisualization/engine/shaders/positionmap.frag b/src/datavisualization/engine/shaders/positionmap.frag
new file mode 100644
index 00000000..9a277ab8
--- /dev/null
+++ b/src/datavisualization/engine/shaders/positionmap.frag
@@ -0,0 +1,11 @@
+varying highp vec3 pos;
+
+void main() {
+ // This shader encodes the axis position into the vertex color, assuming the object
+ // is a cube filling the entire data area of the graph
+ gl_FragColor = vec4((pos.x + 1.0) / 2.0,
+ (pos.y + 1.0) / 2.0,
+ (-pos.z + 1.0) / 2.0,
+ 0.0);
+}
+
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 9121e37c..3d39a71d 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -131,9 +131,6 @@ void Surface3DRenderer::initializeOpenGL()
loadGridLineMesh();
#endif
- // Load label mesh
- loadLabelMesh();
-
// Resize in case we've missed resize events
// Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here
handleResize();
@@ -1297,6 +1294,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
#endif
+ // Do position mapping when necessary
+ if (m_graphPositionQueryPending) {
+ QVector3D graphDimensions(m_scaleX, m_scaleY, m_scaleZ);
+ queriedGraphPosition(projectionViewMatrix, graphDimensions, defaultFboHandle);
+ emit needRender();
+ }
+
// Draw selection buffer
if (!m_cachedIsSlicingActivated && (!m_renderCacheList.isEmpty()
|| !m_customRenderCache.isEmpty())
@@ -2830,8 +2834,11 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing)
m_cachedIsSlicingActivated = isSlicing;
- if (!m_cachedIsSlicingActivated)
- initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize
+ if (!m_cachedIsSlicingActivated) {
+ // We need to re-init selection buffer in case there has been a resize
+ initSelectionBuffer();
+ initCursorPositionBuffer();
+ }
#if !defined(QT_OPENGL_ES_2)
updateDepthBuffer(); // Re-init depth buffer as well
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;
diff --git a/src/datavisualization/utils/texturehelper.cpp b/src/datavisualization/utils/texturehelper.cpp
index 5e21b5cd..9dbf0613 100644
--- a/src/datavisualization/utils/texturehelper.cpp
+++ b/src/datavisualization/utils/texturehelper.cpp
@@ -218,6 +218,31 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf
return textureid;
}
+GLuint TextureHelper::createCursorPositionTexture(const QSize &size, GLuint &frameBuffer)
+{
+ GLuint textureid;
+ glGenTextures(1, &textureid);
+ glBindTexture(GL_TEXTURE_2D, textureid);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenFramebuffers(1, &frameBuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ textureid, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ qCritical() << "Cursor position mapper frame buffer creation failed:" << status;
+ glDeleteTextures(1, &textureid);
+ textureid = 0;
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return textureid;
+}
+
GLuint TextureHelper::createUniformTexture(const QColor &color)
{
QImage image(QSize(int(uniformTextureWidth), int(uniformTextureHeight)),
diff --git a/src/datavisualization/utils/texturehelper_p.h b/src/datavisualization/utils/texturehelper_p.h
index c1dfe8c9..03080b2a 100644
--- a/src/datavisualization/utils/texturehelper_p.h
+++ b/src/datavisualization/utils/texturehelper_p.h
@@ -55,6 +55,7 @@ class TextureHelper : protected QOpenGLFunctions
GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false);
// Returns selection texture and inserts generated framebuffers to framebuffer parameters
GLuint createSelectionTexture(const QSize &size, GLuint &frameBuffer, GLuint &depthBuffer);
+ GLuint createCursorPositionTexture(const QSize &size, GLuint &frameBuffer);
GLuint createUniformTexture(const QColor &color);
GLuint createGradientTexture(const QLinearGradient &gradient);
#if !defined(QT_OPENGL_ES_2)
@@ -75,6 +76,7 @@ class TextureHelper : protected QOpenGLFunctions
friend class Bars3DRenderer;
friend class Surface3DRenderer;
friend class Scatter3DRenderer;
+ friend class Abstract3DRenderer;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp
index fdfa55d8..9206973a 100644
--- a/src/datavisualizationqml2/abstractdeclarative.cpp
+++ b/src/datavisualizationqml2/abstractdeclarative.cpp
@@ -341,6 +341,8 @@ void AbstractDeclarative::setSharedController(Abstract3DController *controller)
&AbstractDeclarative::reflectivityChanged);
QObject::connect(m_controller.data(), &Abstract3DController::localeChanged, this,
&AbstractDeclarative::localeChanged);
+ QObject::connect(m_controller.data(), &Abstract3DController::queriedGraphPositionChanged, this,
+ &AbstractDeclarative::queriedGraphPositionChanged);
}
void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window)
@@ -796,6 +798,11 @@ QLocale AbstractDeclarative::locale() const
return m_controller->locale();
}
+QVector3D AbstractDeclarative::queriedGraphPosition() const
+{
+ return m_controller->queriedGraphPosition();
+}
+
void AbstractDeclarative::windowDestroyed(QObject *obj)
{
// Remove destroyed window from window lists
diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h
index 52a5956b..8dc260c2 100644
--- a/src/datavisualizationqml2/abstractdeclarative_p.h
+++ b/src/datavisualizationqml2/abstractdeclarative_p.h
@@ -78,6 +78,7 @@ class AbstractDeclarative : public QQuickItem
Q_PROPERTY(bool reflection READ isReflection WRITE setReflection NOTIFY reflectionChanged REVISION 2)
Q_PROPERTY(qreal reflectivity READ reflectivity WRITE setReflectivity NOTIFY reflectivityChanged REVISION 2)
Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged REVISION 2)
+ Q_PROPERTY(QVector3D queriedGraphPosition READ queriedGraphPosition NOTIFY queriedGraphPositionChanged REVISION 2)
public:
enum SelectionFlag {
@@ -217,6 +218,8 @@ public:
void setLocale(const QLocale &locale);
QLocale locale() const;
+ QVector3D queriedGraphPosition() const;
+
public slots:
virtual void handleAxisXChanged(QAbstract3DAxis *axis) = 0;
virtual void handleAxisYChanged(QAbstract3DAxis *axis) = 0;
@@ -260,6 +263,7 @@ signals:
Q_REVISION(2) void reflectionChanged(bool enabled);
Q_REVISION(2) void reflectivityChanged(qreal reflectivity);
Q_REVISION(2) void localeChanged(const QLocale &locale);
+ Q_REVISION(2) void queriedGraphPositionChanged(const QVector3D &data);
private:
QPointer<Abstract3DController> m_controller;
diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
index a22fc55c..5aaebf03 100644
--- a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
+++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
@@ -113,6 +113,8 @@ void QtDataVisualizationQml2Plugin::registerTypes(const char *uri)
// New revisions
qmlRegisterUncreatableType<AbstractDeclarative, 2>(uri, 1, 2, "AbstractGraph3D",
QLatin1String("Trying to create uncreatable: AbstractGraph3D."));
+ qmlRegisterUncreatableType<Declarative3DScene, 1>(uri, 1, 2, "Scene3D",
+ QLatin1String("Trying to create uncreatable: Scene3D."));
qmlRegisterType<DeclarativeSurface, 1>(uri, 1, 2, "Surface3D");
qmlRegisterType<Q3DCamera, 1>(uri, 1, 2, "Camera3D");
qmlRegisterType<QCustom3DItem, 1>(uri, 1, 2, "Custom3DItem");
diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp
index 9a81fc86..d7b23719 100644
--- a/tests/barstest/chart.cpp
+++ b/tests/barstest/chart.cpp
@@ -203,6 +203,7 @@ GraphModifier::GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog)
m_graph->activeTheme()->setFont(QFont("Times Roman", 20));
+
// Release and store the default input handler.
m_defaultInputHandler = static_cast<Q3DInputHandler *>(m_graph->activeInputHandler());
m_graph->releaseInputHandler(m_defaultInputHandler);
@@ -1421,6 +1422,11 @@ void GraphModifier::setInputHandlerSelectionEnabled(int enabled)
m_defaultInputHandler->setSelectionEnabled(enabled);
}
+void GraphModifier::setInputHandlerZoomAtTargetEnabled(int enabled)
+{
+ m_defaultInputHandler->setZoomAtTargetEnabled(enabled);
+}
+
void GraphModifier::changeValueAxisSegments(int value)
{
qDebug() << __FUNCTION__ << value;
diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h
index eac6d3f1..93abbfa4 100644
--- a/tests/barstest/chart.h
+++ b/tests/barstest/chart.h
@@ -97,6 +97,7 @@ public:
void setInputHandlerRotationEnabled(int enabled);
void setInputHandlerZoomEnabled(int enabled);
void setInputHandlerSelectionEnabled(int enabled);
+ void setInputHandlerZoomAtTargetEnabled(int enabled);
void setReflection(bool enabled);
void setReflectivity(int value);
void toggleCustomItem();
diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp
index 1cc47859..cffbf4b4 100644
--- a/tests/barstest/main.cpp
+++ b/tests/barstest/main.cpp
@@ -234,6 +234,10 @@ int main(int argc, char **argv)
inputHandlerSelectionCheckBox->setText("IH: Allow selection");
inputHandlerSelectionCheckBox->setChecked(true);
+ QCheckBox *inputHandlerZoomAtTargetCheckBox = new QCheckBox(widget);
+ inputHandlerZoomAtTargetCheckBox->setText("IH: setZoomAtTarget");
+ inputHandlerZoomAtTargetCheckBox->setChecked(false);
+
QSlider *rotationSliderX = new QSlider(Qt::Horizontal, widget);
rotationSliderX->setTickInterval(1);
rotationSliderX->setMinimum(-180);
@@ -422,6 +426,7 @@ int main(int argc, char **argv)
vLayout3->addWidget(inputHandlerRotationCheckBox, 0, Qt::AlignTop);
vLayout3->addWidget(inputHandlerZoomCheckBox, 0, Qt::AlignTop);
vLayout3->addWidget(inputHandlerSelectionCheckBox, 0, Qt::AlignTop);
+ vLayout3->addWidget(inputHandlerZoomAtTargetCheckBox, 0, Qt::AlignTop);
vLayout3->addWidget(new QLabel(QStringLiteral("Adjust shadow quality")), 0, Qt::AlignTop);
vLayout3->addWidget(shadowQuality, 0, Qt::AlignTop);
vLayout3->addWidget(new QLabel(QStringLiteral("Change font")), 0, Qt::AlignTop);
@@ -559,6 +564,8 @@ int main(int argc, char **argv)
&GraphModifier::setInputHandlerZoomEnabled);
QObject::connect(inputHandlerSelectionCheckBox, &QCheckBox::stateChanged, modifier,
&GraphModifier::setInputHandlerSelectionEnabled);
+ QObject::connect(inputHandlerZoomAtTargetCheckBox, &QCheckBox::stateChanged, modifier,
+ &GraphModifier::setInputHandlerZoomAtTargetEnabled);
QObject::connect(rotationCheckBox, &QCheckBox::stateChanged, modifier,
&GraphModifier::setUseNullInputHandler);
diff --git a/tests/scattertest/scatterchart.cpp b/tests/scattertest/scatterchart.cpp
index 35d56236..a45c090b 100644
--- a/tests/scattertest/scatterchart.cpp
+++ b/tests/scattertest/scatterchart.cpp
@@ -23,6 +23,7 @@
#include <QtDataVisualization/q3dscene.h>
#include <QtDataVisualization/q3dcamera.h>
#include <QtDataVisualization/q3dtheme.h>
+#include <QtDataVisualization/Q3DInputHandler>
#include <qmath.h>
using namespace QtDataVisualization;
@@ -46,6 +47,7 @@ ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter)
m_chart->setAxisX(new QValue3DAxis);
m_chart->setAxisY(new QValue3DAxis);
m_chart->setAxisZ(new QValue3DAxis);
+ static_cast<Q3DInputHandler *>(m_chart->activeInputHandler())->setZoomAtTargetEnabled(true);
createAndAddSeries();
createAndAddSeries();
@@ -435,6 +437,10 @@ void ScatterDataModifier::testAxisReverse()
m_chart->axisX()->setRange(0.0f, 10.0f);
m_chart->axisY()->setRange(-20.0f, 50.0f);
m_chart->axisZ()->setRange(5.0f, 15.0f);
+ m_chart->axisX()->setTitle("Axis X");
+ m_chart->axisZ()->setTitle("Axis Z");
+ m_chart->axisX()->setTitleVisible(true);
+ m_chart->axisZ()->setTitleVisible(true);
m_chart->addSeries(series0);
m_chart->addSeries(series1);
}
diff --git a/tests/surfacetest/graphmodifier.cpp b/tests/surfacetest/graphmodifier.cpp
index a22ede2b..1a069cf4 100644
--- a/tests/surfacetest/graphmodifier.cpp
+++ b/tests/surfacetest/graphmodifier.cpp
@@ -21,18 +21,21 @@
#include <QtDataVisualization/QSurfaceDataProxy>
#include <QtDataVisualization/QSurface3DSeries>
#include <QtDataVisualization/Q3DTheme>
+#include <QtDataVisualization/Q3DInputHandler>
#include <qmath.h>
#include <QLinearGradient>
#include <QDebug>
#include <QComboBox>
-
+#ifndef QT_NO_CURSOR
+#include <QtGui/QCursor>
+#endif
using namespace QtDataVisualization;
//#define JITTER_PLANE
//#define WONKY_PLANE
-GraphModifier::GraphModifier(Q3DSurface *graph)
+GraphModifier::GraphModifier(Q3DSurface *graph, QWidget *parentWidget)
: m_graph(graph),
m_series1(new QSurface3DSeries),
m_series2(new QSurface3DSeries),
@@ -63,7 +66,8 @@ GraphModifier::GraphModifier(Q3DSurface *graph)
m_drawMode2(QSurface3DSeries::DrawSurfaceAndWireframe),
m_drawMode3(QSurface3DSeries::DrawSurfaceAndWireframe),
m_drawMode4(QSurface3DSeries::DrawSurfaceAndWireframe),
- m_offset(4.0f)
+ m_offset(4.0f),
+ m_parentWidget(parentWidget)
{
m_graph->setAxisX(new QValue3DAxis);
m_graph->axisX()->setTitle("X-Axis");
@@ -97,6 +101,8 @@ GraphModifier::GraphModifier(Q3DSurface *graph)
m_graph->axisY()->setRange(m_minY, m_minY + m_rangeY);
m_graph->axisZ()->setRange(m_minZ, m_minZ + m_rangeZ);
+ static_cast<Q3DInputHandler *>(m_graph->activeInputHandler())->setZoomAtTargetEnabled(true);
+
for (int i = 0; i < 4; i++) {
m_multiseries[i] = new QSurface3DSeries;
m_multiseries[i]->setName(QStringLiteral("Series %1").arg(i+1));
@@ -109,6 +115,7 @@ GraphModifier::GraphModifier(Q3DSurface *graph)
m_theSeries->setItemLabelFormat(QStringLiteral("@seriesName: (@xLabel, @zLabel): @yLabel"));
connect(&m_timer, &QTimer::timeout, this, &GraphModifier::timeout);
+ connect(&m_graphPositionQueryTimer, &QTimer::timeout, this, &GraphModifier::graphQueryTimeout);
connect(m_theSeries, &QSurface3DSeries::selectedPointChanged, this, &GraphModifier::selectedPointChanged);
QObject::connect(m_graph, &Q3DSurface::axisXChanged, this,
@@ -119,6 +126,8 @@ GraphModifier::GraphModifier(Q3DSurface *graph)
&GraphModifier::handleAxisZChanged);
QObject::connect(m_graph, &QAbstract3DGraph::currentFpsChanged, this,
&GraphModifier::handleFpsChange);
+
+ //m_graphPositionQueryTimer.start(100);
}
GraphModifier::~GraphModifier()
@@ -691,6 +700,16 @@ void GraphModifier::timeout()
m_theSeries->dataProxy()->resetArray(m_planeArray);
}
+void GraphModifier::graphQueryTimeout()
+{
+#ifndef QT_NO_CURSOR
+ m_graph->scene()->setGraphPositionQuery(m_parentWidget->mapFromGlobal(QCursor::pos()));
+ qDebug() << "pos: " << (m_parentWidget->mapFromGlobal(QCursor::pos()));
+#else
+ m_graph->scene()->setGraphPositionQuery(QPoint(100, 100));
+#endif
+}
+
void GraphModifier::handleAxisXChanged(QValue3DAxis *axis)
{
qDebug() << __FUNCTION__ << axis << axis->orientation() << (axis == m_graph->axisX());
diff --git a/tests/surfacetest/graphmodifier.h b/tests/surfacetest/graphmodifier.h
index f461f022..d1c77940 100644
--- a/tests/surfacetest/graphmodifier.h
+++ b/tests/surfacetest/graphmodifier.h
@@ -41,7 +41,7 @@ public:
Map
};
- explicit GraphModifier(Q3DSurface *graph);
+ explicit GraphModifier(Q3DSurface *graph, QWidget *parentWidget);
~GraphModifier();
void toggleSeries1(bool enabled);
@@ -122,6 +122,7 @@ public slots:
void flipViews();
void changeSelectionMode(int mode);
void timeout();
+ void graphQueryTimeout();
void handleAxisXChanged(QValue3DAxis *axis);
void handleAxisYChanged(QValue3DAxis *axis);
@@ -190,6 +191,8 @@ private:
float m_multiSampleOffsetZ[4];
QSurfaceDataArray m_massiveTestCacheArray;
QVector3D m_cameraTarget;
+ QWidget *m_parentWidget;
+ QTimer m_graphPositionQueryTimer;
};
#endif
diff --git a/tests/surfacetest/main.cpp b/tests/surfacetest/main.cpp
index f89e6c50..9e14c665 100644
--- a/tests/surfacetest/main.cpp
+++ b/tests/surfacetest/main.cpp
@@ -524,7 +524,7 @@ int main(int argc, char *argv[])
widget->show();
- GraphModifier *modifier = new GraphModifier(surfaceGraph);
+ GraphModifier *modifier = new GraphModifier(surfaceGraph, container);
// Connect controls to slots on modifier
QObject::connect(smoothCB, &QCheckBox::stateChanged,
diff --git a/tests/volumetrictest/volumetrictest.pro b/tests/volumetrictest/volumetrictest.pro
index 137e5bab..df3ef0dd 100644
--- a/tests/volumetrictest/volumetrictest.pro
+++ b/tests/volumetrictest/volumetrictest.pro
@@ -1,7 +1,3 @@
-android|ios {
- error( "This example is not supported for android or ios." )
-}
-
!include( ../tests.pri ) {
error( "Couldn't find the tests.pri file!" )
}