diff options
author | Tomi Korpipää <tomi.korpipaa@digia.com> | 2013-09-10 11:42:13 +0300 |
---|---|---|
committer | Tomi Korpipää <tomi.korpipaa@digia.com> | 2013-09-10 12:04:24 +0300 |
commit | a28cdb72a4ea768a898ca07f0df0fa3c17c073a8 (patch) | |
tree | 0bafdcfa99fc783e9f5204539a8242bf6128d795 /src/datavisualization/engine/abstract3dcontroller.cpp | |
parent | f3e38983d77c72f3121c33a149a58fdf9c64158c (diff) |
Module renamed
Task-number: QTRD-2224
Change-Id: Iec18b6121809300b11d85445281d3c626c434f35
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src/datavisualization/engine/abstract3dcontroller.cpp')
-rw-r--r-- | src/datavisualization/engine/abstract3dcontroller.cpp | 1057 |
1 files changed, 1057 insertions, 0 deletions
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp new file mode 100644 index 00000000..2f3476dc --- /dev/null +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -0,0 +1,1057 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "abstract3dcontroller_p.h" +#include "camerahelper_p.h" +#include "q3dabstractaxis_p.h" +#include "q3dvalueaxis.h" +#include "q3dcategoryaxis.h" +#include "abstract3drenderer_p.h" +#include "q3dcamera.h" +#include "q3dlight.h" +#include "qabstractdataproxy_p.h" +#include "qabstract3dinputhandler.h" + +#if defined(Q_OS_ANDROID) +#include "qtouch3dinputhandler.h" +#else +#include "q3dinputhandler.h" +#endif + +#include <QThread> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : + QObject(parent), + m_boundingRect(boundRect.x(), boundRect.y(), boundRect.width(), boundRect.height()), + m_horizontalRotation(-45.0f), + m_verticalRotation(15.0f), + m_theme(), + m_font(QFont(QStringLiteral("Arial"))), + m_selectionMode(QDataVis::ModeItem), + m_shadowQuality(QDataVis::ShadowMedium), + m_labelTransparency(QDataVis::TransparencyNoBackground), + m_isBackgroundEnabled(true), + m_isGridEnabled(true), + m_scene(new Q3DScene()), + m_activeInputHandler(0), + m_axisX(0), + m_axisY(0), + m_axisZ(0), + m_renderer(0), + m_isDataDirty(true), + m_data(0), + m_renderPending(false) +{ + m_theme.useColorTheme(QDataVis::ThemeSystem); + + // Populate the scene + m_scene->setCamera(new Q3DCamera()); + m_scene->setLight(new Q3DLight()); + m_scene->light()->setPosition(defaultLightPos); + + // Create initial default input handler + QAbstract3DInputHandler *inputHandler; +#if defined(Q_OS_ANDROID) + inputHandler = new QTouch3DInputHandler(); +#else + inputHandler = new Q3DInputHandler(); +#endif + inputHandler->d_ptr->m_isDefaultHandler = true; + setActiveInputHandler(inputHandler); +} + +Abstract3DController::~Abstract3DController() +{ + // Renderer can be in another thread, don't delete it directly in that case + if (m_renderer && m_renderer->thread() != QThread::currentThread()) + m_renderer->deleteLater(); + else + delete m_renderer; + delete m_scene; +} + +void Abstract3DController::setRenderer(Abstract3DRenderer *renderer) +{ + m_renderer = renderer; +} + +void Abstract3DController::synchDataToRenderer() +{ + // If we don't have a renderer, don't do anything + if (!m_renderer) + return; + + m_renderer->updateScene(m_scene); + + if (m_changeTracker.positionChanged) { + m_renderer->updatePosition(m_boundingRect); + m_changeTracker.positionChanged = false; + } + + if (m_changeTracker.themeChanged) { + m_renderer->updateTheme(m_theme); + m_changeTracker.themeChanged = false; + } + + if (m_changeTracker.fontChanged) { + m_renderer->updateFont(m_font); + m_changeTracker.fontChanged = false; + } + + if (m_changeTracker.labelTransparencyChanged) { + m_renderer->updateLabelTransparency(m_labelTransparency); + m_changeTracker.labelTransparencyChanged = false; + } + + if (m_changeTracker.boundingRectChanged || m_changeTracker.sizeChanged) { + m_renderer->updateBoundingRect(m_boundingRect); + m_changeTracker.boundingRectChanged = false; + m_changeTracker.sizeChanged = false; + } + + if (m_changeTracker.shadowQualityChanged) { + m_renderer->updateShadowQuality(m_shadowQuality); + m_changeTracker.shadowQualityChanged = false; + } + + if (m_changeTracker.selectionModeChanged) { + m_renderer->updateSelectionMode(m_selectionMode); + m_changeTracker.selectionModeChanged = false; + } + + if (m_changeTracker.objFileChanged) { + m_renderer->updateMeshFileName(m_objFile); + m_changeTracker.objFileChanged = false; + } + + if (m_changeTracker.gridEnabledChanged) { + m_renderer->updateGridEnabled(m_isGridEnabled); + m_changeTracker.gridEnabledChanged = false; + } + + if (m_changeTracker.backgroundEnabledChanged) { + m_renderer->updateBackgroundEnabled(m_isBackgroundEnabled); + m_changeTracker.backgroundEnabledChanged = false; + } + + if (m_changeTracker.axisXTypeChanged) { + m_renderer->updateAxisType(Q3DAbstractAxis::AxisOrientationX, m_axisX->type()); + m_changeTracker.axisXTypeChanged = false; + } + + if (m_changeTracker.axisYTypeChanged) { + m_renderer->updateAxisType(Q3DAbstractAxis::AxisOrientationY, m_axisY->type()); + m_changeTracker.axisYTypeChanged = false; + } + + if (m_changeTracker.axisZTypeChanged) { + m_renderer->updateAxisType(Q3DAbstractAxis::AxisOrientationZ, m_axisZ->type()); + m_changeTracker.axisZTypeChanged = false; + } + + if (m_changeTracker.axisXTitleChanged) { + m_renderer->updateAxisTitle(Q3DAbstractAxis::AxisOrientationX, m_axisX->title()); + m_changeTracker.axisXTitleChanged = false; + } + + if (m_changeTracker.axisYTitleChanged) { + m_renderer->updateAxisTitle(Q3DAbstractAxis::AxisOrientationY, m_axisY->title()); + m_changeTracker.axisYTitleChanged = false; + } + + if (m_changeTracker.axisZTitleChanged) { + m_renderer->updateAxisTitle(Q3DAbstractAxis::AxisOrientationZ, m_axisZ->title()); + m_changeTracker.axisZTitleChanged = false; + } + + if (m_changeTracker.axisXLabelsChanged) { + m_renderer->updateAxisLabels(Q3DAbstractAxis::AxisOrientationX, m_axisX->labels()); + m_changeTracker.axisXLabelsChanged = false; + } + + if (m_changeTracker.axisYLabelsChanged) { + m_renderer->updateAxisLabels(Q3DAbstractAxis::AxisOrientationY, m_axisY->labels()); + m_changeTracker.axisYLabelsChanged = false; + } + if (m_changeTracker.axisZLabelsChanged) { + m_renderer->updateAxisLabels(Q3DAbstractAxis::AxisOrientationZ, m_axisZ->labels()); + m_changeTracker.axisZLabelsChanged = false; + } + + if (m_changeTracker.axisXRangeChanged) { + m_changeTracker.axisXRangeChanged = false; + if (m_axisX->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX); + m_renderer->updateAxisRange(Q3DAbstractAxis::AxisOrientationX, + valueAxisX->min(), valueAxisX->max()); + } + } + + if (m_changeTracker.axisYRangeChanged) { + m_changeTracker.axisYRangeChanged = false; + if (m_axisY->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY); + m_renderer->updateAxisRange(Q3DAbstractAxis::AxisOrientationY, + valueAxisY->min(), valueAxisY->max()); + } + } + + if (m_changeTracker.axisZRangeChanged) { + m_changeTracker.axisZRangeChanged = false; + if (m_axisZ->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ); + m_renderer->updateAxisRange(Q3DAbstractAxis::AxisOrientationZ, + valueAxisZ->min(), valueAxisZ->max()); + } + } + + if (m_changeTracker.axisXSegmentCountChanged) { + m_changeTracker.axisXSegmentCountChanged = false; + if (m_axisX->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX); + m_renderer->updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientationX, + valueAxisX->segmentCount()); + } + } + + if (m_changeTracker.axisYSegmentCountChanged) { + m_changeTracker.axisYSegmentCountChanged = false; + if (m_axisY->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY); + m_renderer->updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientationY, + valueAxisY->segmentCount()); + } + } + + if (m_changeTracker.axisZSegmentCountChanged) { + m_changeTracker.axisZSegmentCountChanged = false; + if (m_axisZ->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ); + m_renderer->updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientationZ, + valueAxisZ->segmentCount()); + } + } + + if (m_changeTracker.axisXSubSegmentCountChanged) { + m_changeTracker.axisXSubSegmentCountChanged = false; + if (m_axisX->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX); + m_renderer->updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientationX, + valueAxisX->subSegmentCount()); + } + } + + if (m_changeTracker.axisYSubSegmentCountChanged) { + m_changeTracker.axisYSubSegmentCountChanged = false; + if (m_axisY->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY); + m_renderer->updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientationY, + valueAxisY->subSegmentCount()); + } + } + + if (m_changeTracker.axisZSubSegmentCountChanged) { + m_changeTracker.axisZSubSegmentCountChanged = false; + if (m_axisZ->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ); + m_renderer->updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientationZ, + valueAxisZ->subSegmentCount()); + } + } + + if (m_changeTracker.axisXLabelFormatChanged) { + m_changeTracker.axisXLabelFormatChanged = false; + if (m_axisX->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX); + m_renderer->updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientationX, + valueAxisX->labelFormat()); + } + } + + if (m_changeTracker.axisYLabelFormatChanged) { + m_changeTracker.axisYLabelFormatChanged = false; + if (m_axisY->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY); + m_renderer->updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientationY, + valueAxisY->labelFormat()); + } + } + + if (m_changeTracker.axisZLabelFormatChanged) { + m_changeTracker.axisZLabelFormatChanged = false; + if (m_axisZ->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ); + m_renderer->updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientationZ, + valueAxisZ->labelFormat()); + } + } +} + +void Abstract3DController::render(const GLuint defaultFboHandle) +{ + m_renderPending = false; + + // If not initialized, do nothing. + if (!m_renderer) + return; + + m_renderer->render(defaultFboHandle); + +#ifdef DISPLAY_RENDER_SPEED + // To get meaningful framerate, don't just do render on demand. + emitNeedRender(); +#endif +} + +void Abstract3DController::mouseDoubleClickEvent(QMouseEvent *event) +{ + m_activeInputHandler->mouseDoubleClickEvent(event); + emitNeedRender(); +} + +void Abstract3DController::touchEvent(QTouchEvent *event) +{ + m_activeInputHandler->touchEvent(event); + emitNeedRender(); +} + +void Abstract3DController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ + m_activeInputHandler->mousePressEvent(event, mousePos); + emitNeedRender(); +} + +void Abstract3DController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + m_activeInputHandler->mouseReleaseEvent(event, mousePos); + emitNeedRender(); +} + +void Abstract3DController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + m_activeInputHandler->mouseMoveEvent(event, mousePos); + emitNeedRender(); +} + +void Abstract3DController::wheelEvent(QWheelEvent *event) +{ + m_activeInputHandler->wheelEvent(event); + emitNeedRender(); +} + +void Abstract3DController::setSize(const int width, const int height) +{ + m_boundingRect.setWidth(width); + m_boundingRect.setHeight(height); + m_scene->setViewportSize(width, height); + + m_changeTracker.boundingRectChanged = true; + emitNeedRender(); +} + +const QSize Abstract3DController::size() +{ + return m_boundingRect.size(); +} + +const QRect Abstract3DController::boundingRect() +{ + return m_boundingRect; +} + +void Abstract3DController::setBoundingRect(const QRect boundingRect) +{ + m_boundingRect = boundingRect; + m_scene->setViewport(boundingRect); + + m_changeTracker.boundingRectChanged = true; + emitNeedRender(); +} + +void Abstract3DController::setWidth(const int width) +{ + m_boundingRect.setWidth(width); + m_scene->setViewportSize(width, m_scene->viewport().height()); + + m_changeTracker.sizeChanged = true; + emitNeedRender(); +} + +int Abstract3DController::width() +{ + return m_boundingRect.width(); +} + +void Abstract3DController::setHeight(const int height) +{ + m_boundingRect.setHeight(height); + m_scene->setViewportSize(m_scene->viewport().width(), height); + + m_changeTracker.sizeChanged = true; + emitNeedRender(); +} + +int Abstract3DController::height() +{ + return m_boundingRect.height(); +} + +void Abstract3DController::setX(const int x) +{ + m_boundingRect.setX(x); + + m_changeTracker.positionChanged = true; + emitNeedRender(); +} + +int Abstract3DController::x() +{ + return m_boundingRect.x(); +} + +void Abstract3DController::setY(const int y) +{ + m_boundingRect.setY(y); + + m_changeTracker.positionChanged = true; + emitNeedRender(); +} + +int Abstract3DController::y() +{ + return m_boundingRect.y(); +} + +QRect Abstract3DController::mainViewport() const +{ + return m_scene->mainViewport(); +} + +void Abstract3DController::setMainViewport(const QRect &mainViewport) +{ + m_scene->setMainViewport(mainViewport); +} + +QRect Abstract3DController::sliceViewport() const +{ + return m_scene->sliceViewport(); +} + +void Abstract3DController::setSliceViewport(const QRect &sliceViewport) +{ + m_scene->setSliceViewport(sliceViewport); +} + +void Abstract3DController::setAxisX(Q3DAbstractAxis *axis) +{ + setAxisHelper(Q3DAbstractAxis::AxisOrientationX, axis, &m_axisX); +} + +Q3DAbstractAxis *Abstract3DController::axisX() +{ + return m_axisX; +} + +void Abstract3DController::setAxisY(Q3DAbstractAxis *axis) +{ + setAxisHelper(Q3DAbstractAxis::AxisOrientationY, axis, &m_axisY); +} + +Q3DAbstractAxis *Abstract3DController::axisY() +{ + return m_axisY; +} + +void Abstract3DController::setAxisZ(Q3DAbstractAxis *axis) +{ + setAxisHelper(Q3DAbstractAxis::AxisOrientationZ, axis, &m_axisZ); +} + +Q3DAbstractAxis *Abstract3DController::axisZ() +{ + return m_axisZ; +} + +void Abstract3DController::addAxis(Q3DAbstractAxis *axis) +{ + Q_ASSERT(axis); + Abstract3DController *owner = qobject_cast<Abstract3DController *>(axis->parent()); + if (owner != this) { + Q_ASSERT_X(!owner, "addAxis", "Axis already attached to a graph."); + axis->setParent(this); + } + if (!m_axes.contains(axis)) + m_axes.append(axis); +} + +void Abstract3DController::releaseAxis(Q3DAbstractAxis *axis) +{ + if (axis && m_axes.contains(axis)) { + // Clear the default status from released default axes + if (axis->d_ptr->isDefaultAxis()) + axis->d_ptr->setDefaultAxis(false); + + // If the axis is in use, replace it with a temporary one + switch (axis->orientation()) { + case Q3DAbstractAxis::AxisOrientationX: + setAxisX(0); + break; + case Q3DAbstractAxis::AxisOrientationY: + setAxisY(0); + break; + case Q3DAbstractAxis::AxisOrientationZ: + setAxisZ(0); + break; + default: + break; + } + + m_axes.removeAll(axis); + axis->setParent(0); + } +} + +QList<Q3DAbstractAxis *> Abstract3DController::axes() const +{ + return m_axes; +} + +QAbstractDataProxy *Abstract3DController::activeDataProxy() const +{ + return m_data; +} + +void Abstract3DController::addDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy); + Abstract3DController *owner = qobject_cast<Abstract3DController *>(proxy->parent()); + if (owner != this) { + Q_ASSERT_X(!owner, "addDataProxy", "Proxy already attached to a graph."); + proxy->setParent(this); + } + if (!m_dataProxies.contains(proxy)) + m_dataProxies.append(proxy); +} + +void Abstract3DController::releaseDataProxy(QAbstractDataProxy *proxy) +{ + if (proxy && m_dataProxies.contains(proxy)) { + // Clear the default status from released default proxies + if (proxy->d_ptr->isDefaultProxy()) + proxy->d_ptr->setDefaultProxy(false); + + // If the proxy is in use, replace it with a temporary one + if (m_data == proxy) + setActiveDataProxy(0); + + m_dataProxies.removeAll(proxy); + proxy->setParent(0); + } +} + +QList<QAbstractDataProxy *> Abstract3DController::dataProxies() const +{ + return m_dataProxies; +} + +void Abstract3DController::setActiveDataProxy(QAbstractDataProxy *proxy) +{ + // If existing proxy is the default proxy, delete it + if (m_data) { + if (m_data->d_ptr->isDefaultProxy()) { + m_dataProxies.removeAll(m_data); + delete m_data; + } else { + // Disconnect the old proxy from use + QObject::disconnect(m_data, 0, this, 0); + } + } + + // Assume ownership and activate + addDataProxy(proxy); + m_data = proxy; + m_isDataDirty = true; + emitNeedRender(); +} + +void Abstract3DController::addInputHandler(QAbstract3DInputHandler *inputHandler) +{ + Q_ASSERT(inputHandler); + Abstract3DController *owner = qobject_cast<Abstract3DController *>(inputHandler->parent()); + if (owner != this) { + Q_ASSERT_X(!owner, "addInputHandler", "Input handler already attached to another component."); + inputHandler->setParent(this); + } + + if (!m_inputHandlers.contains(inputHandler)) + m_inputHandlers.append(inputHandler); +} + +void Abstract3DController::releaseInputHandler(QAbstract3DInputHandler *inputHandler) +{ + if (inputHandler && m_inputHandlers.contains(inputHandler)) { + // Clear the default status from released default input handler + if (inputHandler->d_ptr->m_isDefaultHandler) + inputHandler->d_ptr->m_isDefaultHandler = false; + + // If the input handler is in use, remove it + if (m_activeInputHandler == inputHandler) + setActiveInputHandler(0); + + m_inputHandlers.removeAll(inputHandler); + inputHandler->setParent(0); + } +} + +void Abstract3DController::setActiveInputHandler(QAbstract3DInputHandler *inputHandler) +{ + // If existing input handler is the default input handler, delete it + if (m_activeInputHandler) { + if (m_activeInputHandler->d_ptr->m_isDefaultHandler) { + m_inputHandlers.removeAll(m_activeInputHandler); + delete m_activeInputHandler; + } else { + // Disconnect the old input handler from the scene + m_activeInputHandler->setScene(0); + } + } + + // Assume ownership and connect to this controller's scene + addInputHandler(inputHandler); + m_activeInputHandler = inputHandler; + if (m_activeInputHandler) + m_activeInputHandler->setScene(m_scene); +} + +QAbstract3DInputHandler* Abstract3DController::activeInputHandler() +{ + return m_activeInputHandler; +} + +int Abstract3DController::zoomLevel() +{ + return m_scene->camera()->zoomLevel(); +} + +void Abstract3DController::setZoomLevel(int zoomLevel) +{ + m_scene->camera()->setZoomLevel(zoomLevel); + + m_changeTracker.zoomLevelChanged = true; + emitNeedRender(); +} + +void Abstract3DController::setCameraPreset(QDataVis::CameraPreset preset) +{ + m_scene->camera()->setCameraPreset(preset); + emitNeedRender(); +} + +void Abstract3DController::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) +{ + m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); + m_verticalRotation = qBound(0.0f, vertical, 90.0f); + m_scene->camera()->setZoomLevel(qBound(10, distance, 500)); + m_scene->camera()->setRotations(QPointF(m_horizontalRotation, + m_verticalRotation)); + //qDebug() << "camera rotation set to" << m_horizontalRotation << m_verticalRotation; + emitNeedRender(); +} + +void Abstract3DController::setObjectColor(const QColor &baseColor, const QColor &heightColor, + const QColor &depthColor, bool uniform) +{ + m_theme.m_baseColor = baseColor; + m_theme.m_heightColor = heightColor; + m_theme.m_depthColor = depthColor; + m_theme.m_uniformColor = uniform; + + m_changeTracker.themeChanged = true; + emitNeedRender(); +} + +void Abstract3DController::setColorTheme(QDataVis::ColorTheme colorTheme) +{ + m_theme.useColorTheme(colorTheme); + + m_changeTracker.themeChanged = true; + emitNeedRender(); +} + +Theme Abstract3DController::theme() +{ + return m_theme; +} + +void Abstract3DController::setFont(const QFont &font) +{ + m_font = font; + + m_changeTracker.fontChanged = true; + emitNeedRender(); +} + +QFont Abstract3DController::font() +{ + return m_font; +} + +void Abstract3DController::setSelectionMode(QDataVis::SelectionMode mode) +{ + m_selectionMode = mode; + m_changeTracker.selectionModeChanged = true; + emitNeedRender(); +} + +QDataVis::SelectionMode Abstract3DController::selectionMode() +{ + return m_selectionMode; +} + +void Abstract3DController::setShadowQuality(QDataVis::ShadowQuality quality) +{ + m_shadowQuality = quality; + + m_changeTracker.shadowQualityChanged = true; + emit shadowQualityChanged(m_shadowQuality); + emitNeedRender(); +} + +QDataVis::ShadowQuality Abstract3DController::shadowQuality() +{ + return m_shadowQuality; +} + +void Abstract3DController::setLabelTransparency(QDataVis::LabelTransparency transparency) +{ + m_labelTransparency = transparency; + + m_changeTracker.labelTransparencyChanged = true; + emitNeedRender(); +} + +QDataVis::LabelTransparency Abstract3DController::labelTransparency() +{ + return m_labelTransparency; +} + +void Abstract3DController::setBackgroundEnabled(bool enable) +{ + m_isBackgroundEnabled = enable; + m_changeTracker.backgroundEnabledChanged = true; + emitNeedRender(); +} + +bool Abstract3DController::backgroundEnabled() +{ + return m_isBackgroundEnabled; +} + +void Abstract3DController::setGridEnabled(bool enable) +{ + m_isGridEnabled = enable; + m_changeTracker.gridEnabledChanged = true; + emitNeedRender(); +} + +bool Abstract3DController::gridEnabled() +{ + return m_isGridEnabled; +} + +bool Abstract3DController::isSlicingActive() +{ + return m_scene->isSlicingActivated(); +} + +void Abstract3DController::setSlicingActive(bool isSlicing) +{ + m_scene->setSlicingActivated(isSlicing); + emitNeedRender(); +} + +QDataVis::InputState Abstract3DController::inputState() +{ + return m_activeInputHandler->inputState(); +} + +QPoint Abstract3DController::inputPosition() +{ + return m_activeInputHandler->inputPosition(); +} + +void Abstract3DController::setMeshFileName(const QString &fileName) +{ + m_objFile = fileName; + m_changeTracker.objFileChanged = true; + emitNeedRender(); +} + +QString Abstract3DController::meshFileName() +{ + return m_objFile; +} + +Q3DScene *Abstract3DController::scene() +{ + return m_scene; +} + +void Abstract3DController::handleAxisTitleChanged(const QString &title) +{ + Q_UNUSED(title) + handleAxisTitleChangedBySender(sender()); +} + +void Abstract3DController::handleAxisTitleChangedBySender(QObject *sender) +{ + if (sender == m_axisX) + m_changeTracker.axisXTitleChanged = true; + else if (sender == m_axisY) + m_changeTracker.axisYTitleChanged = true; + else if (sender == m_axisZ) + m_changeTracker.axisZTitleChanged = true; + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + emitNeedRender(); +} + +void Abstract3DController::handleAxisLabelsChanged() +{ + handleAxisLabelsChangedBySender(sender()); +} + +void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender) +{ + if (sender == m_axisX) + m_changeTracker.axisXLabelsChanged = true; + else if (sender == m_axisY) + m_changeTracker.axisYLabelsChanged = true; + else if (sender == m_axisZ) + m_changeTracker.axisZLabelsChanged = true; + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + emitNeedRender(); +} + +void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max) +{ + Q_UNUSED(min) + Q_UNUSED(max) + handleAxisRangeChangedBySender(sender()); +} + +void Abstract3DController::handleAxisRangeChangedBySender(QObject *sender) +{ + if (sender == m_axisX) { + m_isDataDirty = true; + m_changeTracker.axisXRangeChanged = true; + } else if (sender == m_axisY) { + m_isDataDirty = true; + m_changeTracker.axisYRangeChanged = true; + } else if (sender == m_axisZ) { + m_isDataDirty = true; + m_changeTracker.axisZRangeChanged = true; + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } + emitNeedRender(); +} + +void Abstract3DController::handleAxisSegmentCountChanged(int count) +{ + Q_UNUSED(count) + handleAxisSegmentCountChangedBySender(sender()); +} + +void Abstract3DController::handleAxisSegmentCountChangedBySender(QObject *sender) +{ + if (sender == m_axisX) + m_changeTracker.axisXSegmentCountChanged = true; + else if (sender == m_axisY) + m_changeTracker.axisYSegmentCountChanged = true; + else if (sender == m_axisZ) + m_changeTracker.axisZSegmentCountChanged = true; + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + emitNeedRender(); +} + +void Abstract3DController::handleAxisSubSegmentCountChanged(int count) +{ + Q_UNUSED(count) + handleAxisSubSegmentCountChangedBySender(sender()); +} + +void Abstract3DController::handleAxisSubSegmentCountChangedBySender(QObject *sender) +{ + if (sender == m_axisX) + m_changeTracker.axisXSubSegmentCountChanged = true; + else if (sender == m_axisY) + m_changeTracker.axisYSubSegmentCountChanged = true; + else if (sender == m_axisZ) + m_changeTracker.axisZSubSegmentCountChanged = true; + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + emitNeedRender(); +} + +void Abstract3DController::handleAxisAutoAdjustRangeChanged(bool autoAdjust) +{ + QObject *sender = QObject::sender(); + if (sender != m_axisX && sender != m_axisY && sender != m_axisZ) + return; + + Q3DAbstractAxis *axis = static_cast<Q3DAbstractAxis*>(sender); + handleAxisAutoAdjustRangeChangedInOrientation(axis->orientation(), autoAdjust); +} + +void Abstract3DController::handleAxisLabelFormatChanged(const QString &format) +{ + Q_UNUSED(format) + handleAxisLabelFormatChangedBySender(sender()); +} + +void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender) +{ + // Label format changing needs to dirty the data so that labels are reset. + if (sender == m_axisX) { + m_isDataDirty = true; + m_changeTracker.axisXLabelFormatChanged = true; + } else if (sender == m_axisY) { + m_isDataDirty = true; + m_changeTracker.axisYLabelFormatChanged = true; + } else if (sender == m_axisZ) { + m_isDataDirty = true; + m_changeTracker.axisZLabelFormatChanged = true; + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } + emitNeedRender(); +} + +void Abstract3DController::setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, + Q3DAbstractAxis *axis, Q3DAbstractAxis **axisPtr) +{ + // Setting null axis indicates using default axis + if (!axis) + axis = createDefaultAxis(orientation); + + // If old axis is default axis, delete it + Q3DAbstractAxis *oldAxis = *axisPtr; + if (oldAxis) { + if (oldAxis->d_ptr->isDefaultAxis()) { + m_axes.removeAll(oldAxis); + delete oldAxis; + oldAxis = 0; + } else { + // Disconnect the old axis from use + QObject::disconnect(oldAxis, 0, this, 0); + oldAxis->d_ptr->setOrientation(Q3DAbstractAxis::AxisOrientationNone); + } + } + + // Assume ownership + addAxis(axis); + + // Connect the new axis + *axisPtr = axis; + + axis->d_ptr->setOrientation(orientation); + + QObject::connect(axis, &Q3DAbstractAxis::titleChanged, + this, &Abstract3DController::handleAxisTitleChanged); + QObject::connect(axis, &Q3DAbstractAxis::labelsChanged, + this, &Abstract3DController::handleAxisLabelsChanged); + + if (orientation == Q3DAbstractAxis::AxisOrientationX) + m_changeTracker.axisXTypeChanged = true; + else if (orientation == Q3DAbstractAxis::AxisOrientationY) + m_changeTracker.axisYTypeChanged = true; + else if (orientation == Q3DAbstractAxis::AxisOrientationZ) + m_changeTracker.axisZTypeChanged = true; + + handleAxisTitleChangedBySender(axis); + handleAxisLabelsChangedBySender(axis); + + if (axis->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(axis); + QObject::connect(valueAxis, &Q3DValueAxis::rangeChanged, + this, &Abstract3DController::handleAxisRangeChanged); + QObject::connect(valueAxis, &Q3DValueAxis::segmentCountChanged, + this, &Abstract3DController::handleAxisSegmentCountChanged); + QObject::connect(valueAxis, &Q3DValueAxis::subSegmentCountChanged, + this, &Abstract3DController::handleAxisSubSegmentCountChanged); + QObject::connect(valueAxis, &Q3DValueAxis::autoAdjustRangeChanged, + this, &Abstract3DController::handleAxisAutoAdjustRangeChanged); + QObject::connect(valueAxis, &Q3DValueAxis::labelFormatChanged, + this, &Abstract3DController::handleAxisLabelFormatChanged); + + handleAxisRangeChangedBySender(valueAxis); + handleAxisSegmentCountChangedBySender(valueAxis); + handleAxisSubSegmentCountChangedBySender(valueAxis); + handleAxisAutoAdjustRangeChangedInOrientation(valueAxis->orientation(), + valueAxis->isAutoAdjustRange()); + handleAxisLabelFormatChangedBySender(valueAxis); + } +} + +Q3DAbstractAxis *Abstract3DController::createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation) +{ + Q_UNUSED(orientation) + + // The default default axis is a value axis. If the chart type has a different default axis + // for some orientation, this function needs to be overridden. + Q3DAbstractAxis *defaultAxis = createDefaultValueAxis(); + return defaultAxis; +} + +Q3DValueAxis *Abstract3DController::createDefaultValueAxis() +{ + // Default value axis has single segment, empty label format, and auto scaling + // TODO: Grid should be also hidden, but that is not currently controlled by axis + Q3DValueAxis *defaultAxis = new Q3DValueAxis; + defaultAxis->setSegmentCount(1); + defaultAxis->setSubSegmentCount(1); + defaultAxis->setAutoAdjustRange(true); + defaultAxis->setLabelFormat(QString()); + defaultAxis->d_ptr->setDefaultAxis(true); + + return defaultAxis; +} + +Q3DCategoryAxis *Abstract3DController::createDefaultCategoryAxis() +{ + // Default category axis has no labels + // TODO: Grid should be also hidden, but that is not currently controlled by axis. + Q3DCategoryAxis *defaultAxis = new Q3DCategoryAxis; + defaultAxis->d_ptr->setDefaultAxis(true); + return defaultAxis; +} + +void Abstract3DController::emitNeedRender() +{ + if (!m_renderPending) { + emit needRender(); + m_renderPending = true; + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE |