diff --git a/src/graphs3d/CMakeLists.txt b/src/graphs3d/CMakeLists.txt index ed8177c9..c9a8c16b 100644 --- a/src/graphs3d/CMakeLists.txt +++ b/src/graphs3d/CMakeLists.txt @@ -93,8 +93,6 @@ else() data/qsurfacedataproxy.cpp data/qsurfacedataproxy.h data/qsurfacedataproxy_p.h data/surfaceitemmodelhandler.cpp data/surfaceitemmodelhandler_p.h - engine/surfaceselectioninstancing.cpp engine/surfaceselectioninstancing_p.h - qml/foreigntypessurface_p.h qml/qquickgraphssurface.cpp qml/qquickgraphssurface_p.h qml/qquickgraphssurfaceseries.cpp qml/qquickgraphssurfaceseries_p.h diff --git a/src/graphs3d/data/qabstract3dseries.cpp b/src/graphs3d/data/qabstract3dseries.cpp index 326d9144..c9103fb3 100644 --- a/src/graphs3d/data/qabstract3dseries.cpp +++ b/src/graphs3d/data/qabstract3dseries.cpp @@ -790,9 +790,9 @@ void QAbstract3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy) void QAbstract3DSeriesPrivate::setGraph(QQuickGraphsItem *graph) { Q_Q(QAbstract3DSeries); - connectGraphAndProxy(graph); m_graph = graph; q->setParent(graph); + connectGraphAndProxy(graph); markItemLabelDirty(); } diff --git a/src/graphs3d/engine/surfaceselectioninstancing.cpp b/src/graphs3d/engine/surfaceselectioninstancing.cpp deleted file mode 100644 index 51b05a88..00000000 --- a/src/graphs3d/engine/surfaceselectioninstancing.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -#include "surfaceselectioninstancing_p.h" - -SurfaceSelectionInstancing::SurfaceSelectionInstancing() {} - -SurfaceSelectionInstancing::~SurfaceSelectionInstancing() {} - -void SurfaceSelectionInstancing::addPosition(QVector3D position) -{ - m_positions.append(position); - markDirty(); - m_dirty = true; -} - -void SurfaceSelectionInstancing::resetPositions() -{ - m_positions.clear(); - markDirty(); - m_dirty = true; -} - -QByteArray SurfaceSelectionInstancing::getInstanceBuffer(int *instanceCount) -{ - if (m_dirty) { - m_instanceData.resize(0); - int instanceNumber = 0; - - for (auto position : m_positions) { - auto entry = calculateTableEntry(position, m_scale, m_rotation, m_color); - m_instanceData.append(reinterpret_cast(&entry), sizeof(entry)); - instanceNumber++; - } - m_instanceCount = instanceNumber; - m_dirty = false; - } - - if (instanceCount) - *instanceCount = m_instanceCount; - - return m_instanceData; -} diff --git a/src/graphs3d/engine/surfaceselectioninstancing_p.h b/src/graphs3d/engine/surfaceselectioninstancing_p.h deleted file mode 100644 index 3bc92044..00000000 --- a/src/graphs3d/engine/surfaceselectioninstancing_p.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only - -// -// W A R N I N G -// ------------- -// -// This file is not part of the QtGraphs API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#ifndef SURFACESELECTIONINSTANCING_H -#define SURFACESELECTIONINSTANCING_H - -#include - -QT_BEGIN_NAMESPACE - -class SurfaceSelectionInstancing : public QQuick3DInstancing -{ - Q_OBJECT - -public: - SurfaceSelectionInstancing(); - ~SurfaceSelectionInstancing(); - - void setRotation(QVector3D rotation) { m_rotation = rotation; } - void setScale(QVector3D scale) { m_scale = scale; } - void addPosition(QVector3D position); - void resetPositions(); - void setColor(QColor color) { m_color = color; } - -protected: - QByteArray getInstanceBuffer(int *instanceCount) override; - -private: - QByteArray m_instanceData; - int m_instanceCount = 0; - QVector3D m_rotation = {.0f, .0f, .0f}; - QVector3D m_scale = {.0f, .0f, .0f}; - QList m_positions; - QColor m_color = {0, 0, 0}; - bool m_dirty = true; -}; - -QT_END_NAMESPACE - -#endif // SURFACESELECTIONINSTANCING_H diff --git a/src/graphs3d/qml/qquickgraphssurface.cpp b/src/graphs3d/qml/qquickgraphssurface.cpp index a5c4ed39..e2365c78 100644 --- a/src/graphs3d/qml/qquickgraphssurface.cpp +++ b/src/graphs3d/qml/qquickgraphssurface.cpp @@ -13,7 +13,6 @@ #include "qsurface3dseries_p.h" #include "qsurfacedataproxy_p.h" #include "qvalue3daxis_p.h" -#include "surfaceselectioninstancing_p.h" #include #include @@ -164,8 +163,6 @@ QQuickGraphsSurface::~QQuickGraphsSurface() const QMutexLocker locker2(mutex()); for (const auto &model : std::as_const(m_model)) delete model; - delete m_instancing; - delete m_sliceInstancing; } void QQuickGraphsSurface::setAxisX(QValue3DAxis *axis) @@ -225,6 +222,139 @@ void QQuickGraphsSurface::handleWireframeColorChanged() } } +void QQuickGraphsSurface::handleMeshTypeChanged(QAbstract3DSeries::Mesh mesh) +{ + QSurface3DSeries *sender = qobject_cast(QObject::sender()); + changePointerMeshTypeForSeries(mesh, sender); + if (sliceView()) + changeSlicePointerMeshTypeForSeries(mesh, sender); +} + +void QQuickGraphsSurface::changePointerMeshTypeForSeries(QAbstract3DSeries::Mesh mesh, + QSurface3DSeries *series) +{ + changePointerForSeries(getMeshFileName(mesh, series), series); +} + +void QQuickGraphsSurface::changeSlicePointerMeshTypeForSeries(QAbstract3DSeries::Mesh mesh, + QSurface3DSeries *series) +{ + changeSlicePointerForSeries(getMeshFileName(mesh, series), series); +} + +QString QQuickGraphsSurface::getMeshFileName(QAbstract3DSeries::Mesh mesh, + QSurface3DSeries *series) const +{ + QString fileName = {}; + switch (mesh) { + case QAbstract3DSeries::Mesh::Sphere: + fileName = QStringLiteral("defaultMeshes/sphereMesh"); + break; + case QAbstract3DSeries::Mesh::Bar: + case QAbstract3DSeries::Mesh::Cube: + fileName = QStringLiteral("defaultMeshes/barMesh"); + break; + case QAbstract3DSeries::Mesh::Pyramid: + fileName = QStringLiteral("defaultMeshes/pyramidMesh"); + break; + case QAbstract3DSeries::Mesh::Cone: + fileName = QStringLiteral("defaultMeshes/coneMesh"); + break; + case QAbstract3DSeries::Mesh::Cylinder: + fileName = QStringLiteral("defaultMeshes/cylinderMesh"); + break; + case QAbstract3DSeries::Mesh::BevelBar: + case QAbstract3DSeries::Mesh::BevelCube: + fileName = QStringLiteral("defaultMeshes/bevelBarMesh"); + break; + case QAbstract3DSeries::Mesh::UserDefined: + fileName = series->userDefinedMesh(); + break; + default: + fileName = QStringLiteral("defaultMeshes/sphereMesh"); + } + return fileName; +} + +void QQuickGraphsSurface::handlePointerChanged(const QString &filename) +{ + QSurface3DSeries *sender = qobject_cast(QObject::sender()); + changePointerForSeries(filename, sender); + changeSlicePointerForSeries(filename, sender); +} + +void QQuickGraphsSurface::changePointerForSeries(const QString &filename, QSurface3DSeries *series) +{ + if (!filename.isEmpty()) { + // Selection pointer + QQuick3DNode *parent = rootNode(); + + QQuick3DPrincipledMaterial *pointerMaterial = nullptr; + QQuick3DModel *pointer = m_selectionPointers.value(series); + + if (pointer) { + // Retrieve the already created material + QQmlListReference materialRef(pointer, "materials"); + pointerMaterial = qobject_cast(materialRef.at(0)); + // Delete old model + delete pointer; + } else { + // No pointer yet; create material for it + pointerMaterial = new QQuick3DPrincipledMaterial(); + pointerMaterial->setParent(this); + pointerMaterial->setBaseColor(theme()->singleHighlightColor()); + } + // Create new pointer + pointer = new QQuick3DModel(); + pointer->setParent(parent); + pointer->setParentItem(parent); + pointer->setSource(QUrl(filename)); + pointer->setScale(QVector3D(0.05f, 0.05f, 0.05f)); + // Insert to the map + m_selectionPointers.insert(series, pointer); + // Set material + QQmlListReference materialRef(pointer, "materials"); + materialRef.append(pointerMaterial); + } +} + +void QQuickGraphsSurface::changeSlicePointerForSeries(const QString &filename, + QSurface3DSeries *series) +{ + if (!filename.isEmpty()) { + // Slice selection pointer + QQuick3DNode *sliceParent = sliceView()->scene(); + + QQuick3DPrincipledMaterial *slicePointerMaterial = nullptr; + QQuick3DModel *slicePointer = m_sliceSelectionPointers.value(series); + + if (slicePointer) { + // Retrieve the already created material + QQmlListReference sliceMaterialRef(slicePointer, "materials"); + slicePointerMaterial = qobject_cast( + sliceMaterialRef.at(0)); + // Delete old model + delete slicePointer; + } else { + // No pointer yet; create material for it + slicePointerMaterial = new QQuick3DPrincipledMaterial(); + slicePointerMaterial->setParent(sliceParent); + slicePointerMaterial->setBaseColor(theme()->singleHighlightColor()); + } + // Create new pointer + slicePointer = new QQuick3DModel(); + slicePointer->setParent(sliceParent); + slicePointer->setParentItem(sliceParent); + slicePointer->setSource(QUrl(filename)); + slicePointer->setScale(QVector3D(0.05f, 0.05f, 0.05f)); + // Insert to the map + m_sliceSelectionPointers.insert(series, slicePointer); + // Set material + QQmlListReference sliceMaterialRef(slicePointer, "materials"); + sliceMaterialRef.append(slicePointerMaterial); + } +} + void QQuickGraphsSurface::handleFlipHorizontalGridChanged(bool flip) { float factor = -1.0f; @@ -827,23 +957,10 @@ void QQuickGraphsSurface::componentComplete() { QQuickGraphsItem::componentComplete(); - for (auto series : surfaceSeriesList()) + for (auto series : surfaceSeriesList()) { addModel(series); - - QQuick3DNode *parent = rootNode(); - - m_selectionPointer = new QQuick3DModel(); - m_selectionPointer->setParent(parent); - m_selectionPointer->setParentItem(parent); - m_selectionPointer->setSource(QUrl(QStringLiteral("#Sphere"))); - auto pointerMaterial = new QQuick3DPrincipledMaterial(); - pointerMaterial->setParent(this); - pointerMaterial->setBaseColor(theme()->singleHighlightColor()); - QQmlListReference materialRef(m_selectionPointer, "materials"); - materialRef.append(pointerMaterial); - m_instancing = new SurfaceSelectionInstancing(); - m_instancing->setScale(QVector3D(0.001f, 0.001f, 0.001f)); - m_selectionPointer->setInstancing(m_instancing); + changePointerMeshTypeForSeries(series->mesh(), series); + } graphsInputHandler()->setGraphsItem(this); } @@ -2010,9 +2127,17 @@ bool QQuickGraphsSurface::doPicking(QPointF position) void QQuickGraphsSurface::updateSelectedPoint() { bool labelVisible = false; - m_instancing->resetPositions(); - if (sliceView() && sliceView()->isVisible()) - m_sliceInstancing->resetPositions(); + + auto list = surfaceSeriesList(); + for (auto series : list) { + // If the pointer and its instancing do not exist yet (as will happen in widget case), + // we must create them + if (!m_selectionPointers.value(series)) + changePointerMeshTypeForSeries(series->mesh(), series); + m_selectionPointers.value(series)->setVisible(false); + if (sliceView() && sliceView()->isVisible()) + m_sliceSelectionPointers.value(series)->setVisible(false); + } QPointF worldCoord; for (auto model : m_model) { @@ -2043,13 +2168,15 @@ void QQuickGraphsSurface::updateSelectedPoint() selectedVertex.coord = model->selectedVertex.coord; if (model->series->isVisible() && !selectedVertex.position.isNull() && selectionMode().testFlag(QtGraphs3D::SelectionFlag::Item)) { - m_instancing->addPosition(selectedVertex.position); + m_selectionPointers.value(model->series)->setPosition(selectedVertex.position); + m_selectionPointers.value(model->series)->setVisible(true); QVector3D slicePosition = getNormalizedVertex(dataPos, false, false); if (sliceView() && sliceView()->isVisible()) { if (selectionMode().testFlag(QtGraphs3D::SelectionFlag::Column)) slicePosition.setX(-slicePosition.z()); slicePosition.setZ(.0f); - m_sliceInstancing->addPosition(slicePosition); + m_sliceSelectionPointers.value(model->series)->setPosition(slicePosition); + m_sliceSelectionPointers.value(model->series)->setVisible(true); } if (model->picked) { QVector3D labelPosition = selectedVertex.position; @@ -2170,7 +2297,14 @@ void QQuickGraphsSurface::addModel(QSurface3DSeries *series) &QSurface3DSeries::wireframeColorChanged, this, &QQuickGraphsSurface::handleWireframeColorChanged); - + connect(series, + &QSurface3DSeries::userDefinedMeshChanged, + this, + &QQuickGraphsSurface::handlePointerChanged); + connect(series, + &QSurface3DSeries::meshChanged, + this, + &QQuickGraphsSurface::handleMeshTypeChanged); if (sliceView()) addSliceModel(surfaceModel); } @@ -2180,24 +2314,10 @@ void QQuickGraphsSurface::createSliceView() setSliceOrthoProjection(true); QQuickGraphsItem::createSliceView(); - for (auto surfaceModel : m_model) + for (auto surfaceModel : m_model) { addSliceModel(surfaceModel); - - QQuick3DViewport *sliceParent = sliceView(); - - m_sliceSelectionPointer = new QQuick3DModel(); - m_sliceSelectionPointer->setParent(sliceParent->scene()); - m_sliceSelectionPointer->setParentItem(sliceParent->scene()); - m_sliceSelectionPointer->setSource(QUrl(QStringLiteral("#Sphere"))); - QQuick3DPrincipledMaterial *pointerMaterial = new QQuick3DPrincipledMaterial(); - pointerMaterial->setParent(m_sliceSelectionPointer); - pointerMaterial->setBaseColor(theme()->singleHighlightColor()); - QQmlListReference sliceMaterialRef(m_sliceSelectionPointer, "materials"); - sliceMaterialRef.append(pointerMaterial); - m_sliceInstancing = new SurfaceSelectionInstancing(); - m_sliceInstancing->setScale(QVector3D(0.001f, 0.001f, 0.001f)); - m_sliceSelectionPointer->setInstancing(m_sliceInstancing); - m_sliceInstancing->setColor(theme()->singleHighlightColor()); + changeSlicePointerMeshTypeForSeries(surfaceModel->series->mesh(), surfaceModel->series); + } } void QQuickGraphsSurface::updateSliceItemLabel(const QString &label, QVector3D position) @@ -2305,9 +2425,18 @@ void QQuickGraphsSurface::addSliceModel(SurfaceModel *model) void QQuickGraphsSurface::updateSingleHighlightColor() { - m_instancing->setColor(theme()->singleHighlightColor()); - if (sliceView()) - m_sliceInstancing->setColor(theme()->singleHighlightColor()); + auto list = surfaceSeriesList(); + for (auto series : list) { + QQmlListReference pMaterialRef(m_selectionPointers.value(series), "materials"); + auto pmat = qobject_cast(pMaterialRef.at(0)); + if (pmat) + pmat->setBaseColor(theme()->singleHighlightColor()); + if (sliceView()) { + QQmlListReference spMaterialRef(m_sliceSelectionPointers.value(series), "materials"); + auto spmat = qobject_cast(spMaterialRef.at(0)); + spmat->setBaseColor(theme()->singleHighlightColor()); + } + } } void QQuickGraphsSurface::updateLightStrength() diff --git a/src/graphs3d/qml/qquickgraphssurface_p.h b/src/graphs3d/qml/qquickgraphssurface_p.h index 36600347..f4716440 100644 --- a/src/graphs3d/qml/qquickgraphssurface_p.h +++ b/src/graphs3d/qml/qquickgraphssurface_p.h @@ -24,7 +24,6 @@ QT_BEGIN_NAMESPACE class QValue3DAxis; class QSurface3DSeries; class QQuickGraphsSurface; -class SurfaceSelectionInstancing; struct Surface3DChangeBitField { @@ -233,11 +232,17 @@ private: void addModel(QSurface3DSeries *series); void addSliceModel(SurfaceModel *model); + void handleMeshTypeChanged(QAbstract3DSeries::Mesh mesh); + void handlePointerChanged(const QString &filename); + void changePointerMeshTypeForSeries(QAbstract3DSeries::Mesh mesh, QSurface3DSeries *series); + void changePointerForSeries(const QString &filename, QSurface3DSeries *series); + void changeSlicePointerMeshTypeForSeries(QAbstract3DSeries::Mesh mesh, QSurface3DSeries *series); + void changeSlicePointerForSeries(const QString &filename, QSurface3DSeries *series); + QString getMeshFileName(QAbstract3DSeries::Mesh mesh, QSurface3DSeries *series) const; + QVector m_model; - QQuick3DModel *m_selectionPointer = nullptr; - SurfaceSelectionInstancing *m_instancing = nullptr; - QQuick3DModel *m_sliceSelectionPointer = nullptr; - SurfaceSelectionInstancing *m_sliceInstancing = nullptr; + QMap m_selectionPointers = {}; + QMap m_sliceSelectionPointers = {}; bool m_isIndexDirty = true; bool m_selectionDirty = false; diff --git a/tests/manual/surfacetest/graphmodifier.cpp b/tests/manual/surfacetest/graphmodifier.cpp index 0e6c6c51..4150af8d 100644 --- a/tests/manual/surfacetest/graphmodifier.cpp +++ b/tests/manual/surfacetest/graphmodifier.cpp @@ -1681,44 +1681,44 @@ void GraphModifier::changeMesh() static int model = 0; switch (model) { case 0: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Cylinder); - m_graph->seriesList().at(0)->setMeshSmooth(false); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Cylinder); + m_graph->selectedSeries()->setMeshSmooth(false); break; case 1: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Cylinder); - m_graph->seriesList().at(0)->setMeshSmooth(true); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Cylinder); + m_graph->selectedSeries()->setMeshSmooth(true); break; case 2: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Cone); - m_graph->seriesList().at(0)->setMeshSmooth(false); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Cone); + m_graph->selectedSeries()->setMeshSmooth(false); break; case 3: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Cone); - m_graph->seriesList().at(0)->setMeshSmooth(true); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Cone); + m_graph->selectedSeries()->setMeshSmooth(true); break; case 4: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Bar); - m_graph->seriesList().at(0)->setMeshSmooth(false); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Bar); + m_graph->selectedSeries()->setMeshSmooth(false); break; case 5: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Bar); - m_graph->seriesList().at(0)->setMeshSmooth(true); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Bar); + m_graph->selectedSeries()->setMeshSmooth(true); break; case 6: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Pyramid); - m_graph->seriesList().at(0)->setMeshSmooth(false); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Pyramid); + m_graph->selectedSeries()->setMeshSmooth(false); break; case 7: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Pyramid); - m_graph->seriesList().at(0)->setMeshSmooth(true); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Pyramid); + m_graph->selectedSeries()->setMeshSmooth(true); break; case 8: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::BevelBar); - m_graph->seriesList().at(0)->setMeshSmooth(false); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::BevelBar); + m_graph->selectedSeries()->setMeshSmooth(false); break; case 9: - m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::BevelBar); - m_graph->seriesList().at(0)->setMeshSmooth(true); + m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::BevelBar); + m_graph->selectedSeries()->setMeshSmooth(true); break; } model++;