React to userDefinedMesh and mesh change in Surface3D

Pick-to: 6.8.1 6.8
Fixes: QTBUG-130010
Fixes: QTBUG-130011
Fixes: QTBUG-130870
Change-Id: I3516b1af5a1af65ad0060c775143e73af8732167
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
This commit is contained in:
Tomi Korpipaa 2024-10-25 10:33:18 +03:00
parent ffa6c6018d
commit 1728887e0a
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/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

View File

@ -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();
}

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 "qsurfacedataproxy_p.h"
#include "qvalue3daxis_p.h"
#include "surfaceselectioninstancing_p.h"
#include <QtQuick3D/private/qquick3dcustommaterial_p.h>
#include <QtQuick3D/private/qquick3ddefaultmaterial_p.h>
@ -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<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)
{
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<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()

View File

@ -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<SurfaceModel *> m_model;
QQuick3DModel *m_selectionPointer = nullptr;
SurfaceSelectionInstancing *m_instancing = nullptr;
QQuick3DModel *m_sliceSelectionPointer = nullptr;
SurfaceSelectionInstancing *m_sliceInstancing = nullptr;
QMap<QSurface3DSeries *, QQuick3DModel *> m_selectionPointers = {};
QMap<QSurface3DSeries *, QQuick3DModel *> m_sliceSelectionPointers = {};
bool m_isIndexDirty = true;
bool m_selectionDirty = false;

View File

@ -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++;