QmlDesigner: Implement selection box to 3D edit view

Change-Id: Ib0b13ecd7946e3b7da8ed06d4f5965e06e51a152
Fixes: QDS-1210
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2019-11-19 17:43:03 +02:00
parent dbfdacecf4
commit 0b510f173e
11 changed files with 384 additions and 9 deletions

View File

@@ -200,6 +200,11 @@ Window {
step: 50
}
SelectionBox {
view3D: editView
targetNode: viewWindow.selectedNode
}
PointLight {
id: editLight
visible: showEditLight

View File

@@ -84,7 +84,7 @@ Node {
anchors.fill: parent
cached: true
source: iconImage
color: transparent
color: "transparent"
opacity: 0.6
}

View File

@@ -29,11 +29,13 @@ import QtQuick3D 1.0
IconGizmo {
id: lightGizmo
iconSource: targetNode instanceof DirectionalLight
iconSource: targetNode
? targetNode instanceof DirectionalLight
? "qrc:///qtquickplugin/mockfiles/images/directional_light_gradient.png"
: targetNode instanceof AreaLight
? "qrc:///qtquickplugin/mockfiles/images/area_light_gradient.png"
: "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png"
: "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png"
overlayColor: targetNode.color
overlayColor: targetNode ? targetNode.color : "transparent"
}

View File

@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.0
import QtQuick3D 1.0
import SelectionBoxGeometry 1.0
Node {
id: selectionBox
property View3D view3D
property Node targetNode: null
SelectionBoxGeometry {
id: selectionBoxGeometry
name: "Selection Box of 3D Edit View"
view3D: selectionBox.view3D
targetNode: selectionBox.targetNode
rootNode: selectionBox
}
Model {
id: selectionBoxModel
geometry: selectionBoxGeometry
scale: selectionBox.targetNode ? selectionBox.targetNode.scale : Qt.vector3d(1, 1, 1)
rotation: selectionBox.targetNode ? selectionBox.targetNode.rotation : Qt.vector3d(0, 0, 0)
position: selectionBox.targetNode ? selectionBox.targetNode.position : Qt.vector3d(0, 0, 0)
pivot: selectionBox.targetNode ? selectionBox.targetNode.pivot : Qt.vector3d(0, 0, 0)
orientation: selectionBox.targetNode ? selectionBox.targetNode.orientation : Node.LeftHanded
rotationOrder: selectionBox.targetNode ? selectionBox.targetNode.rotationOrder : Node.YXZ
visible: selectionBox.targetNode && selectionBox.targetNode instanceof Model
materials: [
DefaultMaterial {
emissiveColor: "#e5009e"
lighting: DefaultMaterial.NoLighting
cullingMode: Material.DisableCulling
}
]
}
}

View File

@@ -1,9 +1,11 @@
HEADERS += $$PWD/generalhelper.h \
$$PWD/mousearea3d.h \
$$PWD/camerageometry.h \
$$PWD/gridgeometry.h
$$PWD/gridgeometry.h \
$$PWD/selectionboxgeometry.h
SOURCES += $$PWD/generalhelper.cpp \
$$PWD/mousearea3d.cpp \
$$PWD/camerageometry.cpp \
$$PWD/gridgeometry.cpp
$$PWD/gridgeometry.cpp \
$$PWD/selectionboxgeometry.cpp

View File

@@ -0,0 +1,216 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#ifdef QUICK3D_MODULE
#include "selectionboxgeometry.h"
#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
#include <QtQuick3DUtils/private/qssgbounds3_p.h>
#include <QtQuick3D/private/qquick3dmodel_p.h>
#include <QtQuick3D/private/qquick3dobject_p_p.h>
#include <QtQuick/qquickwindow.h>
namespace QmlDesigner {
namespace Internal {
SelectionBoxGeometry::SelectionBoxGeometry()
: QQuick3DGeometry()
{
}
SelectionBoxGeometry::~SelectionBoxGeometry()
{
}
QQuick3DNode *SelectionBoxGeometry::targetNode() const
{
return m_targetNode;
}
QQuick3DNode *SelectionBoxGeometry::rootNode() const
{
return m_rootNode;
}
QQuick3DViewport *SelectionBoxGeometry::view3D() const
{
return m_view3D;
}
void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode)
{
if (m_targetNode == targetNode)
return;
if (m_targetNode)
m_targetNode->disconnect(this);
m_targetNode = targetNode;
if (auto model = qobject_cast<QQuick3DModel *>(m_targetNode)) {
QObject::connect(model, &QQuick3DModel::sourceChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
QObject::connect(model, &QQuick3DModel::geometryChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
}
emit targetNodeChanged();
update();
}
void SelectionBoxGeometry::setRootNode(QQuick3DNode *rootNode)
{
if (m_rootNode == rootNode)
return;
m_rootNode = rootNode;
emit rootNodeChanged();
update();
}
void SelectionBoxGeometry::setView3D(QQuick3DViewport *view)
{
if (m_view3D == view)
return;
m_view3D = view;
emit view3DChanged();
update();
}
QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
{
node = QQuick3DGeometry::updateSpatialNode(node);
QSSGRenderGeometry *geometry = static_cast<QSSGRenderGeometry *>(node);
geometry->clear();
QByteArray vertexData;
QByteArray indexData;
QVector3D minBounds(-100.f, -100.f, -100.f);
QVector3D maxBounds(100.f, 100.f, 100.f);
QVector3D extents;
if (m_targetNode) {
auto rootPriv = QQuick3DObjectPrivate::get(m_rootNode);
auto targetPriv = QQuick3DObjectPrivate::get(m_targetNode);
auto rootRN = static_cast<QSSGRenderNode *>(rootPriv->spatialNode);
auto targetRN = static_cast<QSSGRenderNode *>(targetPriv->spatialNode);
if (rootRN && targetRN) {
// Explicitly set local transform of root node to target node parent's global transform
// to avoid having to reparent the selection box. This has to be done directly on render
// nodes.
targetRN->parent->calculateGlobalVariables();
QMatrix4x4 m = targetRN->parent->globalTransform;
rootRN->localTransform = m;
rootRN->markDirty(QSSGRenderNode::TransformDirtyFlag::TransformNotDirty);
rootRN->calculateGlobalVariables();
}
if (auto modelNode = qobject_cast<QQuick3DModel *>(m_targetNode)) {
auto nodePriv = QQuick3DObjectPrivate::get(m_targetNode);
if (auto renderModel = static_cast<QSSGRenderModel *>(nodePriv->spatialNode)) {
QWindow *window = static_cast<QWindow *>(m_view3D->window());
if (window) {
auto context = QSSGRenderContextInterface::getRenderContextInterface(
quintptr(window));
if (!context.isNull()) {
auto bufferManager = context->bufferManager();
QSSGBounds3 bounds = renderModel->getModelBounds(bufferManager);
QVector3D center = bounds.center();
extents = bounds.extents();
minBounds = center - extents;
maxBounds = center + extents;
}
}
}
}
}
// Adjust bounds to reduce targetNode pixels obscuring the selection box
extents /= 1000.f;
minBounds -= extents;
maxBounds += extents;
fillVertexData(vertexData, indexData, minBounds, maxBounds);
geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::F32Type);
geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::U16Type);
geometry->setStride(12);
geometry->setVertexData(vertexData);
geometry->setIndexData(indexData);
geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
geometry->setBounds(minBounds, maxBounds);
return node;
}
void SelectionBoxGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData,
const QVector3D &minBounds, const QVector3D &maxBounds)
{
const int vertexSize = int(sizeof(float)) * 8 * 3; // 8 vertices, 3 floats/vert
vertexData.resize(vertexSize);
const int indexSize = int(sizeof(quint16)) * 12 * 2; // 12 lines, 2 vert/line
indexData.resize(indexSize);
auto dataPtr = reinterpret_cast<float *>(vertexData.data());
auto indexPtr = reinterpret_cast<quint16 *>(indexData.data());
*dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z();
*dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z();
*dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = maxBounds.z();
*dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = maxBounds.z();
*dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = minBounds.z();
*dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = minBounds.z();
*dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z();
*dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z();
*indexPtr++ = 0; *indexPtr++ = 1;
*indexPtr++ = 1; *indexPtr++ = 2;
*indexPtr++ = 2; *indexPtr++ = 3;
*indexPtr++ = 3; *indexPtr++ = 0;
*indexPtr++ = 0; *indexPtr++ = 4;
*indexPtr++ = 1; *indexPtr++ = 5;
*indexPtr++ = 2; *indexPtr++ = 6;
*indexPtr++ = 3; *indexPtr++ = 7;
*indexPtr++ = 4; *indexPtr++ = 5;
*indexPtr++ = 5; *indexPtr++ = 6;
*indexPtr++ = 6; *indexPtr++ = 7;
*indexPtr++ = 7; *indexPtr++ = 4;
}
}
}
#endif // QUICK3D_MODULE

