React to userDefinedMesh and mesh change in Surface3D

Pick-to: 6.8.1
Fixes: QTBUG-130010
Fixes: QTBUG-130011
Fixes: QTBUG-130870
Change-Id: I3516b1af5a1af65ad0060c775143e73af8732167
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
(cherry picked from commit 1728887e0a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tomi Korpipaa 2024-10-25 10:33:18 +03:00 committed by Qt Cherry-pick Bot
parent abde6365ec
commit b4922fc50b
7 changed files with 205 additions and 166 deletions

View File

@ -93,8 +93,6 @@ else()
data/qsurfacedataproxy.cpp data/qsurfacedataproxy.h data/qsurfacedataproxy_p.h data/qsurfacedataproxy.cpp data/qsurfacedataproxy.h data/qsurfacedataproxy_p.h
data/surfaceitemmodelhandler.cpp data/surfaceitemmodelhandler_p.h data/surfaceitemmodelhandler.cpp data/surfaceitemmodelhandler_p.h
engine/surfaceselectioninstancing.cpp engine/surfaceselectioninstancing_p.h
qml/foreigntypessurface_p.h qml/foreigntypessurface_p.h
qml/qquickgraphssurface.cpp qml/qquickgraphssurface_p.h qml/qquickgraphssurface.cpp qml/qquickgraphssurface_p.h
qml/qquickgraphssurfaceseries.cpp qml/qquickgraphssurfaceseries_p.h qml/qquickgraphssurfaceseries.cpp qml/qquickgraphssurfaceseries_p.h

View File

@ -790,9 +790,9 @@ void QAbstract3DSeriesPrivate::setDataProxy(QAbstractDataProxy *proxy)
void QAbstract3DSeriesPrivate::setGraph(QQuickGraphsItem *graph) void QAbstract3DSeriesPrivate::setGraph(QQuickGraphsItem *graph)
{ {
Q_Q(QAbstract3DSeries); Q_Q(QAbstract3DSeries);
connectGraphAndProxy(graph);
m_graph = graph; m_graph = graph;
q->setParent(graph); q->setParent(graph);
connectGraphAndProxy(graph);
markItemLabelDirty(); markItemLabelDirty();
} }

View File

@ -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<const char *>(&entry), sizeof(entry));
instanceNumber++;
}
m_instanceCount = instanceNumber;
m_dirty = false;
}
if (instanceCount)
*instanceCount = m_instanceCount;
return m_instanceData;
}

View File

@ -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 <QtQuick3D/private/qquick3dinstancing_p.h>
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<QVector3D> m_positions;
QColor m_color = {0, 0, 0};
bool m_dirty = true;
};
QT_END_NAMESPACE
#endif // SURFACESELECTIONINSTANCING_H

View File

