forked from qt-creator/qt-creator
QmlDesigner: Create 3D models at the point of context menu trigger
Fixes: QDS-7640 Change-Id: I2f178c2e2661dedc4efe23b675363283e3cd3bc3 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
@@ -81,23 +81,10 @@ public:
|
|||||||
QQuick3DNode *pickNode() const;
|
QQuick3DNode *pickNode() const;
|
||||||
MouseArea3D *dragHelper() const;
|
MouseArea3D *dragHelper() const;
|
||||||
|
|
||||||
|
QVector3D getMousePosInPlane(const MouseArea3D *helper, const QPointF &mousePosInView) const;
|
||||||
|
|
||||||
static qreal mouseDragMultiplier() { return .02; }
|
static qreal mouseDragMultiplier() { return .02; }
|
||||||
|
|
||||||
public slots:
|
|
||||||
void setView3D(QQuick3DViewport *view3D);
|
|
||||||
void setGrabsMouse(bool grabsMouse);
|
|
||||||
void setActive(bool active);
|
|
||||||
void setCirclePickArea(const QPointF &pickArea);
|
|
||||||
void setMinAngle(qreal angle);
|
|
||||||
void setPickNode(QQuick3DNode *node);
|
|
||||||
void setDragHelper(MouseArea3D *dragHelper);
|
|
||||||
|
|
||||||
void setX(qreal x);
|
|
||||||
void setY(qreal y);
|
|
||||||
void setWidth(qreal width);
|
|
||||||
void setHeight(qreal height);
|
|
||||||
void setPriority(int level);
|
|
||||||
|
|
||||||
Q_INVOKABLE QVector3D rayIntersectsPlane(const QVector3D &rayPos0,
|
Q_INVOKABLE QVector3D rayIntersectsPlane(const QVector3D &rayPos0,
|
||||||
const QVector3D &rayPos1,
|
const QVector3D &rayPos1,
|
||||||
const QVector3D &planePos,
|
const QVector3D &planePos,
|
||||||
@@ -120,6 +107,21 @@ public slots:
|
|||||||
Q_INVOKABLE void forceMoveEvent(double x, double y);
|
Q_INVOKABLE void forceMoveEvent(double x, double y);
|
||||||
Q_INVOKABLE void forceReleaseEvent(double x, double y);
|
Q_INVOKABLE void forceReleaseEvent(double x, double y);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setView3D(QQuick3DViewport *view3D);
|
||||||
|
void setGrabsMouse(bool grabsMouse);
|
||||||
|
void setActive(bool active);
|
||||||
|
void setCirclePickArea(const QPointF &pickArea);
|
||||||
|
void setMinAngle(qreal angle);
|
||||||
|
void setPickNode(QQuick3DNode *node);
|
||||||
|
void setDragHelper(MouseArea3D *dragHelper);
|
||||||
|
|
||||||
|
void setX(qreal x);
|
||||||
|
void setY(qreal y);
|
||||||
|
void setWidth(qreal width);
|
||||||
|
void setHeight(qreal height);
|
||||||
|
void setPriority(int level);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void view3DChanged();
|
void view3DChanged();
|
||||||
|
|
||||||
@@ -153,7 +155,6 @@ private:
|
|||||||
void setHovering(bool enable);
|
void setHovering(bool enable);
|
||||||
QVector3D getNormal() const;
|
QVector3D getNormal() const;
|
||||||
QVector3D getCameraToNodeDir(QQuick3DNode *node) const;
|
QVector3D getCameraToNodeDir(QQuick3DNode *node) const;
|
||||||
QVector3D getMousePosInPlane(const MouseArea3D *helper, const QPointF &mousePosInView) const;
|
|
||||||
|
|
||||||
Q_DISABLE_COPY(MouseArea3D)
|
Q_DISABLE_COPY(MouseArea3D)
|
||||||
QQuick3DViewport *m_view3D = nullptr;
|
QQuick3DViewport *m_view3D = nullptr;
|
||||||
|
@@ -428,18 +428,33 @@ void Qt5InformationNodeInstanceServer::getNodeAtPos(const QPointF &pos)
|
|||||||
Q_ARG(QVariant, pos.x()),
|
Q_ARG(QVariant, pos.x()),
|
||||||
Q_ARG(QVariant, pos.y()));
|
Q_ARG(QVariant, pos.y()));
|
||||||
QObject *gizmoObj = qvariant_cast<QObject *>(gizmoVar);
|
QObject *gizmoObj = qvariant_cast<QObject *>(gizmoVar);
|
||||||
QVariant instance = -1;
|
qint32 instanceId = -1;
|
||||||
|
|
||||||
if (gizmoObj && hasInstanceForObject(gizmoObj)) {
|
if (gizmoObj && hasInstanceForObject(gizmoObj)) {
|
||||||
instance = instanceForObject(gizmoObj).instanceId();
|
instanceId = instanceForObject(gizmoObj).instanceId();
|
||||||
} else {
|
} else {
|
||||||
QQuick3DModel *hitModel = helper->pickViewAt(editView, pos.x(), pos.y()).objectHit();
|
QQuick3DModel *hitModel = helper->pickViewAt(editView, pos.x(), pos.y()).objectHit();
|
||||||
QObject *resolvedPick = helper->resolvePick(hitModel);
|
QObject *resolvedPick = helper->resolvePick(hitModel);
|
||||||
if (hasInstanceForObject(resolvedPick))
|
if (hasInstanceForObject(resolvedPick))
|
||||||
instance = instanceForObject(resolvedPick).instanceId();
|
instanceId = instanceForObject(resolvedPick).instanceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::NodeAtPos, instance});
|
// Also get the intersection with an axis plane of the scene.
|
||||||
|
QVector3D pos3d;
|
||||||
|
if (editView) {
|
||||||
|
Internal::MouseArea3D ma;
|
||||||
|
ma.setView3D(editView);
|
||||||
|
ma.setEulerRotation({90, 0, 0}); // Default grid plane (XZ plane)
|
||||||
|
QVector3D planePos = ma.getMousePosInPlane(nullptr, pos);
|
||||||
|
const float limit = 10000000; // Remove extremes on nearly parallel plane
|
||||||
|
if (!qFuzzyCompare(planePos.z(), -1.f) && qAbs(planePos.x()) < limit && qAbs(planePos.y()) < limit)
|
||||||
|
pos3d = {planePos.x(), 0, planePos.y()};
|
||||||
|
}
|
||||||
|
QVariantList data;
|
||||||
|
data.append(instanceId);
|
||||||
|
data.append(pos3d);
|
||||||
|
nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::NodeAtPos,
|
||||||
|
QVariant::fromValue(data)});
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(pos)
|
Q_UNUSED(pos)
|
||||||
#endif
|
#endif
|
||||||
|
@@ -295,15 +295,16 @@ void Edit3DView::customNotification(const AbstractView *view, const QString &ide
|
|||||||
* Response from puppet process for the model at requested position
|
* Response from puppet process for the model at requested position
|
||||||
*
|
*
|
||||||
* @param modelNode Node picked at the requested position or invalid node if nothing could be picked
|
* @param modelNode Node picked at the requested position or invalid node if nothing could be picked
|
||||||
|
* @param pos3d 3D scene position of the requested view position
|
||||||
*/
|
*/
|
||||||
void Edit3DView::nodeAtPosReady(const ModelNode &modelNode)
|
void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d)
|
||||||
{
|
{
|
||||||
if (m_nodeAtPosReqType == NodeAtPosReqType::ContextMenu) {
|
if (m_nodeAtPosReqType == NodeAtPosReqType::ContextMenu) {
|
||||||
// Make sure right-clicked item is selected. Due to a bug in puppet side right-clicking an item
|
// Make sure right-clicked item is selected. Due to a bug in puppet side right-clicking an item
|
||||||
// while the context-menu is shown doesn't select the item.
|
// while the context-menu is shown doesn't select the item.
|
||||||
if (modelNode.isValid() && !modelNode.isSelected())
|
if (modelNode.isValid() && !modelNode.isSelected())
|
||||||
setSelectedModelNode(modelNode);
|
setSelectedModelNode(modelNode);
|
||||||
m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode);
|
m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode, pos3d);
|
||||||
} else if (m_nodeAtPosReqType == NodeAtPosReqType::MaterialDrop) {
|
} else if (m_nodeAtPosReqType == NodeAtPosReqType::MaterialDrop) {
|
||||||
if (m_droppedMaterial.isValid() && modelNode.isValid()
|
if (m_droppedMaterial.isValid() && modelNode.isValid()
|
||||||
&& modelNode.isSubclassOf("QtQuick3D.Model")) {
|
&& modelNode.isSubclassOf("QtQuick3D.Model")) {
|
||||||
|
@@ -63,7 +63,7 @@ public:
|
|||||||
void modelAboutToBeDetached(Model *model) override;
|
void modelAboutToBeDetached(Model *model) override;
|
||||||
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
|
||||||
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
|
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
|
||||||
void nodeAtPosReady(const ModelNode &modelNode) override;
|
void nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d) override;
|
||||||
|
|
||||||
void sendInputEvent(QInputEvent *e) const;
|
void sendInputEvent(QInputEvent *e) const;
|
||||||
void edit3DViewResized(const QSize &size) const;
|
void edit3DViewResized(const QSize &size) const;
|
||||||
|
@@ -238,7 +238,7 @@ void Edit3DWidget::onCreateAction()
|
|||||||
int activeScene = m_view->rootModelNode().auxiliaryData("active3dScene@Internal").toInt();
|
int activeScene = m_view->rootModelNode().auxiliaryData("active3dScene@Internal").toInt();
|
||||||
|
|
||||||
auto modelNode = QmlVisualNode::createQml3DNode(m_view, m_nameToEntry.value(action->data().toString()),
|
auto modelNode = QmlVisualNode::createQml3DNode(m_view, m_nameToEntry.value(action->data().toString()),
|
||||||
activeScene).modelNode();
|
activeScene, m_contextMenuPos3d).modelNode();
|
||||||
QTC_ASSERT(modelNode.isValid(), return);
|
QTC_ASSERT(modelNode.isValid(), return);
|
||||||
m_view->setSelectedModelNode(modelNode);
|
m_view->setSelectedModelNode(modelNode);
|
||||||
|
|
||||||
@@ -296,9 +296,10 @@ void Edit3DWidget::showBackgroundColorMenu(bool show, const QPoint &pos)
|
|||||||
m_backgroundColorMenu->close();
|
m_backgroundColorMenu->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode)
|
void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode, const QVector3D &pos3d)
|
||||||
{
|
{
|
||||||
m_contextMenuTarget = modelNode;
|
m_contextMenuTarget = modelNode;
|
||||||
|
m_contextMenuPos3d = pos3d;
|
||||||
|
|
||||||
const bool isValid = modelNode.isValid();
|
const bool isValid = modelNode.isValid();
|
||||||
const bool isModel = isValid && modelNode.isSubclassOf("QtQuick3D.Model");
|
const bool isModel = isValid && modelNode.isSubclassOf("QtQuick3D.Model");
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QVector3D>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include <coreplugin/icontext.h>
|
#include <coreplugin/icontext.h>
|
||||||
@@ -57,7 +58,7 @@ public:
|
|||||||
QMenu *backgroundColorMenu() const;
|
QMenu *backgroundColorMenu() const;
|
||||||
void showBackgroundColorMenu(bool show, const QPoint &pos);
|
void showBackgroundColorMenu(bool show, const QPoint &pos);
|
||||||
|
|
||||||
void showContextMenu(const QPoint &pos, const ModelNode &modelNode);
|
void showContextMenu(const QPoint &pos, const ModelNode &modelNode, const QVector3D &pos3d);
|
||||||
void updateCreateSubMenu(const QStringList &keys,
|
void updateCreateSubMenu(const QStringList &keys,
|
||||||
const QHash<QString, QList<ItemLibraryEntry>> &entriesMap);
|
const QHash<QString, QList<ItemLibraryEntry>> &entriesMap);
|
||||||
|
|
||||||
@@ -85,6 +86,7 @@ private:
|
|||||||
QPointer<QAction> m_deleteAction;
|
QPointer<QAction> m_deleteAction;
|
||||||
QPointer<QMenu> m_createSubMenu;
|
QPointer<QMenu> m_createSubMenu;
|
||||||
ModelNode m_contextMenuTarget;
|
ModelNode m_contextMenuTarget;
|
||||||
|
QVector3D m_contextMenuPos3d;
|
||||||
QHash<QString, ItemLibraryEntry> m_nameToEntry;
|
QHash<QString, ItemLibraryEntry> m_nameToEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QVector3D>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
@@ -166,7 +167,7 @@ public:
|
|||||||
void emitUpdateActiveScene3D(const QVariantMap &sceneState);
|
void emitUpdateActiveScene3D(const QVariantMap &sceneState);
|
||||||
void emitModelNodelPreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
|
void emitModelNodelPreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
|
||||||
void emitImport3DSupportChanged(const QVariantMap &supportMap);
|
void emitImport3DSupportChanged(const QVariantMap &supportMap);
|
||||||
void emitNodeAtPosResult(const ModelNode &modelNode);
|
void emitNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d);
|
||||||
|
|
||||||
void sendTokenToInstances(const QString &token, int number, const QVector<ModelNode> &nodeVector);
|
void sendTokenToInstances(const QString &token, int number, const QVector<ModelNode> &nodeVector);
|
||||||
|
|
||||||
@@ -232,7 +233,7 @@ public:
|
|||||||
virtual void renderImage3DChanged(const QImage &image);
|
virtual void renderImage3DChanged(const QImage &image);
|
||||||
virtual void updateActiveScene3D(const QVariantMap &sceneState);
|
virtual void updateActiveScene3D(const QVariantMap &sceneState);
|
||||||
virtual void updateImport3DSupport(const QVariantMap &supportMap);
|
virtual void updateImport3DSupport(const QVariantMap &supportMap);
|
||||||
virtual void nodeAtPosReady(const ModelNode &modelNode);
|
virtual void nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d);
|
||||||
virtual void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
|
virtual void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
|
||||||
|
|
||||||
virtual void dragStarted(QMimeData *mimeData);
|
virtual void dragStarted(QMimeData *mimeData);
|
||||||
|
@@ -1706,8 +1706,12 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand
|
|||||||
const QVariantMap supportMap = qvariant_cast<QVariantMap>(command.data());
|
const QVariantMap supportMap = qvariant_cast<QVariantMap>(command.data());
|
||||||
emitImport3DSupportChanged(supportMap);
|
emitImport3DSupportChanged(supportMap);
|
||||||
} else if (command.type() == PuppetToCreatorCommand::NodeAtPos) {
|
} else if (command.type() == PuppetToCreatorCommand::NodeAtPos) {
|
||||||
ModelNode modelNode = modelNodeForInternalId(command.data().toUInt());
|
auto data = qvariant_cast<QVariantList>(command.data());
|
||||||
emitNodeAtPosResult(modelNode);
|
if (data.size() == 2) {
|
||||||
|
ModelNode modelNode = modelNodeForInternalId(data[0].toInt());
|
||||||
|
QVector3D pos3d = data[1].value<QVector3D>();
|
||||||
|
emitNodeAtPosResult(modelNode, pos3d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -408,8 +408,9 @@ void AbstractView::updateImport3DSupport(const QVariantMap & /*supportMap*/)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// a Quick3DModel that is picked at the requested position in the 3D Editor
|
// a Quick3DNode that is picked at the requested view position in the 3D Editor and the 3D scene
|
||||||
void AbstractView::nodeAtPosReady(const ModelNode & /*modelNode*/) {}
|
// position of the requested view position.
|
||||||
|
void AbstractView::nodeAtPosReady(const ModelNode & /*modelNode*/, const QVector3D &/*pos3d*/) {}
|
||||||
|
|
||||||
void AbstractView::modelNodePreviewPixmapChanged(const ModelNode & /*node*/, const QPixmap & /*pixmap*/)
|
void AbstractView::modelNodePreviewPixmapChanged(const ModelNode & /*node*/, const QPixmap & /*pixmap*/)
|
||||||
{
|
{
|
||||||
@@ -802,10 +803,10 @@ void AbstractView::emitImport3DSupportChanged(const QVariantMap &supportMap)
|
|||||||
model()->d->notifyImport3DSupportChanged(supportMap);
|
model()->d->notifyImport3DSupportChanged(supportMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractView::emitNodeAtPosResult(const ModelNode &modelNode)
|
void AbstractView::emitNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d)
|
||||||
{
|
{
|
||||||
if (model())
|
if (model())
|
||||||
model()->d->notifyNodeAtPosResult(modelNode);
|
model()->d->notifyNodeAtPosResult(modelNode, pos3d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractView::emitRewriterEndTransaction()
|
void AbstractView::emitRewriterEndTransaction()
|
||||||
|
@@ -598,9 +598,9 @@ void ModelPrivate::notifyImport3DSupportChanged(const QVariantMap &supportMap)
|
|||||||
notifyInstanceChanges([&](AbstractView *view) { view->updateImport3DSupport(supportMap); });
|
notifyInstanceChanges([&](AbstractView *view) { view->updateImport3DSupport(supportMap); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelPrivate::notifyNodeAtPosResult(const ModelNode &modelNode)
|
void ModelPrivate::notifyNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d)
|
||||||
{
|
{
|
||||||
notifyInstanceChanges([&](AbstractView *view) { view->nodeAtPosReady(modelNode); });
|
notifyInstanceChanges([&](AbstractView *view) { view->nodeAtPosReady(modelNode, pos3d); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelPrivate::notifyDragStarted(QMimeData *mimeData)
|
void ModelPrivate::notifyDragStarted(QMimeData *mimeData)
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
#include <QVector3D>
|
||||||
|
|
||||||
#include "modelnode.h"
|
#include "modelnode.h"
|
||||||
#include "abstractview.h"
|
#include "abstractview.h"
|
||||||
@@ -186,7 +187,7 @@ public:
|
|||||||
void notifyUpdateActiveScene3D(const QVariantMap &sceneState);
|
void notifyUpdateActiveScene3D(const QVariantMap &sceneState);
|
||||||
void notifyModelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
|
void notifyModelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
|
||||||
void notifyImport3DSupportChanged(const QVariantMap &supportMap);
|
void notifyImport3DSupportChanged(const QVariantMap &supportMap);
|
||||||
void notifyNodeAtPosResult(const ModelNode &modelNode);
|
void notifyNodeAtPosResult(const ModelNode &modelNode, const QVector3D &pos3d);
|
||||||
|
|
||||||
void notifyDragStarted(QMimeData *mimeData);
|
void notifyDragStarted(QMimeData *mimeData);
|
||||||
void notifyDragEnded();
|
void notifyDragEnded();
|
||||||
|
@@ -288,7 +288,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
|
|||||||
QList<PropertyBindingEntry> propertyBindingList;
|
QList<PropertyBindingEntry> propertyBindingList;
|
||||||
QList<PropertyBindingEntry> propertyEnumList;
|
QList<PropertyBindingEntry> propertyEnumList;
|
||||||
if (itemLibraryEntry.qmlSource().isEmpty()) {
|
if (itemLibraryEntry.qmlSource().isEmpty()) {
|
||||||
QList<QPair<PropertyName, QVariant> > propertyPairList = position.propertyPairList();
|
QList<QPair<PropertyName, QVariant> > propertyPairList;
|
||||||
|
|
||||||
for (const auto &property : itemLibraryEntry.properties()) {
|
for (const auto &property : itemLibraryEntry.properties()) {
|
||||||
if (property.type() == "binding") {
|
if (property.type() == "binding") {
|
||||||
@@ -302,6 +302,8 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
|
|||||||
propertyPairList.append({property.name(), property.value()});
|
propertyPairList.append({property.name(), property.value()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Add position last so it'll override any default position specified in the entry
|
||||||
|
propertyPairList.append(position.propertyPairList());
|
||||||
|
|
||||||
ModelNode::NodeSourceType nodeSourceType = ModelNode::NodeWithoutSource;
|
ModelNode::NodeSourceType nodeSourceType = ModelNode::NodeWithoutSource;
|
||||||
if (itemLibraryEntry.typeName() == "QtQml.Component")
|
if (itemLibraryEntry.typeName() == "QtQml.Component")
|
||||||
|
Reference in New Issue
Block a user