From c1f3dc4f5473cb3fa8cb59bf2c6d607a059c75c6 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Mon, 7 Nov 2022 16:50:23 +0200 Subject: [PATCH] QmlDesigner: Add positioning methods to QmlVisualNode QmlVisualNode would be able to: 1. Set a position for the visual node 2. Translate the position of the visual node 3. The visual node could be scattered 4. Get the related position of visual node All these methods will work for either 2D or 3D nodes. Also, a potential bug has been fixed for the Position. It was assumed that if a position equals to 0, it's not a valid position, but now it's handled by this change. Change-Id: I9dd59dbe0d14084087ff39bd14d2a783d24a5efd Reviewed-by: Miikka Heikkinen Reviewed-by: Mahmoud Badri --- .../designercore/include/qmlvisualnode.h | 16 +-- .../designercore/model/qmlvisualnode.cpp | 97 +++++++++++++++---- 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h index ee0817d3737..8506de0edf7 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h @@ -26,23 +26,24 @@ class QMLDESIGNERCORE_EXPORT QmlVisualNode : public QmlObjectNode friend class QmlAnchors; public: - class Position + class Position : public QVector3D { friend class QmlVisualNode; public: Position() {} Position(const QPointF &position) : - m_2dPos(position) + QVector3D(position) {} Position(const QVector3D &position) : - m_3dPos(position) + QVector3D(position), + m_is3D(true) {} + bool is3D() const; QList> propertyPairList() const; private: - QPointF m_2dPos; - QVector3D m_3dPos; + bool m_is3D = false; }; QmlVisualNode() = default; @@ -65,7 +66,10 @@ public: void setVisibilityOverride(bool visible); bool visibilityOverride() const; - void initializePosition(const Position &position); + void scatter(const ModelNode &targetNode, const std::optional &offset); + void translate(const QVector3D &vector); + void setPosition(const Position &position); + Position position() const; static bool isItemOr3DNode(const ModelNode &modelNode); diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp index 0fb9209b3f1..36edea4e9ea 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace QmlDesigner { @@ -156,21 +157,81 @@ bool QmlVisualNode::visibilityOverride() const return false; } +void QmlVisualNode::scatter(const ModelNode &targetNode, const std::optional &offset) +{ + if (!isValid()) + return; + + if (targetNode.metaInfo().isValid() && targetNode.metaInfo().isLayoutable()) + return; + + bool scatter = false; + const QList targetDirectNodes = targetNode.directSubModelNodes(); + for (const ModelNode &childNode : targetDirectNodes) { + if (childNode == modelNode()) + continue; + + if (isValidQmlVisualNode(childNode)) { + Position childPos = QmlVisualNode(childNode).position(); + if (qFuzzyCompare(position().distanceToPoint(childPos), 0.f)) { + scatter = true; + break; + } + } + } + + if (!scatter) + return; + + if (offset.has_value()) { // offset + double offsetValue = offset.value(); + this->translate(QVector3D(offsetValue, offsetValue, offsetValue)); + } else { // scatter in range + const double scatterRange = 20.; + double x = QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2; + double y = QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2; + double z = (modelNode().metaInfo().isQtQuick3DNode()) + ? QRandomGenerator::global()->generateDouble() * scatterRange - scatterRange / 2 + : 0.; + this->translate(QVector3D(x, y, z)); + } +} + +void QmlVisualNode::translate(const QVector3D &vector) +{ + setPosition(position() + vector); +} + void QmlVisualNode::setDoubleProperty(const PropertyName &name, double value) { modelNode().variantProperty(name).setValue(value); } -void QmlVisualNode::initializePosition(const QmlVisualNode::Position &position) +void QmlVisualNode::setPosition(const QmlVisualNode::Position &position) { - if (!position.m_2dPos.isNull()) { - setDoubleProperty("x", qRound(position.m_2dPos.x())); - setDoubleProperty("y", qRound(position.m_2dPos.y())); - } else if (!position.m_3dPos.isNull()) { - setDoubleProperty("x", position.m_3dPos.x()); - setDoubleProperty("y", position.m_3dPos.y()); - setDoubleProperty("z", position.m_3dPos.z()); + if (!isValid()) + return; + + setDoubleProperty("x", position.x()); + setDoubleProperty("y", position.y()); + + if (position.is3D() && modelNode().metaInfo().isQtQuick3DNode()) + setDoubleProperty("z", position.z()); +} + +QmlVisualNode::Position QmlVisualNode::position() const +{ + if (!isValid()) + return {}; + + double x = modelNode().variantProperty("x").value().toDouble(); + double y = modelNode().variantProperty("y").value().toDouble(); + + if (modelNode().metaInfo().isQtQuick3DModel()) { + double z = modelNode().variantProperty("z").value().toDouble(); + return Position(QVector3D(x,y,z)); } + return Position(QPointF(x,y)); } QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, @@ -230,7 +291,7 @@ static QmlObjectNode createQmlObjectNodeFromSource(AbstractView *view, if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) { ModelNode rootModelNode = rewriterView->rootModelNode(); inputModel->detachView(rewriterView.data()); - QmlVisualNode(rootModelNode).initializePosition(position); + QmlVisualNode(rootModelNode).setPosition(position); ModelMerger merger(view); return merger.insertModel(rootModelNode); } @@ -496,18 +557,20 @@ QmlModelState QmlModelStateGroup::state(const QString &name) const return QmlModelState(); } +bool QmlVisualNode::Position::is3D() const +{ + return m_is3D; +} + QList > QmlVisualNode::Position::propertyPairList() const { QList > propertyPairList; - if (!m_2dPos.isNull()) { - propertyPairList.append({"x", QVariant(qRound(m_2dPos.x()))}); - propertyPairList.append({"y", QVariant(qRound(m_2dPos.y()))}); - } else if (!m_3dPos.isNull()) { - propertyPairList.append({"x", QVariant(m_3dPos.x())}); - propertyPairList.append({"y", QVariant(m_3dPos.y())}); - propertyPairList.append({"z", QVariant(m_3dPos.z())}); - } + propertyPairList.append({"x", QVariant(qRound(x()))}); + propertyPairList.append({"y", QVariant(qRound(y()))}); + + if (m_is3D) + propertyPairList.append({"z", QVariant(z())}); return propertyPairList; }