QmlDesigner: Add look-at gizmo to visualize 3D edit camera look-at pos

Look-at gizmo can be toggled from visibility toggles submenu.
Look-at gizmo is hidden when fly mode crosshairs is visible.

Fixes: QDS-12767
Change-Id: I2c71b23f14e403c9774498937764607cfea3bd1d
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2024-05-24 13:01:56 +03:00
parent c881408e5c
commit c5d0263b32
13 changed files with 198 additions and 10 deletions

View File

@@ -36,6 +36,7 @@ enum class View3DActionType {
OrientationToggle,
EditLightToggle,
ShowGrid,
ShowLookAt,
ShowSelectionBox,
ShowIconGizmo,
ShowCameraFrustum,

View File

@@ -135,6 +135,7 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState)
const QString orientationKey = QStringLiteral("globalOrientation");
const QString editLightKey = QStringLiteral("showEditLight");
const QString gridKey = QStringLiteral("showGrid");
const QString showLookAtKey = QStringLiteral("showLookAt");
const QString selectionBoxKey = QStringLiteral("showSelectionBox");
const QString iconGizmoKey = QStringLiteral("showIconGizmo");
const QString cameraFrustumKey = QStringLiteral("showCameraFrustum");
@@ -189,6 +190,11 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState)
else
m_showGridAction->action()->setChecked(false);
if (sceneState.contains(showLookAtKey))
m_showLookAtAction->action()->setChecked(sceneState[showLookAtKey].toBool());
else
m_showLookAtAction->action()->setChecked(false);
if (sceneState.contains(selectionBoxKey))
m_showSelectionBoxAction->action()->setChecked(sceneState[selectionBoxKey].toBool());
else
@@ -1040,6 +1046,18 @@ void Edit3DView::createEdit3DActions()
nullptr,
QCoreApplication::translate("ShowGridAction", "Toggle the visibility of the helper grid."));
m_showLookAtAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_EDIT_SHOW_LOOKAT,
View3DActionType::ShowLookAt,
QCoreApplication::translate("ShowLookAtAction", "Show Look-at"),
QKeySequence(Qt::Key_L),
true,
true,
QIcon(),
this,
nullptr,
QCoreApplication::translate("ShowLookAtAction", "Toggle the visibility of the edit camera look-at indicator."));
m_showSelectionBoxAction = std::make_unique<Edit3DAction>(
QmlDesigner::Constants::EDIT3D_EDIT_SHOW_SELECTION_BOX,
View3DActionType::ShowSelectionBox,
@@ -1343,6 +1361,7 @@ void Edit3DView::createEdit3DActions()
m_rightActions << m_resetAction.get();
m_visibilityToggleActions << m_showGridAction.get();
m_visibilityToggleActions << m_showLookAtAction.get();
m_visibilityToggleActions << m_showSelectionBoxAction.get();
m_visibilityToggleActions << m_showIconGizmoAction.get();
m_visibilityToggleActions << m_showCameraFrustumAction.get();

View File

@@ -159,6 +159,7 @@ private:
std::unique_ptr<Edit3DAction> m_orientationModeAction;
std::unique_ptr<Edit3DAction> m_editLightAction;
std::unique_ptr<Edit3DAction> m_showGridAction;
std::unique_ptr<Edit3DAction> m_showLookAtAction;
std::unique_ptr<Edit3DAction> m_showSelectionBoxAction;
std::unique_ptr<Edit3DAction> m_showIconGizmoAction;
std::unique_ptr<Edit3DAction> m_showCameraFrustumAction;

View File

@@ -50,6 +50,7 @@ inline constexpr char EDIT3D_EDIT_CAMERA[] = "QmlDesigner.Editor3D.EditCameraTog
inline constexpr char EDIT3D_ORIENTATION[] = "QmlDesigner.Editor3D.OrientationToggle";
inline constexpr char EDIT3D_EDIT_LIGHT[] = "QmlDesigner.Editor3D.EditLightToggle";
inline constexpr char EDIT3D_EDIT_SHOW_GRID[] = "QmlDesigner.Editor3D.ToggleGrid";
inline constexpr char EDIT3D_EDIT_SHOW_LOOKAT[] = "QmlDesigner.Editor3D.ToggleLookAt";
inline constexpr char EDIT3D_EDIT_SELECT_BACKGROUND_COLOR[]
= "QmlDesigner.Editor3D.SelectBackgroundColor";
inline constexpr char EDIT3D_EDIT_SELECT_GRID_COLOR[] = "QmlDesigner.Editor3D.SelectGridColor";

View File

@@ -93,6 +93,7 @@ extend_qtc_executable(qml2puppet
linegeometry.cpp linegeometry.h
icongizmoimageprovider.cpp icongizmoimageprovider.h
boxgeometry.cpp boxgeometry.h
lookatgeometry.cpp lookatgeometry.h
)
find_package(Qt6 COMPONENTS Quick3DAssetImport QUIET)

View File

@@ -37,6 +37,7 @@
<file>mockfiles/qt6/LightIconGizmo.qml</file>
<file>mockfiles/qt6/LightModel.qml</file>
<file>mockfiles/qt6/Line3D.qml</file>
<file>mockfiles/qt6/LookAtGizmo.qml</file>
<file>mockfiles/qt6/MaterialNodeView.qml</file>
<file>mockfiles/qt6/ModelNode2DImageView.qml</file>
<file>mockfiles/qt6/ModelNode3DImageView.qml</file>

View File

@@ -29,7 +29,7 @@ Item {
readonly property real _keyPanAmount: 1.0
property bool ignoreToolState: false
property bool flyMode: viewRoot.flyMode
property bool hasMovedInFlyMode: false
property bool showCrosshairs: false
z: 10
anchors.fill: parent
@@ -175,14 +175,14 @@ Item {
function rotateCamera(angles)
{
if (flyMode)
hasMovedInFlyMode = true;
showCrosshairs = true;
cameraCtrl._lookAtPoint = _generalHelper.rotateCamera(camera, angles, _lookAtPoint);
}
function moveCamera(moveVec)
{
if (flyMode)
hasMovedInFlyMode = true;
showCrosshairs = true;
cameraCtrl._lookAtPoint = _generalHelper.moveCamera(camera, _lookAtPoint, moveVec);
}
@@ -248,11 +248,15 @@ Item {
cameraCtrl._dragging = false;
cameraCtrl.storeCameraState(0);
}
hasMovedInFlyMode = false;
showCrosshairs = false;
_generalHelper.stopAllCameraMoves();
_generalHelper.setCameraSpeedModifier(1.0);
}
on_LookAtPointChanged: {
viewRoot.overlayViews[splitId].lookAtGizmo.position = _lookAtPoint;
}
Connections {
target: _generalHelper
enabled: viewRoot.activeSplit === cameraCtrl.splitId
@@ -268,7 +272,7 @@ Item {
Image {
anchors.centerIn: parent
source: "qrc:///qtquickplugin/mockfiles/images/crosshair.png"
visible: cameraCtrl.hasMovedInFlyMode && viewRoot.activeSplit === cameraCtrl.splitId
visible: cameraCtrl.showCrosshairs && viewRoot.activeSplit === cameraCtrl.splitId
opacity: 0.7
}

View File

@@ -25,6 +25,7 @@ Item {
property bool showEditLight: false
property bool showGrid: true
property bool showLookAt: true
property bool showSelectionBox: true
property bool showIconGizmo: true
property bool showCameraFrustum: false
@@ -66,6 +67,7 @@ Item {
onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid);
onShowLookAtChanged: _generalHelper.storeToolState(sceneId, "showLookAt", showLookAt);
onSyncEnvBackgroundChanged: _generalHelper.storeToolState(sceneId, "syncEnvBackground", syncEnvBackground);
onShowSelectionBoxChanged: _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox);
onShowIconGizmoChanged: _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo);
@@ -304,6 +306,11 @@ Item {
else if (resetToDefault)
showGrid = true;
if ("showLookAt" in toolStates)
showLookAt = toolStates.showLookAt;
else if (resetToDefault)
showLookAt = true;
if ("syncEnvBackground" in toolStates) {
syncEnvBackground = toolStates.syncEnvBackground;
updateEnvBackground();
@@ -393,6 +400,7 @@ Item {
{
_generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
_generalHelper.storeToolState(sceneId, "showGrid", showGrid)
_generalHelper.storeToolState(sceneId, "showLookAt", showLookAt)
_generalHelper.storeToolState(sceneId, "syncEnvBackground", syncEnvBackground)
_generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox)
_generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo)

View File

@@ -0,0 +1,27 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick3D
import LookAtGeometry
Node {
id: root
property alias crossScale: lookAtGeometry.crossScale
property alias color: lookAtMat.baseColor
Model {
readonly property bool _edit3dLocked: true // Make this non-pickable
geometry: LookAtGeometry {
id: lookAtGeometry
}
materials: [
PrincipledMaterial {
id: lookAtMat
lighting: DefaultMaterial.NoLighting
cullMode: Material.NoCulling
}
]
}
}

View File

@@ -12,6 +12,7 @@ View3D {
property alias rotateGizmo: rotateGizmo
property alias scaleGizmo: scaleGizmo
property alias lightGizmo: lightGizmo
property alias lookAtGizmo: lookAtGizmo
property var viewRoot: null
property View3D editView: null
@@ -484,6 +485,12 @@ View3D {
position: pivotLine.startPos
}
AutoScaleHelper {
id: lookAtAutoScale
view3D: overlayView
position: lookAtGizmo.scenePosition
}
MoveGizmo {
id: moveGizmo
scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
@@ -619,5 +626,14 @@ View3D {
]
}
}
LookAtGizmo {
id: lookAtGizmo
color: "#ddd600"
scale: lookAtAutoScale.getScale(Qt.vector3d(10, 10, 10))
visible: overlayView.viewRoot.showLookAt
&& overlayView.isActive
&& !overlayView.viewRoot.cameraControls[viewRoot.activeSplit].showCrosshairs
}
}
}

View File

@@ -0,0 +1,62 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifdef QUICK3D_MODULE
#include "lookatgeometry.h"
namespace QmlDesigner::Internal {
LookAtGeometry::LookAtGeometry()
: GeometryBase()
, m_crossScale(1.f, 1.f, 1.f)
{
}
LookAtGeometry::~LookAtGeometry()
{
}
QVector3D LookAtGeometry::crossScale() const
{
return m_crossScale;
}
void LookAtGeometry::setCrossScale(const QVector3D &scale)
{
if (scale != m_crossScale) {
m_crossScale = scale;
emit crossScaleChanged();
updateGeometry();
}
}
void LookAtGeometry::doUpdateGeometry()
{
GeometryBase::doUpdateGeometry();
QByteArray vertexData;
vertexData.resize(6 * 3 * 4); // 6 vertices of 3 floats each 4 bytes
float *dataPtr = reinterpret_cast<float *>(vertexData.data());
auto addVertex = [&dataPtr](float x, float y, float z) {
dataPtr[0] = x;
dataPtr[1] = y;
dataPtr[2] = z;
dataPtr += 3;
};
addVertex(m_crossScale.x(), 0.f, 0.f);
addVertex(-m_crossScale.x(), 0.f, 0.f);
addVertex(0.f, m_crossScale.y(), 0.f);
addVertex(0.f, -m_crossScale.y(), 0.f);
addVertex(0.f, 0.f, m_crossScale.z());
addVertex(0.f, 0.f, -m_crossScale.z());
setVertexData(vertexData);
setBounds(-m_crossScale, m_crossScale);
}
} // namespace QmlDesigner::Internal
#endif // QUICK3D_MODULE

View File

@@ -0,0 +1,42 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#ifdef QUICK3D_MODULE
#include "geometrybase.h"
#include <QtGui/QVector3D>
namespace QmlDesigner::Internal {
class LookAtGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(QVector3D crossScale READ crossScale WRITE setCrossScale NOTIFY crossScaleChanged)
public:
LookAtGeometry();
~LookAtGeometry() override;
QVector3D crossScale() const;
public slots:
void setCrossScale(const QVector3D &pos);
signals:
void crossScaleChanged();
protected:
void doUpdateGeometry() override;
private:
QVector3D m_crossScale;
};
} // namespace QmlDesigner::Internal
QML_DECLARE_TYPE(QmlDesigner::Internal::LookAtGeometry)
#endif // QUICK3D_MODULE

View File

@@ -41,14 +41,15 @@
#include "changeauxiliarycommand.h"
#include "../editor3d/boxgeometry.h"
#include "../editor3d/generalhelper.h"
#include "../editor3d/mousearea3d.h"
#include "../editor3d/camerageometry.h"
#include "../editor3d/lightgeometry.h"
#include "../editor3d/generalhelper.h"
#include "../editor3d/gridgeometry.h"
#include "../editor3d/selectionboxgeometry.h"
#include "../editor3d/linegeometry.h"
#include "../editor3d/icongizmoimageprovider.h"
#include "../editor3d/lightgeometry.h"
#include "../editor3d/linegeometry.h"
#include "../editor3d/lookatgeometry.h"
#include "../editor3d/mousearea3d.h"
#include "../editor3d/selectionboxgeometry.h"
#include <private/qquickdesignersupport_p.h>
#include <qmlprivategate.h>
@@ -526,6 +527,7 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
qmlRegisterType<QmlDesigner::Internal::LineGeometry>("LineGeometry", 1, 0, "LineGeometry");
qmlRegisterType<QmlDesigner::Internal::BoxGeometry>("BoxGeometry", 1, 0, "BoxGeometry");
qmlRegisterType<QmlDesigner::Internal::LookAtGeometry>("LookAtGeometry", 1, 0, "LookAtGeometry");
auto helper = new QmlDesigner::Internal::GeneralHelper();
QObject::connect(helper, &QmlDesigner::Internal::GeneralHelper::toolStateChanged,
@@ -2533,6 +2535,9 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
case View3DActionType::ShowGrid:
updatedToolState.insert("showGrid", command.isEnabled());
break;
case View3DActionType::ShowLookAt:
updatedToolState.insert("showLookAt", command.isEnabled());
break;
case View3DActionType::ShowSelectionBox:
updatedToolState.insert("showSelectionBox", command.isEnabled());
break;