@ -13,7 +13,6 @@
#include "qsurface3dseries_p.h" #include "qsurface3dseries_p.h"
#include "qsurfacedataproxy_p.h" #include "qsurfacedataproxy_p.h"
#include "qvalue3daxis_p.h" #include "qvalue3daxis_p.h"
#include "surfaceselectioninstancing_p.h"
#include <QtQuick3D/private/qquick3dcustommaterial_p.h> #include <QtQuick3D/private/qquick3dcustommaterial_p.h>
#include <QtQuick3D/private/qquick3ddefaultmaterial_p.h> #include <QtQuick3D/private/qquick3ddefaultmaterial_p.h>
@ -164,8 +163,6 @@ QQuickGraphsSurface::~QQuickGraphsSurface()
const QMutexLocker locker2(mutex()); const QMutexLocker locker2(mutex());
for (const auto &model : std::as_const(m_model)) for (const auto &model : std::as_const(m_model))
delete model; delete model;
delete m_instancing;
delete m_sliceInstancing;
} }
void QQuickGraphsSurface::setAxisX(QValue3DAxis *axis) void QQuickGraphsSurface::setAxisX(QValue3DAxis *axis)
@ -225,6 +222,139 @@ void QQuickGraphsSurface::handleWireframeColorChanged()
} }
} }
void QQuickGraphsSurface::handleMeshTypeChanged(QAbstract3DSeries::Mesh mesh)
{
QSurface3DSeries *sender = qobject_cast<QSurface3DSeries *>(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<QSurface3DSeries *>(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<QQuick3DPrincipledMaterial *>(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<QQuick3DPrincipledMaterial *>(
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) void QQuickGraphsSurface::handleFlipHorizontalGridChanged(bool flip)
{ {
float factor = -1.0f; float factor = -1.0f;
@ -827,23 +957,10 @@ void QQuickGraphsSurface::componentComplete()
{ {
QQuickGraphsItem::componentComplete(); QQuickGraphsItem::componentComplete();
for (auto series : surfaceSeriesList()) for (auto series : surfaceSeriesList()) {
addModel(series); addModel(series);
changePointerMeshTypeForSeries(series->mesh(), 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);
graphsInputHandler()->setGraphsItem(this); graphsInputHandler()->setGraphsItem(this);
} }
@ -2010,9 +2127,17 @@ bool QQuickGraphsSurface::doPicking(QPointF position)
void QQuickGraphsSurface::updateSelectedPoint() void QQuickGraphsSurface::updateSelectedPoint()
{ {
bool labelVisible = false; bool labelVisible = false;
m_instancing->resetPositions();
if (sliceView() && sliceView()->isVisible()) auto list = surfaceSeriesList();
m_sliceInstancing->resetPositions(); 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; QPointF worldCoord;
for (auto model : m_model) { for (auto model : m_model) {
@ -2043,13 +2168,15 @@ void QQuickGraphsSurface::updateSelectedPoint()
selectedVertex.coord = model->selectedVertex.coord; selectedVertex.coord = model->selectedVertex.coord;
if (model->series->isVisible() && !selectedVertex.position.isNull() if (model->series->isVisible() && !selectedVertex.position.isNull()
&& selectionMode().testFlag(QtGraphs3D::SelectionFlag::Item)) { && 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); QVector3D slicePosition = getNormalizedVertex(dataPos, false, false);
if (sliceView() && sliceView()->isVisible()) { if (sliceView() && sliceView()->isVisible()) {
if (selectionMode().testFlag(QtGraphs3D::SelectionFlag::Column)) if (selectionMode().testFlag(QtGraphs3D::SelectionFlag::Column))
slicePosition.setX(-slicePosition.z()); slicePosition.setX(-slicePosition.z());
slicePosition.setZ(.0f); slicePosition.setZ(.0f);
m_sliceInstancing->addPosition(slicePosition); m_sliceSelectionPointers.value(model->series)->setPosition(slicePosition);
m_sliceSelectionPointers.value(model->series)->setVisible(true);
} }
if (model->picked) { if (model->picked) {
QVector3D labelPosition = selectedVertex.position; QVector3D labelPosition = selectedVertex.position;
@ -2170,7 +2297,14 @@ void QQuickGraphsSurface::addModel(QSurface3DSeries *series)
&QSurface3DSeries::wireframeColorChanged, &QSurface3DSeries::wireframeColorChanged,
this, this,
&QQuickGraphsSurface::handleWireframeColorChanged); &QQuickGraphsSurface::handleWireframeColorChanged);
connect(series,
&QSurface3DSeries::userDefinedMeshChanged,
this,
&QQuickGraphsSurface::handlePointerChanged);
connect(series,
&QSurface3DSeries::meshChanged,
this,
&QQuickGraphsSurface::handleMeshTypeChanged);
if (sliceView()) if (sliceView())
addSliceModel(surfaceModel); addSliceModel(surfaceModel);
} }
@ -2180,24 +2314,10 @@ void QQuickGraphsSurface::createSliceView()
setSliceOrthoProjection(true); setSliceOrthoProjection(true);
QQuickGraphsItem::createSliceView(); QQuickGraphsItem::createSliceView();
for (auto surfaceModel : m_model) for (auto surfaceModel : m_model) {
addSliceModel(surfaceModel); addSliceModel(surfaceModel);
changeSlicePointerMeshTypeForSeries(surfaceModel->series->mesh(), surfaceModel->series);
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());
} }
void QQuickGraphsSurface::updateSliceItemLabel(const QString &label, QVector3D position) void QQuickGraphsSurface::updateSliceItemLabel(const QString &label, QVector3D position)
@ -2305,9 +2425,18 @@ void QQuickGraphsSurface::addSliceModel(SurfaceModel *model)
void QQuickGraphsSurface::updateSingleHighlightColor() void QQuickGraphsSurface::updateSingleHighlightColor()
{ {
m_instancing->setColor(theme()->singleHighlightColor()); auto list = surfaceSeriesList();
if (sliceView()) for (auto series : list) {
m_sliceInstancing->setColor(theme()->singleHighlightColor()); QQmlListReference pMaterialRef(m_selectionPointers.value(series), "materials");
auto pmat = qobject_cast<QQuick3DPrincipledMaterial *>(pMaterialRef.at(0));
if (pmat)
pmat->setBaseColor(theme()->singleHighlightColor());
if (sliceView()) {
QQmlListReference spMaterialRef(m_sliceSelectionPointers.value(series), "materials");
auto spmat = qobject_cast<QQuick3DPrincipledMaterial *>(spMaterialRef.at(0));
spmat->setBaseColor(theme()->singleHighlightColor());
}
}
} }
void QQuickGraphsSurface::updateLightStrength() void QQuickGraphsSurface::updateLightStrength()

View File

@ -24,7 +24,6 @@ QT_BEGIN_NAMESPACE
class QValue3DAxis; class QValue3DAxis;
class QSurface3DSeries; class QSurface3DSeries;
class QQuickGraphsSurface; class QQuickGraphsSurface;
class SurfaceSelectionInstancing;
struct Surface3DChangeBitField struct Surface3DChangeBitField
{ {
@ -233,11 +232,17 @@ private:
void addModel(QSurface3DSeries *series); void addModel(QSurface3DSeries *series);
void addSliceModel(SurfaceModel *model); 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<SurfaceModel *> m_model; QVector<SurfaceModel *> m_model;
QQuick3DModel *m_selectionPointer = nullptr; QMap<QSurface3DSeries *, QQuick3DModel *> m_selectionPointers = {};
SurfaceSelectionInstancing *m_instancing = nullptr; QMap<QSurface3DSeries *, QQuick3DModel *> m_sliceSelectionPointers = {};
QQuick3DModel *m_sliceSelectionPointer = nullptr;
SurfaceSelectionInstancing *m_sliceInstancing = nullptr;
bool m_isIndexDirty = true; bool m_isIndexDirty = true;
bool m_selectionDirty = false; bool m_selectionDirty = false;

View File

@ -1681,44 +1681,44 @@ void GraphModifier::changeMesh()
static int model = 0; static int model = 0;
switch (model) { switch (model) {
case 0: case 0:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Cylinder); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Cylinder);
m_graph->seriesList().at(0)->setMeshSmooth(false); m_graph->selectedSeries()->setMeshSmooth(false);
break; break;
case 1: case 1:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Cylinder); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Cylinder);
m_graph->seriesList().at(0)->setMeshSmooth(true); m_graph->selectedSeries()->setMeshSmooth(true);
break; break;
case 2: case 2:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Cone); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Cone);
m_graph->seriesList().at(0)->setMeshSmooth(false); m_graph->selectedSeries()->setMeshSmooth(false);
break; break;
case 3: case 3:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Cone); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Cone);
m_graph->seriesList().at(0)->setMeshSmooth(true); m_graph->selectedSeries()->setMeshSmooth(true);
break; break;
case 4: case 4:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Bar); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Bar);
m_graph->seriesList().at(0)->setMeshSmooth(false); m_graph->selectedSeries()->setMeshSmooth(false);
break; break;
case 5: case 5:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Bar); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Bar);
m_graph->seriesList().at(0)->setMeshSmooth(true); m_graph->selectedSeries()->setMeshSmooth(true);
break; break;
case 6: case 6:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Pyramid); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Pyramid);
m_graph->seriesList().at(0)->setMeshSmooth(false); m_graph->selectedSeries()->setMeshSmooth(false);
break; break;
case 7: case 7:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::Pyramid); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::Pyramid);
m_graph->seriesList().at(0)->setMeshSmooth(true); m_graph->selectedSeries()->setMeshSmooth(true);
break; break;
case 8: case 8:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::BevelBar); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::BevelBar);
m_graph->seriesList().at(0)->setMeshSmooth(false); m_graph->selectedSeries()->setMeshSmooth(false);
break; break;
case 9: case 9:
m_graph->seriesList().at(0)->setMesh(QAbstract3DSeries::Mesh::BevelBar); m_graph->selectedSeries()->setMesh(QAbstract3DSeries::Mesh::BevelBar);
m_graph->seriesList().at(0)->setMeshSmooth(true); m_graph->selectedSeries()->setMeshSmooth(true);
break; break;
} }
model++; model++;