forked from qt-creator/qt-creator
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 <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -26,23 +26,24 @@ class QMLDESIGNERCORE_EXPORT QmlVisualNode : public QmlObjectNode
|
|||||||
friend class QmlAnchors;
|
friend class QmlAnchors;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Position
|
class Position : public QVector3D
|
||||||
{
|
{
|
||||||
friend class QmlVisualNode;
|
friend class QmlVisualNode;
|
||||||
public:
|
public:
|
||||||
Position() {}
|
Position() {}
|
||||||
Position(const QPointF &position) :
|
Position(const QPointF &position) :
|
||||||
m_2dPos(position)
|
QVector3D(position)
|
||||||
{}
|
{}
|
||||||
Position(const QVector3D &position) :
|
Position(const QVector3D &position) :
|
||||||
m_3dPos(position)
|
QVector3D(position),
|
||||||
|
m_is3D(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
bool is3D() const;
|
||||||
QList<QPair<PropertyName, QVariant>> propertyPairList() const;
|
QList<QPair<PropertyName, QVariant>> propertyPairList() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointF m_2dPos;
|
bool m_is3D = false;
|
||||||
QVector3D m_3dPos;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QmlVisualNode() = default;
|
QmlVisualNode() = default;
|
||||||
@@ -65,7 +66,10 @@ public:
|
|||||||
void setVisibilityOverride(bool visible);
|
void setVisibilityOverride(bool visible);
|
||||||
bool visibilityOverride() const;
|
bool visibilityOverride() const;
|
||||||
|
|
||||||
void initializePosition(const Position &position);
|
void scatter(const ModelNode &targetNode, const std::optional<int> &offset);
|
||||||
|
void translate(const QVector3D &vector);
|
||||||
|
void setPosition(const Position &position);
|
||||||
|
Position position() const;
|
||||||
|
|
||||||
static bool isItemOr3DNode(const ModelNode &modelNode);
|
static bool isItemOr3DNode(const ModelNode &modelNode);
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
@@ -156,21 +157,81 @@ bool QmlVisualNode::visibilityOverride() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlVisualNode::scatter(const ModelNode &targetNode, const std::optional<int> &offset)
|
||||||
|
{
|
||||||
|
if (!isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (targetNode.metaInfo().isValid() && targetNode.metaInfo().isLayoutable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool scatter = false;
|
||||||
|
const QList<ModelNode> 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)
|
void QmlVisualNode::setDoubleProperty(const PropertyName &name, double value)
|
||||||
{
|
{
|
||||||
modelNode().variantProperty(name).setValue(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()) {
|
if (!isValid())
|
||||||
setDoubleProperty("x", qRound(position.m_2dPos.x()));
|
return;
|
||||||
setDoubleProperty("y", qRound(position.m_2dPos.y()));
|
|
||||||
} else if (!position.m_3dPos.isNull()) {
|
setDoubleProperty("x", position.x());
|
||||||
setDoubleProperty("x", position.m_3dPos.x());
|
setDoubleProperty("y", position.y());
|
||||||
setDoubleProperty("y", position.m_3dPos.y());
|
|
||||||
setDoubleProperty("z", position.m_3dPos.z());
|
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,
|
QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
|
||||||
@@ -230,7 +291,7 @@ static QmlObjectNode createQmlObjectNodeFromSource(AbstractView *view,
|
|||||||
if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) {
|
if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) {
|
||||||
ModelNode rootModelNode = rewriterView->rootModelNode();
|
ModelNode rootModelNode = rewriterView->rootModelNode();
|
||||||
inputModel->detachView(rewriterView.data());
|
inputModel->detachView(rewriterView.data());
|
||||||
QmlVisualNode(rootModelNode).initializePosition(position);
|
QmlVisualNode(rootModelNode).setPosition(position);
|
||||||
ModelMerger merger(view);
|
ModelMerger merger(view);
|
||||||
return merger.insertModel(rootModelNode);
|
return merger.insertModel(rootModelNode);
|
||||||
}
|
}
|
||||||
@@ -496,18 +557,20 @@ QmlModelState QmlModelStateGroup::state(const QString &name) const
|
|||||||
return QmlModelState();
|
return QmlModelState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QmlVisualNode::Position::is3D() const
|
||||||
|
{
|
||||||
|
return m_is3D;
|
||||||
|
}
|
||||||
|
|
||||||
QList<QPair<PropertyName, QVariant> > QmlVisualNode::Position::propertyPairList() const
|
QList<QPair<PropertyName, QVariant> > QmlVisualNode::Position::propertyPairList() const
|
||||||
{
|
{
|
||||||
QList<QPair<PropertyName, QVariant> > propertyPairList;
|
QList<QPair<PropertyName, QVariant> > propertyPairList;
|
||||||
|
|
||||||
if (!m_2dPos.isNull()) {
|
propertyPairList.append({"x", QVariant(qRound(x()))});
|
||||||
propertyPairList.append({"x", QVariant(qRound(m_2dPos.x()))});
|
propertyPairList.append({"y", QVariant(qRound(y()))});
|
||||||
propertyPairList.append({"y", QVariant(qRound(m_2dPos.y()))});
|
|
||||||
} else if (!m_3dPos.isNull()) {
|
if (m_is3D)
|
||||||
propertyPairList.append({"x", QVariant(m_3dPos.x())});
|
propertyPairList.append({"z", QVariant(z())});
|
||||||
propertyPairList.append({"y", QVariant(m_3dPos.y())});
|
|
||||||
propertyPairList.append({"z", QVariant(m_3dPos.z())});
|
|
||||||
}
|
|
||||||
|
|
||||||
return propertyPairList;
|
return propertyPairList;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user