View File

@@ -0,0 +1,79 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#ifdef QUICK3D_MODULE
#include <QtQuick3D/private/qquick3dnode_p.h>
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include <QtQuick3D/private/qquick3dviewport_p.h>
namespace QmlDesigner {
namespace Internal {
class SelectionBoxGeometry : public QQuick3DGeometry
{
Q_OBJECT
Q_PROPERTY(QQuick3DNode *targetNode READ targetNode WRITE setTargetNode NOTIFY targetNodeChanged)
Q_PROPERTY(QQuick3DNode *rootNode READ rootNode WRITE setRootNode NOTIFY rootNodeChanged)
Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged)
public:
SelectionBoxGeometry();
~SelectionBoxGeometry() override;
QQuick3DNode *targetNode() const;
QQuick3DNode *rootNode() const;
QQuick3DViewport *view3D() const;
public Q_SLOTS:
void setTargetNode(QQuick3DNode *targetNode);
void setRootNode(QQuick3DNode *rootNode);
void setView3D(QQuick3DViewport *view);
Q_SIGNALS:
void targetNodeChanged();
void rootNodeChanged();
void view3DChanged();
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
private:
void fillVertexData(QByteArray &vertexData, QByteArray &indexData,
const QVector3D &minBounds, const QVector3D &maxBounds);
QQuick3DNode *m_targetNode = nullptr;
QQuick3DViewport *m_view3D = nullptr;
QQuick3DNode *m_rootNode = nullptr;
};
}
}
QML_DECLARE_TYPE(QmlDesigner::Internal::SelectionBoxGeometry)
#endif // QUICK3D_MODULE

