QmlDesigner: Select correct underlying View3D for "Edit in 3D View"

If the selected node is not View3D, check if the topmost item in
scenePosition is View3D and target that instead for "Edit in 3D View"
action.

Fixes: QDS-12347
Change-Id: I06b59f55246e828cced8dd3c15ee9b297e5edeb7
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2024-04-23 11:39:53 +03:00
parent 7dfa746920
commit 651d7f5d85
5 changed files with 58 additions and 14 deletions

View File

@@ -61,11 +61,6 @@ inline static QString captionForModelNode(const ModelNode &modelNode)
return modelNode.id(); return modelNode.id();
} }
inline static bool contains(const QmlItemNode &node, const QPointF &position)
{
return node.isValid() && node.instanceSceneTransform().mapRect(node.instanceBoundingRect()).contains(position);
}
DesignerActionManagerView *DesignerActionManager::view() DesignerActionManagerView *DesignerActionManager::view()
{ {
return m_designerActionManagerView; return m_designerActionManagerView;
@@ -438,8 +433,8 @@ public:
} }
for (const ModelNode &node : selectionContext().view()->allModelNodes()) { for (const ModelNode &node : selectionContext().view()->allModelNodes()) {
if (node != selectionContext().currentSingleSelectedNode() && node != parentNode if (node != selectionContext().currentSingleSelectedNode() && node != parentNode
&& contains(node, selectionContext().scenePosition()) && !node.isRootNode() && SelectionContextHelpers::contains(node, selectionContext().scenePosition())
&& !ModelUtils::isThisOrAncestorLocked(node)) { && !node.isRootNode() && !ModelUtils::isThisOrAncestorLocked(node)) {
selectionContext().setTargetNode(node); selectionContext().setTargetNode(node);
QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1")).arg(captionForModelNode(node)); QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1")).arg(captionForModelNode(node));
ActionTemplate *selectionAction = new ActionTemplate("SELECT", what, &ModelNodeOperations::select); ActionTemplate *selectionAction = new ActionTemplate("SELECT", what, &ModelNodeOperations::select);
@@ -1971,7 +1966,7 @@ void DesignerActionManager::createDefaultDesignerActions()
QKeySequence(), QKeySequence(),
Priorities::ComponentActions + 1, Priorities::ComponentActions + 1,
&editIn3dView, &editIn3dView,
&singleSelectionView3D, &SelectionContextFunctors::always, // If action is visible, it is usable
&singleSelectionView3D)); &singleSelectionView3D));
addDesignerAction(new ModelNodeContextMenuAction( addDesignerAction(new ModelNodeContextMenuAction(

View File

@@ -25,6 +25,16 @@ namespace QmlDesigner {
using SelectionContextPredicate = std::function<bool (const SelectionContext&)>; using SelectionContextPredicate = std::function<bool (const SelectionContext&)>;
using SelectionContextOperation = std::function<void (const SelectionContext&)>; using SelectionContextOperation = std::function<void (const SelectionContext&)>;
namespace SelectionContextHelpers {
inline bool contains(const QmlItemNode &node, const QPointF &position)
{
return node.isValid()
&& node.instanceSceneTransform().mapRect(node.instanceBoundingRect()).contains(position);
}
} // namespace SelectionContextHelpers
namespace SelectionContextFunctors { namespace SelectionContextFunctors {
inline bool always(const SelectionContext &) inline bool always(const SelectionContext &)
@@ -99,8 +109,22 @@ inline bool singleSelectionNotRoot(const SelectionContext &selectionState)
inline bool singleSelectionView3D(const SelectionContext &selectionState) inline bool singleSelectionView3D(const SelectionContext &selectionState)
{ {
return selectionState.singleNodeIsSelected() if (selectionState.singleNodeIsSelected()
&& selectionState.currentSingleSelectedNode().metaInfo().isQtQuick3DView3D(); && selectionState.currentSingleSelectedNode().metaInfo().isQtQuick3DView3D()) {
return true;
}
// If currently selected node is not View3D, check if there is a View3D under the cursor.
if (!selectionState.scenePosition().isNull()) {
// Assumption is that last match in allModelNodes() list is the topmost one.
const QList<ModelNode> allNodes = selectionState.view()->allModelNodes();
for (int i = allNodes.size() - 1; i >= 0; --i) {
if (SelectionContextHelpers::contains(allNodes[i], selectionState.scenePosition()))
return allNodes[i].metaInfo().isQtQuick3DView3D();
}
}
return false;
} }
inline bool selectionHasProperty(const SelectionContext &selectionState, const char *property) inline bool selectionHasProperty(const SelectionContext &selectionState, const char *property)

View File

@@ -1685,16 +1685,37 @@ void updateImported3DAsset(const SelectionContext &selectionContext)
void editIn3dView(const SelectionContext &selectionContext) void editIn3dView(const SelectionContext &selectionContext)
{ {
if (selectionContext.view() && selectionContext.hasSingleSelectedModelNode() if (!selectionContext.view())
return;
ModelNode targetNode;
if (selectionContext.hasSingleSelectedModelNode()
&& selectionContext.currentSingleSelectedNode().metaInfo().isQtQuick3DView3D()) { && selectionContext.currentSingleSelectedNode().metaInfo().isQtQuick3DView3D()) {
targetNode = selectionContext.currentSingleSelectedNode();
}
const QPointF scenePos = selectionContext.scenePosition();
if (!targetNode.isValid() && !scenePos.isNull()) {
// If currently selected node is not View3D, check if there is a View3D under the cursor.
// Assumption is that last match in allModelNodes() list is the topmost one.
const QList<ModelNode> allNodes = selectionContext.view()->allModelNodes();
for (int i = allNodes.size() - 1; i >= 0; --i) {
if (SelectionContextHelpers::contains(allNodes[i], selectionContext.scenePosition())) {
if (allNodes[i].metaInfo().isQtQuick3DView3D())
targetNode = allNodes[i];
break;
}
}
}
if (targetNode.isValid()) {
QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("Editor3D", true); QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("Editor3D", true);
const QPointF scenePos = selectionContext.scenePosition();
if (scenePos.isNull()) { if (scenePos.isNull()) {
selectionContext.view()->emitView3DAction(View3DActionType::AlignViewToCamera, true); selectionContext.view()->emitView3DAction(View3DActionType::AlignViewToCamera, true);
} else { } else {
selectionContext.view()->emitCustomNotification("pick_3d_node_from_2d_scene", selectionContext.view()->emitCustomNotification("pick_3d_node_from_2d_scene",
{selectionContext.currentSingleSelectedNode()}, {targetNode}, {scenePos});
{scenePos});
} }
} }
} }

View File

@@ -462,6 +462,7 @@ void Edit3DView::customNotification([[maybe_unused]] const AbstractView *view,
self->emitView3DAction(View3DActionType::GetNodeAtMainScenePos, self->emitView3DAction(View3DActionType::GetNodeAtMainScenePos,
QVariantList{data[0], nodeList[0].internalId()}); QVariantList{data[0], nodeList[0].internalId()});
self->m_nodeAtPosReqType = NodeAtPosReqType::MainScenePick; self->m_nodeAtPosReqType = NodeAtPosReqType::MainScenePick;
self->m_pickView3dNode = nodeList[0];
}); });
} }
} }
@@ -514,6 +515,8 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos
} else if (m_nodeAtPosReqType == NodeAtPosReqType::MainScenePick) { } else if (m_nodeAtPosReqType == NodeAtPosReqType::MainScenePick) {
if (modelNode.isValid()) if (modelNode.isValid())
setSelectedModelNode(modelNode); setSelectedModelNode(modelNode);
else if (m_pickView3dNode.isValid() && !m_pickView3dNode.isSelected())
setSelectedModelNode(m_pickView3dNode);
emitView3DAction(View3DActionType::AlignViewToCamera, true); emitView3DAction(View3DActionType::AlignViewToCamera, true);
} }

View File

@@ -189,6 +189,7 @@ private:
QList<SplitToolState> m_splitToolStates; QList<SplitToolState> m_splitToolStates;
QList<Edit3DAction *> m_flyModeDisabledActions; QList<Edit3DAction *> m_flyModeDisabledActions;
ModelNode m_contextMenuPendingNode; ModelNode m_contextMenuPendingNode;
ModelNode m_pickView3dNode;
double m_previousCameraSpeed = -1.; double m_previousCameraSpeed = -1.;
double m_previousCameraMultiplier = -1.; double m_previousCameraMultiplier = -1.;