View File

@@ -66,6 +66,7 @@
#include "../editor3d/mousearea3d.h"
#include "../editor3d/camerageometry.h"
#include "../editor3d/gridgeometry.h"
#include "../editor3d/selectionboxgeometry.h"
#include <designersupportdelegate.h>
@@ -110,6 +111,7 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D");
qmlRegisterType<QmlDesigner::Internal::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry");
qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry");
qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
#endif
QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"));

View File

@@ -26,6 +26,7 @@
<file>mockfiles/ToolBarButton.qml</file>
<file>mockfiles/RotateGizmo.qml</file>
<file>mockfiles/RotateRing.qml</file>
<file>mockfiles/SelectionBox.qml</file>
<file>mockfiles/meshes/arrow.mesh</file>
<file>mockfiles/meshes/scalerod.mesh</file>
<file>mockfiles/meshes/ring.mesh</file>

View File

@@ -112,6 +112,7 @@ extend_qtc_executable(qml2puppet
mousearea3d.cpp mousearea3d.h
camerageometry.cpp camerageometry.h
gridgeometry.cpp gridgeometry.h
selectionboxgeometry.cpp selectionboxgeometry.h
)
extend_qtc_executable(qml2puppet

View File

@@ -205,6 +205,8 @@ QtcTool {
"editor3d/camerageometry.h",
"editor3d/gridgeometry.cpp",
"editor3d/gridgeometry.h",
"editor3d/selectionboxgeometry.cpp",
"editor3d/selectionboxgeometry.h",
"qml2puppetmain.cpp",
]
}