forked from qt-creator/qt-creator
QmlDesigner: Add fly mode for 3D view
You can now activate fly mode in 3D view by pressing right mouse button. In fly mode, cursor is hidden and mouse controls edit camera rotation directly, and WASDQE can be used to move the camera around. Fixes: QDS-12030 Change-Id: I52550502632af19de36a1557d9aac84ff3cb18cc Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
@@ -49,7 +49,11 @@ enum class View3DActionType {
|
|||||||
SetBakeLightsView3D,
|
SetBakeLightsView3D,
|
||||||
SplitViewToggle,
|
SplitViewToggle,
|
||||||
MaterialOverride,
|
MaterialOverride,
|
||||||
ShowWireframe
|
ShowWireframe,
|
||||||
|
FlyModeToggle,
|
||||||
|
EditCameraRotation,
|
||||||
|
EditCameraMove,
|
||||||
|
EditCameraStopAllMoves
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr bool isNanotraceEnabled()
|
constexpr bool isNanotraceEnabled()
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
#include <qmldesignerplugin.h>
|
#include <qmldesignerplugin.h>
|
||||||
#include <qmldesignerconstants.h>
|
#include <qmldesignerconstants.h>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDateTime>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QQuickWidget>
|
#include <QQuickWidget>
|
||||||
@@ -77,10 +79,67 @@ QWidget *Edit3DCanvas::busyIndicator() const
|
|||||||
return m_busyIndicator;
|
return m_busyIndicator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Edit3DCanvas::setFlyMode(bool enabled, const QPoint &pos)
|
||||||
|
{
|
||||||
|
if (m_flyMode == enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_flyMode = enabled;
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
m_flyModeStartTime = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
|
||||||
|
// Mouse cursor will be hidden in the flight mode
|
||||||
|
QApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
|
||||||
|
|
||||||
|
m_flyModeStartCursorPos = pos;
|
||||||
|
m_flyModeFirstUpdate = true;
|
||||||
|
|
||||||
|
// Hide cursor on the middle of the active split to make the wheel work during flight mode.
|
||||||
|
// We can't rely on current activeSplit value, as mouse press to enter flight mode can change the
|
||||||
|
// active split, so hide the cursor based on its current location.
|
||||||
|
QPoint center = mapToGlobal(QPoint(width() / 2, height() / 2));
|
||||||
|
if (m_parent->view()->isSplitView()) {
|
||||||
|
if (pos.x() <= center.x()) {
|
||||||
|
if (pos.y() <= center.y())
|
||||||
|
m_hiddenCursorPos = mapToGlobal(QPoint(width() / 4, height() / 4));
|
||||||
|
else
|
||||||
|
m_hiddenCursorPos = mapToGlobal(QPoint(width() / 4, (height() / 4) * 3));
|
||||||
|
} else {
|
||||||
|
if (pos.y() <= center.y())
|
||||||
|
m_hiddenCursorPos = mapToGlobal(QPoint((width() / 4) * 3, height() / 4));
|
||||||
|
else
|
||||||
|
m_hiddenCursorPos = mapToGlobal(QPoint((width() / 4) * 3, (height() / 4) * 3));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_hiddenCursorPos = center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCursor::setPos(m_hiddenCursorPos);
|
||||||
|
} else {
|
||||||
|
QCursor::setPos(m_flyModeStartCursorPos);
|
||||||
|
|
||||||
|
if (QApplication::overrideCursor())
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
|
||||||
|
if (m_contextMenuPending && (QDateTime::currentMSecsSinceEpoch() - m_flyModeStartTime) < 500)
|
||||||
|
m_parent->view()->showContextMenu();
|
||||||
|
|
||||||
|
m_contextMenuPending = false;
|
||||||
|
m_flyModeStartTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_parent->view()->setFlyMode(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
void Edit3DCanvas::mousePressEvent(QMouseEvent *e)
|
void Edit3DCanvas::mousePressEvent(QMouseEvent *e)
|
||||||
{
|
{
|
||||||
if (e->button() == Qt::RightButton && e->modifiers() == Qt::NoModifier)
|
m_contextMenuPending = false;
|
||||||
|
if (!m_flyMode && e->modifiers() == Qt::NoModifier && e->buttons() == Qt::RightButton) {
|
||||||
|
setFlyMode(true, e->globalPos());
|
||||||
m_parent->view()->startContextMenu(e->pos());
|
m_parent->view()->startContextMenu(e->pos());
|
||||||
|
m_contextMenuPending = true;
|
||||||
|
}
|
||||||
|
|
||||||
m_parent->view()->sendInputEvent(e);
|
m_parent->view()->sendInputEvent(e);
|
||||||
QWidget::mousePressEvent(e);
|
QWidget::mousePressEvent(e);
|
||||||
@@ -88,6 +147,8 @@ void Edit3DCanvas::mousePressEvent(QMouseEvent *e)
|
|||||||
|
|
||||||
void Edit3DCanvas::mouseReleaseEvent(QMouseEvent *e)
|
void Edit3DCanvas::mouseReleaseEvent(QMouseEvent *e)
|
||||||
{
|
{
|
||||||
|
if ((e->buttons() & Qt::RightButton) == Qt::NoButton)
|
||||||
|
setFlyMode(false);
|
||||||
m_parent->view()->sendInputEvent(e);
|
m_parent->view()->sendInputEvent(e);
|
||||||
QWidget::mouseReleaseEvent(e);
|
QWidget::mouseReleaseEvent(e);
|
||||||
}
|
}
|
||||||
@@ -100,8 +161,29 @@ void Edit3DCanvas::mouseDoubleClickEvent(QMouseEvent *e)
|
|||||||
|
|
||||||
void Edit3DCanvas::mouseMoveEvent(QMouseEvent *e)
|
void Edit3DCanvas::mouseMoveEvent(QMouseEvent *e)
|
||||||
{
|
{
|
||||||
m_parent->view()->sendInputEvent(e);
|
if (!m_flyMode)
|
||||||
|
m_parent->view()->sendInputEvent(e);
|
||||||
|
|
||||||
QWidget::mouseMoveEvent(e);
|
QWidget::mouseMoveEvent(e);
|
||||||
|
|
||||||
|
if (m_flyMode && e->globalPos() != m_hiddenCursorPos) {
|
||||||
|
if (!m_flyModeFirstUpdate) {
|
||||||
|
// We notify explicit camera rotation need for puppet rather than rely in mouse events,
|
||||||
|
// as mouse isn't grabbed on puppet side and can't handle fast movements that go out of
|
||||||
|
// edit camera mouse area. This also simplifies split view handling.
|
||||||
|
QPointF diff = m_hiddenCursorPos - e->globalPos();
|
||||||
|
if (e->buttons() == (Qt::LeftButton | Qt::RightButton)) {
|
||||||
|
m_parent->view()->emitView3DAction(View3DActionType::EditCameraMove,
|
||||||
|
QVector3D{float(-diff.x()), float(-diff.y()), 0.f});
|
||||||
|
} else {
|
||||||
|
m_parent->view()->emitView3DAction(View3DActionType::EditCameraRotation, diff / 6.);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Skip first move to avoid undesirable jump occasionally when initiating flight mode
|
||||||
|
m_flyModeFirstUpdate = false;
|
||||||
|
}
|
||||||
|
QCursor::setPos(m_hiddenCursorPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Edit3DCanvas::wheelEvent(QWheelEvent *e)
|
void Edit3DCanvas::wheelEvent(QWheelEvent *e)
|
||||||
@@ -112,13 +194,15 @@ void Edit3DCanvas::wheelEvent(QWheelEvent *e)
|
|||||||
|
|
||||||
void Edit3DCanvas::keyPressEvent(QKeyEvent *e)
|
void Edit3DCanvas::keyPressEvent(QKeyEvent *e)
|
||||||
{
|
{
|
||||||
m_parent->view()->sendInputEvent(e);
|
if (!e->isAutoRepeat())
|
||||||
|
m_parent->view()->sendInputEvent(e);
|
||||||
QWidget::keyPressEvent(e);
|
QWidget::keyPressEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Edit3DCanvas::keyReleaseEvent(QKeyEvent *e)
|
void Edit3DCanvas::keyReleaseEvent(QKeyEvent *e)
|
||||||
{
|
{
|
||||||
m_parent->view()->sendInputEvent(e);
|
if (!e->isAutoRepeat())
|
||||||
|
m_parent->view()->sendInputEvent(e);
|
||||||
QWidget::keyReleaseEvent(e);
|
QWidget::keyReleaseEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +230,10 @@ void Edit3DCanvas::focusOutEvent(QFocusEvent *focusEvent)
|
|||||||
{
|
{
|
||||||
QmlDesignerPlugin::emitUsageStatisticsTime(Constants::EVENT_3DEDITOR_TIME,
|
QmlDesignerPlugin::emitUsageStatisticsTime(Constants::EVENT_3DEDITOR_TIME,
|
||||||
m_usageTimer.elapsed());
|
m_usageTimer.elapsed());
|
||||||
|
|
||||||
|
setFlyMode(false);
|
||||||
|
m_parent->view()->emitView3DAction(View3DActionType::EditCameraStopAllMoves, {});
|
||||||
|
|
||||||
QWidget::focusOutEvent(focusEvent);
|
QWidget::focusOutEvent(focusEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtWidgets/qwidget.h>
|
#include <QEvent>
|
||||||
#include <QtGui/qimage.h>
|
#include <QElapsedTimer>
|
||||||
#include <QtGui/qevent.h>
|
#include <QImage>
|
||||||
#include <QtCore/qelapsedtimer.h>
|
#include <QPoint>
|
||||||
#include <QtCore/qpointer.h>
|
#include <QPointer>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
@@ -25,6 +26,8 @@ public:
|
|||||||
QImage renderImage() const;
|
QImage renderImage() const;
|
||||||
void setOpacity(qreal opacity);
|
void setOpacity(qreal opacity);
|
||||||
QWidget *busyIndicator() const;
|
QWidget *busyIndicator() const;
|
||||||
|
void setFlyMode(bool enabled, const QPoint &pos = {});
|
||||||
|
bool isFlyMode() const { return m_flyMode; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
@@ -50,6 +53,12 @@ private:
|
|||||||
QElapsedTimer m_usageTimer;
|
QElapsedTimer m_usageTimer;
|
||||||
qreal m_opacity = 1.0;
|
qreal m_opacity = 1.0;
|
||||||
QWidget *m_busyIndicator = nullptr;
|
QWidget *m_busyIndicator = nullptr;
|
||||||
|
bool m_flyMode = false;
|
||||||
|
QPoint m_flyModeStartCursorPos;
|
||||||
|
QPoint m_hiddenCursorPos;
|
||||||
|
qint64 m_flyModeStartTime = 0;
|
||||||
|
bool m_flyModeFirstUpdate = false;
|
||||||
|
bool m_contextMenuPending = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -449,11 +449,13 @@ void Edit3DView::customNotification([[maybe_unused]] const AbstractView *view,
|
|||||||
void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos3d)
|
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
|
m_contextMenuPos3D = pos3d;
|
||||||
// while the context-menu is shown doesn't select the item.
|
if (m_edit3DWidget->canvas()->isFlyMode()) {
|
||||||
if (modelNode.isValid() && !modelNode.isSelected())
|
m_contextMenuPendingNode = modelNode;
|
||||||
setSelectedModelNode(modelNode);
|
} else {
|
||||||
m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode, pos3d);
|
m_nodeAtPosReqType = NodeAtPosReqType::None;
|
||||||
|
showContextMenu();
|
||||||
|
}
|
||||||
} else if (m_nodeAtPosReqType == NodeAtPosReqType::ComponentDrop) {
|
} else if (m_nodeAtPosReqType == NodeAtPosReqType::ComponentDrop) {
|
||||||
ModelNode createdNode;
|
ModelNode createdNode;
|
||||||
executeInTransaction(__FUNCTION__, [&] {
|
executeInTransaction(__FUNCTION__, [&] {
|
||||||
@@ -679,6 +681,49 @@ QPoint Edit3DView::resolveToolbarPopupPos(Edit3DAction *action) const
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Edit3DView::showContextMenu()
|
||||||
|
{
|
||||||
|
// If request for context menu is still pending, skip for now
|
||||||
|
if (m_nodeAtPosReqType == NodeAtPosReqType::ContextMenu)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_contextMenuPendingNode.isValid() && !m_contextMenuPendingNode.isSelected())
|
||||||
|
setSelectedModelNode(m_contextMenuPendingNode);
|
||||||
|
m_edit3DWidget->showContextMenu(m_contextMenuPosMouse, m_contextMenuPendingNode, m_contextMenuPos3D);
|
||||||
|
m_contextMenuPendingNode = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Edit3DView::setFlyMode(bool enabled)
|
||||||
|
{
|
||||||
|
emitView3DAction(View3DActionType::FlyModeToggle, enabled);
|
||||||
|
|
||||||
|
// Disable any actions with conflicting hotkeys
|
||||||
|
if (enabled) {
|
||||||
|
m_flyModeDisabledActions.clear();
|
||||||
|
const QList<QKeySequence> controlKeys = { Qt::Key_W, Qt::Key_A, Qt::Key_S,
|
||||||
|
Qt::Key_D, Qt::Key_Q, Qt::Key_E,
|
||||||
|
Qt::Key_Up, Qt::Key_Down, Qt::Key_Left,
|
||||||
|
Qt::Key_Right, Qt::Key_PageDown, Qt::Key_PageUp};
|
||||||
|
for (auto i = m_edit3DActions.cbegin(), end = m_edit3DActions.cend(); i != end; ++i) {
|
||||||
|
for (const QKeySequence &controlKey : controlKeys) {
|
||||||
|
if (Core::Command *cmd = m_edit3DWidget->actionToCommandHash().value(i.value()->action())) {
|
||||||
|
if (cmd->keySequence().matches(controlKey) == QKeySequence::ExactMatch) {
|
||||||
|
if (i.value()->action()->isEnabled()) {
|
||||||
|
m_flyModeDisabledActions.append(i.value());
|
||||||
|
i.value()->action()->setEnabled(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (Edit3DAction *action : std::as_const(m_flyModeDisabledActions))
|
||||||
|
action->action()->setEnabled(true);
|
||||||
|
m_flyModeDisabledActions.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Edit3DView::syncSnapAuxPropsToSettings()
|
void Edit3DView::syncSnapAuxPropsToSettings()
|
||||||
{
|
{
|
||||||
if (!model())
|
if (!model())
|
||||||
@@ -722,6 +767,11 @@ int Edit3DView::activeSplit() const
|
|||||||
return m_activeSplit;
|
return m_activeSplit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Edit3DView::isSplitView() const
|
||||||
|
{
|
||||||
|
return m_splitViewAction->action()->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
void Edit3DView::createEdit3DActions()
|
void Edit3DView::createEdit3DActions()
|
||||||
{
|
{
|
||||||
m_selectionModeAction = std::make_unique<Edit3DAction>(
|
m_selectionModeAction = std::make_unique<Edit3DAction>(
|
||||||
@@ -850,7 +900,7 @@ void Edit3DView::createEdit3DActions()
|
|||||||
QmlDesigner::Constants::EDIT3D_EDIT_SHOW_SELECTION_BOX,
|
QmlDesigner::Constants::EDIT3D_EDIT_SHOW_SELECTION_BOX,
|
||||||
View3DActionType::ShowSelectionBox,
|
View3DActionType::ShowSelectionBox,
|
||||||
QCoreApplication::translate("ShowSelectionBoxAction", "Show Selection Boxes"),
|
QCoreApplication::translate("ShowSelectionBoxAction", "Show Selection Boxes"),
|
||||||
QKeySequence(Qt::Key_S),
|
QKeySequence(Qt::Key_B),
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
QIcon(),
|
QIcon(),
|
||||||
@@ -1189,7 +1239,7 @@ void Edit3DView::addQuick3DImport()
|
|||||||
// context menu is created when nodeAtPosReady() is received from puppet
|
// context menu is created when nodeAtPosReady() is received from puppet
|
||||||
void Edit3DView::startContextMenu(const QPoint &pos)
|
void Edit3DView::startContextMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
m_contextMenuPos = pos;
|
m_contextMenuPosMouse = pos;
|
||||||
m_nodeAtPosReqType = NodeAtPosReqType::ContextMenu;
|
m_nodeAtPosReqType = NodeAtPosReqType::ContextMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QVector3D>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QAction;
|
class QAction;
|
||||||
@@ -73,6 +74,7 @@ public:
|
|||||||
|
|
||||||
void addQuick3DImport();
|
void addQuick3DImport();
|
||||||
void startContextMenu(const QPoint &pos);
|
void startContextMenu(const QPoint &pos);
|
||||||
|
void showContextMenu();
|
||||||
void dropMaterial(const ModelNode &matNode, const QPointF &pos);
|
void dropMaterial(const ModelNode &matNode, const QPointF &pos);
|
||||||
void dropBundleMaterial(const QPointF &pos);
|
void dropBundleMaterial(const QPointF &pos);
|
||||||
void dropBundleEffect(const QPointF &pos);
|
void dropBundleEffect(const QPointF &pos);
|
||||||
@@ -88,6 +90,8 @@ public:
|
|||||||
void setSplitToolState(int splitIndex, const SplitToolState &state);
|
void setSplitToolState(int splitIndex, const SplitToolState &state);
|
||||||
|
|
||||||
int activeSplit() const;
|
int activeSplit() const;
|
||||||
|
bool isSplitView() const;
|
||||||
|
void setFlyMode(bool enabled);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onEntriesChanged();
|
void onEntriesChanged();
|
||||||
@@ -167,7 +171,8 @@ private:
|
|||||||
ItemLibraryEntry m_droppedEntry;
|
ItemLibraryEntry m_droppedEntry;
|
||||||
QString m_droppedFile;
|
QString m_droppedFile;
|
||||||
NodeAtPosReqType m_nodeAtPosReqType;
|
NodeAtPosReqType m_nodeAtPosReqType;
|
||||||
QPoint m_contextMenuPos;
|
QPoint m_contextMenuPosMouse;
|
||||||
|
QVector3D m_contextMenuPos3D;
|
||||||
QTimer m_compressionTimer;
|
QTimer m_compressionTimer;
|
||||||
QPointer<BakeLights> m_bakeLights;
|
QPointer<BakeLights> m_bakeLights;
|
||||||
bool m_isBakingLightsSupported = false;
|
bool m_isBakingLightsSupported = false;
|
||||||
@@ -175,6 +180,8 @@ private:
|
|||||||
int m_activeSplit = 0;
|
int m_activeSplit = 0;
|
||||||
|
|
||||||
QList<SplitToolState> m_splitToolStates;
|
QList<SplitToolState> m_splitToolStates;
|
||||||
|
QList<Edit3DAction *> m_flyModeDisabledActions;
|
||||||
|
ModelNode m_contextMenuPendingNode;
|
||||||
|
|
||||||
friend class Edit3DAction;
|
friend class Edit3DAction;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view)
|
|||||||
// Register action as creator command to make it configurable
|
// Register action as creator command to make it configurable
|
||||||
Core::Command *command = Core::ActionManager::registerAction(
|
Core::Command *command = Core::ActionManager::registerAction(
|
||||||
a, action->menuId().constData(), context);
|
a, action->menuId().constData(), context);
|
||||||
|
m_actionToCommandHash.insert(a, command);
|
||||||
command->setDefaultKeySequence(a->shortcut());
|
command->setDefaultKeySequence(a->shortcut());
|
||||||
if (proxyGroup)
|
if (proxyGroup)
|
||||||
proxyGroup->addAction(command->action());
|
proxyGroup->addAction(command->action());
|
||||||
|
|||||||
@@ -12,6 +12,10 @@
|
|||||||
#include <itemlibraryentry.h>
|
#include <itemlibraryentry.h>
|
||||||
#include <modelnode.h>
|
#include <modelnode.h>
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class Command;
|
||||||
|
}
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class Edit3DView;
|
class Edit3DView;
|
||||||
@@ -52,6 +56,8 @@ public:
|
|||||||
void showContextMenu(const QPoint &pos, const ModelNode &modelNode, const QVector3D &pos3d);
|
void showContextMenu(const QPoint &pos, const ModelNode &modelNode, const QVector3D &pos3d);
|
||||||
void updateCreateSubMenu(const QList<ItemLibraryDetails> &entriesList);
|
void updateCreateSubMenu(const QList<ItemLibraryDetails> &entriesList);
|
||||||
|
|
||||||
|
const QHash<QAction *, Core::Command *> &actionToCommandHash() { return m_actionToCommandHash; }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onCreateAction(QAction *action);
|
void onCreateAction(QAction *action);
|
||||||
void onMatOverrideAction(QAction *action);
|
void onMatOverrideAction(QAction *action);
|
||||||
@@ -100,6 +106,7 @@ private:
|
|||||||
QVector3D m_contextMenuPos3d;
|
QVector3D m_contextMenuPos3d;
|
||||||
QHash<QString, ItemLibraryEntry> m_nameToEntry;
|
QHash<QString, ItemLibraryEntry> m_nameToEntry;
|
||||||
ItemLibraryEntry m_draggedEntry;
|
ItemLibraryEntry m_draggedEntry;
|
||||||
|
QHash<QAction *, Core::Command *> m_actionToCommandHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ Item {
|
|||||||
readonly property vector3d _defaultCameraPosition: Qt.vector3d(0, 600, 600)
|
readonly property vector3d _defaultCameraPosition: Qt.vector3d(0, 600, 600)
|
||||||
readonly property vector3d _defaultCameraRotation: Qt.vector3d(-45, 0, 0)
|
readonly property vector3d _defaultCameraRotation: Qt.vector3d(-45, 0, 0)
|
||||||
readonly property real _defaultCameraLookAtDistance: _defaultCameraPosition.length()
|
readonly property real _defaultCameraLookAtDistance: _defaultCameraPosition.length()
|
||||||
readonly property real _keyPanAmount: 5
|
readonly property real _keyPanAmount: 10
|
||||||
property bool ignoreToolState: false
|
property bool ignoreToolState: false
|
||||||
|
property bool flyMode: viewRoot.flyMode
|
||||||
|
|
||||||
z: 10
|
z: 10
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -150,6 +151,58 @@ Item {
|
|||||||
_lookAtPoint, _zoomFactor, true);
|
_lookAtPoint, _zoomFactor, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rotateCamera(angles)
|
||||||
|
{
|
||||||
|
cameraCtrl._lookAtPoint = _generalHelper.rotateCamera(camera, angles, _lookAtPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveCamera(moveVec)
|
||||||
|
{
|
||||||
|
cameraCtrl._lookAtPoint = _generalHelper.moveCamera(camera, _lookAtPoint, _zoomFactor,
|
||||||
|
moveVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMoveVectorForKey(key) {
|
||||||
|
if (flyMode) {
|
||||||
|
switch (key) {
|
||||||
|
case Qt.Key_A:
|
||||||
|
case Qt.Key_Left:
|
||||||
|
return Qt.vector3d(_keyPanAmount, 0, 0);
|
||||||
|
case Qt.Key_D:
|
||||||
|
case Qt.Key_Right:
|
||||||
|
return Qt.vector3d(-_keyPanAmount, 0, 0);
|
||||||
|
case Qt.Key_E:
|
||||||
|
case Qt.Key_PageUp:
|
||||||
|
return Qt.vector3d(0, _keyPanAmount, 0);
|
||||||
|
case Qt.Key_Q:
|
||||||
|
case Qt.Key_PageDown:
|
||||||
|
return Qt.vector3d(0, -_keyPanAmount, 0);
|
||||||
|
case Qt.Key_W:
|
||||||
|
case Qt.Key_Up:
|
||||||
|
return Qt.vector3d(0, 0, _keyPanAmount);
|
||||||
|
case Qt.Key_S:
|
||||||
|
case Qt.Key_Down:
|
||||||
|
return Qt.vector3d(0, 0, -_keyPanAmount);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (key) {
|
||||||
|
case Qt.Key_Left:
|
||||||
|
return Qt.vector3d(_keyPanAmount, 0, 0);
|
||||||
|
case Qt.Key_Right:
|
||||||
|
return Qt.vector3d(-_keyPanAmount, 0, 0);
|
||||||
|
case Qt.Key_Up:
|
||||||
|
return Qt.vector3d(0, _keyPanAmount, 0);
|
||||||
|
case Qt.Key_Down:
|
||||||
|
return Qt.vector3d(0, -_keyPanAmount, 0);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Qt.vector3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
onCameraChanged: {
|
onCameraChanged: {
|
||||||
if (camera && _prevCamera) {
|
if (camera && _prevCamera) {
|
||||||
// Reset zoom on previous camera to ensure it's properties are good to copy to new cam
|
// Reset zoom on previous camera to ensure it's properties are good to copy to new cam
|
||||||
@@ -166,6 +219,25 @@ Item {
|
|||||||
_prevCamera = camera;
|
_prevCamera = camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFlyModeChanged: {
|
||||||
|
if (cameraCtrl._dragging) {
|
||||||
|
cameraCtrl._dragging = false;
|
||||||
|
cameraCtrl.storeCameraState(0);
|
||||||
|
}
|
||||||
|
_generalHelper.stopAllCameraMoves()
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: _generalHelper
|
||||||
|
enabled: viewRoot.activeSplit === cameraCtrl.splitId
|
||||||
|
function onRequestCameraMove(camera, moveVec) {
|
||||||
|
if (camera === cameraCtrl.camera) {
|
||||||
|
cameraCtrl.moveCamera(moveVec);
|
||||||
|
_generalHelper.requestRender();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseHandler
|
id: mouseHandler
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||||
@@ -190,6 +262,8 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPressed: (mouse) => {
|
onPressed: (mouse) => {
|
||||||
|
if (cameraCtrl.flyMode)
|
||||||
|
return;
|
||||||
viewRoot.activeSplit = cameraCtrl.splitId
|
viewRoot.activeSplit = cameraCtrl.splitId
|
||||||
if (cameraCtrl.camera && mouse.modifiers === Qt.AltModifier) {
|
if (cameraCtrl.camera && mouse.modifiers === Qt.AltModifier) {
|
||||||
cameraCtrl._dragging = true;
|
cameraCtrl._dragging = true;
|
||||||
@@ -215,6 +289,8 @@ Item {
|
|||||||
onCanceled: handleRelease()
|
onCanceled: handleRelease()
|
||||||
|
|
||||||
onWheel: (wheel) => {
|
onWheel: (wheel) => {
|
||||||
|
if (cameraCtrl.flyMode && cameraCtrl.splitId !== viewRoot.activeSplit)
|
||||||
|
return;
|
||||||
viewRoot.activeSplit = cameraCtrl.splitId
|
viewRoot.activeSplit = cameraCtrl.splitId
|
||||||
if (cameraCtrl.camera) {
|
if (cameraCtrl.camera) {
|
||||||
// Empirically determined divisor for nice zoom
|
// Empirically determined divisor for nice zoom
|
||||||
@@ -225,33 +301,13 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Keys.onPressed: (event) => {
|
Keys.onPressed: (event) => {
|
||||||
var pressPoint = Qt.vector3d(view3d.width / 2, view3d.height / 2, 0);
|
event.accepted = true;
|
||||||
var currentPoint;
|
_generalHelper.startCameraMove(cameraCtrl.camera, cameraCtrl.getMoveVectorForKey(event.key));
|
||||||
|
}
|
||||||
|
|
||||||
switch (event.key) {
|
Keys.onReleased: (event) => {
|
||||||
case Qt.Key_Left:
|
event.accepted = true;
|
||||||
currentPoint = pressPoint.plus(Qt.vector3d(_keyPanAmount, 0, 0));
|
_generalHelper.stopCameraMove(cameraCtrl.getMoveVectorForKey(event.key));
|
||||||
break;
|
|
||||||
case Qt.Key_Right:
|
|
||||||
currentPoint = pressPoint.plus(Qt.vector3d(-_keyPanAmount, 0, 0));
|
|
||||||
break;
|
|
||||||
case Qt.Key_Up:
|
|
||||||
currentPoint = pressPoint.plus(Qt.vector3d(0, _keyPanAmount, 0));
|
|
||||||
break;
|
|
||||||
case Qt.Key_Down:
|
|
||||||
currentPoint = pressPoint.plus(Qt.vector3d(0, -_keyPanAmount, 0));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentPoint) {
|
|
||||||
_lookAtPoint = _generalHelper.panCamera(
|
|
||||||
camera, cameraCtrl.camera.sceneTransform,
|
|
||||||
cameraCtrl.camera.position, _lookAtPoint,
|
|
||||||
pressPoint, currentPoint, _zoomFactor);
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OriginGizmo {
|
OriginGizmo {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ Item {
|
|||||||
property color gridColor: "#cccccc"
|
property color gridColor: "#cccccc"
|
||||||
property bool syncEnvBackground: false
|
property bool syncEnvBackground: false
|
||||||
property bool splitView: false
|
property bool splitView: false
|
||||||
|
property bool flyMode: false
|
||||||
|
|
||||||
enum SelectionMode { Item, Group }
|
enum SelectionMode { Item, Group }
|
||||||
enum TransformMode { Move, Rotate, Scale }
|
enum TransformMode { Move, Rotate, Scale }
|
||||||
@@ -129,6 +130,7 @@ Item {
|
|||||||
|
|
||||||
selectionBoxCount = 0;
|
selectionBoxCount = 0;
|
||||||
editViewsChanged();
|
editViewsChanged();
|
||||||
|
cameraControls[activeSplit].forceActiveFocus();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -351,6 +353,11 @@ Item {
|
|||||||
cameraControls[i].restoreDefaultState();
|
cameraControls[i].restoreDefaultState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("flyMode" in toolStates)
|
||||||
|
flyMode = toolStates.flyMode;
|
||||||
|
else if (resetToDefault)
|
||||||
|
flyMode = false;
|
||||||
|
|
||||||
if ("splitView" in toolStates)
|
if ("splitView" in toolStates)
|
||||||
splitView = toolStates.splitView;
|
splitView = toolStates.splitView;
|
||||||
else if (resetToDefault)
|
else if (resetToDefault)
|
||||||
@@ -598,6 +605,16 @@ Item {
|
|||||||
return activeOverlayView.gizmoAt(splitPoint.x, splitPoint.y);
|
return activeOverlayView.gizmoAt(splitPoint.x, splitPoint.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rotateEditCamera(angles)
|
||||||
|
{
|
||||||
|
cameraControls[activeSplit].rotateCamera(angles);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveEditCamera(amounts)
|
||||||
|
{
|
||||||
|
cameraControls[activeSplit].moveCamera(amounts);
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
createEditViews();
|
createEditViews();
|
||||||
selectObjects([]);
|
selectObjects([]);
|
||||||
@@ -822,6 +839,9 @@ Item {
|
|||||||
property bool initialMoveBlock: false
|
property bool initialMoveBlock: false
|
||||||
|
|
||||||
onPressed: (mouse) => {
|
onPressed: (mouse) => {
|
||||||
|
if (viewRoot.flyMode)
|
||||||
|
return;
|
||||||
|
|
||||||
viewRoot.updateActiveSplit(mouse.x, mouse.y);
|
viewRoot.updateActiveSplit(mouse.x, mouse.y);
|
||||||
|
|
||||||
let splitPoint = viewRoot.resolveSplitPoint(mouse.x, mouse.y);
|
let splitPoint = viewRoot.resolveSplitPoint(mouse.x, mouse.y);
|
||||||
|
|||||||
@@ -66,6 +66,11 @@ GeneralHelper::GeneralHelper()
|
|||||||
QList<QColor> defaultBg;
|
QList<QColor> defaultBg;
|
||||||
defaultBg.append(QColor());
|
defaultBg.append(QColor());
|
||||||
m_bgColor = QVariant::fromValue(defaultBg);
|
m_bgColor = QVariant::fromValue(defaultBg);
|
||||||
|
|
||||||
|
m_camMoveData.timer.setInterval(16);
|
||||||
|
QObject::connect(&m_camMoveData.timer, &QTimer::timeout, this, [this]() {
|
||||||
|
emit requestCameraMove(m_camMoveData.camera, m_camMoveData.combinedMoveVector);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralHelper::requestOverlayUpdate()
|
void GeneralHelper::requestOverlayUpdate()
|
||||||
@@ -142,14 +147,111 @@ QVector3D GeneralHelper::panCamera(QQuick3DCamera *camera, const QMatrix4x4 star
|
|||||||
const float *dataPtr(startTransform.data());
|
const float *dataPtr(startTransform.data());
|
||||||
const QVector3D xAxis = QVector3D(dataPtr[0], dataPtr[1], dataPtr[2]).normalized();
|
const QVector3D xAxis = QVector3D(dataPtr[0], dataPtr[1], dataPtr[2]).normalized();
|
||||||
const QVector3D yAxis = QVector3D(dataPtr[4], dataPtr[5], dataPtr[6]).normalized();
|
const QVector3D yAxis = QVector3D(dataPtr[4], dataPtr[5], dataPtr[6]).normalized();
|
||||||
const QVector3D xDelta = -1.f * xAxis * dragVector.x();
|
const QVector3D xDelta = xAxis * dragVector.x();
|
||||||
const QVector3D yDelta = yAxis * dragVector.y();
|
const QVector3D yDelta = yAxis * dragVector.y();
|
||||||
const QVector3D delta = (xDelta + yDelta) * zoomFactor;
|
const QVector3D delta = (yDelta - xDelta) * zoomFactor;
|
||||||
|
|
||||||
camera->setPosition(startPosition + delta);
|
camera->setPosition(startPosition + delta);
|
||||||
return startLookAt + delta;
|
return startLookAt + delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Moves camera in 3D space and returns new look-at point
|
||||||
|
QVector3D GeneralHelper::moveCamera(QQuick3DCamera *camera, const QVector3D &startLookAt,
|
||||||
|
float zoomFactor, const QVector3D &moveVector)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (moveVector.length() < 0.001f)
|
||||||
|
return startLookAt;
|
||||||
|
|
||||||
|
QMatrix4x4 m = camera->sceneTransform(); // Works because edit camera is at scene root
|
||||||
|
const float *dataPtr(m.data());
|
||||||
|
const QVector3D xAxis = QVector3D(dataPtr[0], dataPtr[1], dataPtr[2]).normalized();
|
||||||
|
const QVector3D yAxis = QVector3D(dataPtr[4], dataPtr[5], dataPtr[6]).normalized();
|
||||||
|
const QVector3D zAxis = QVector3D(dataPtr[8], dataPtr[9], dataPtr[10]).normalized();
|
||||||
|
const QVector3D xDelta = xAxis * moveVector.x();
|
||||||
|
const QVector3D yDelta = yAxis * moveVector.y();
|
||||||
|
const QVector3D zDelta = zAxis * moveVector.z();
|
||||||
|
const QVector3D delta = (yDelta - xDelta - zDelta) * zoomFactor;
|
||||||
|
|
||||||
|
camera->setPosition(camera->position() + delta);
|
||||||
|
|
||||||
|
return startLookAt + delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotates camera and returns the new look-at point
|
||||||
|
QVector3D GeneralHelper::rotateCamera(QQuick3DCamera *camera, const QPointF &angles,
|
||||||
|
const QVector3D &lookAtPoint)
|
||||||
|
{
|
||||||
|
float lookAtDist = (camera->scenePosition() - lookAtPoint).length();
|
||||||
|
|
||||||
|
if (qAbs(angles.y()) > 0.001f)
|
||||||
|
camera->rotate(angles.y(), QVector3D(1.f, 0.f, 0.f), QQuick3DNode::LocalSpace);
|
||||||
|
// Rotation around Y-axis is done in scene space to keep horizon level
|
||||||
|
if (qAbs(angles.x()) > 0.001f)
|
||||||
|
camera->rotate(angles.x(), QVector3D(0.f, 1.f, 0.f), QQuick3DNode::SceneSpace);
|
||||||
|
|
||||||
|
QMatrix4x4 m = camera->sceneTransform();
|
||||||
|
const float *dataPtr(m.data());
|
||||||
|
QVector3D newLookVector(dataPtr[8], dataPtr[9], dataPtr[10]);
|
||||||
|
|
||||||
|
newLookVector.normalize();
|
||||||
|
newLookVector *= lookAtDist;
|
||||||
|
|
||||||
|
return camera->scenePosition() - newLookVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneralHelper::updateCombinedCameraMoveVector()
|
||||||
|
{
|
||||||
|
QVector3D combinedVec;
|
||||||
|
for (const QVector3D &vec : std::as_const(m_camMoveData.moveVectors))
|
||||||
|
combinedVec += vec;
|
||||||
|
m_camMoveData.combinedMoveVector = combinedVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key events can be buffered and there are repeat delays imposed by OS, so to get smooth camera
|
||||||
|
// movement in response to keys, register start/stop of moves along each axis and use timer to
|
||||||
|
// trigger new moves along registered axes.
|
||||||
|
void GeneralHelper::startCameraMove(QQuick3DCamera *camera, const QVector3D moveVector)
|
||||||
|
{
|
||||||
|
if (moveVector.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_camMoveData.camera != camera) {
|
||||||
|
m_camMoveData.camera = camera;
|
||||||
|
m_camMoveData.moveVectors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_camMoveData.moveVectors.contains(moveVector)) {
|
||||||
|
m_camMoveData.moveVectors.append(moveVector);
|
||||||
|
updateCombinedCameraMoveVector();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_camMoveData.timer.isActive()) {
|
||||||
|
m_camMoveData.timer.start();
|
||||||
|
emit requestCameraMove(camera, m_camMoveData.combinedMoveVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneralHelper::stopCameraMove(const QVector3D moveVector)
|
||||||
|
{
|
||||||
|
if (moveVector.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_camMoveData.moveVectors.removeOne(moveVector);
|
||||||
|
|
||||||
|
updateCombinedCameraMoveVector();
|
||||||
|
|
||||||
|
if (m_camMoveData.moveVectors.isEmpty())
|
||||||
|
m_camMoveData.timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneralHelper::stopAllCameraMoves()
|
||||||
|
{
|
||||||
|
m_camMoveData.moveVectors.clear();
|
||||||
|
m_camMoveData.combinedMoveVector = {};
|
||||||
|
m_camMoveData.timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
float GeneralHelper::zoomCamera([[maybe_unused]] QQuick3DViewport *viewPort,
|
float GeneralHelper::zoomCamera([[maybe_unused]] QQuick3DViewport *viewPort,
|
||||||
QQuick3DCamera *camera,
|
QQuick3DCamera *camera,
|
||||||
float distance,
|
float distance,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <QMatrix4x4>
|
#include <QMatrix4x4>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QPointF>
|
||||||
#include <QQuaternion>
|
#include <QQuaternion>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
@@ -52,6 +53,15 @@ public:
|
|||||||
const QVector3D &startPosition, const QVector3D &startLookAt,
|
const QVector3D &startPosition, const QVector3D &startLookAt,
|
||||||
const QVector3D &pressPos, const QVector3D ¤tPos,
|
const QVector3D &pressPos, const QVector3D ¤tPos,
|
||||||
float zoomFactor);
|
float zoomFactor);
|
||||||
|
Q_INVOKABLE QVector3D moveCamera(QQuick3DCamera *camera,const QVector3D &startLookAt,
|
||||||
|
float zoomFactor, const QVector3D &moveVector);
|
||||||
|
Q_INVOKABLE QVector3D rotateCamera(QQuick3DCamera *camera, const QPointF &angles,
|
||||||
|
const QVector3D &lookAtPoint);
|
||||||
|
|
||||||
|
Q_INVOKABLE void startCameraMove(QQuick3DCamera *camera, const QVector3D moveVector);
|
||||||
|
Q_INVOKABLE void stopCameraMove(const QVector3D moveVector);
|
||||||
|
Q_INVOKABLE void stopAllCameraMoves();
|
||||||
|
|
||||||
Q_INVOKABLE float zoomCamera(QQuick3DViewport *viewPort, QQuick3DCamera *camera, float distance,
|
Q_INVOKABLE float zoomCamera(QQuick3DViewport *viewPort, QQuick3DCamera *camera, float distance,
|
||||||
float defaultLookAtDistance, const QVector3D &lookAt,
|
float defaultLookAtDistance, const QVector3D &lookAt,
|
||||||
float zoomFactor, bool relative);
|
float zoomFactor, bool relative);
|
||||||
@@ -149,6 +159,8 @@ signals:
|
|||||||
void minGridStepChanged();
|
void minGridStepChanged();
|
||||||
void updateDragTooltip();
|
void updateDragTooltip();
|
||||||
void sceneEnvDataChanged();
|
void sceneEnvDataChanged();
|
||||||
|
void requestCameraMove(QQuick3DCamera *camera, const QVector3D &moveVector);
|
||||||
|
void requestRender();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handlePendingToolStateUpdate();
|
void handlePendingToolStateUpdate();
|
||||||
@@ -163,6 +175,15 @@ private:
|
|||||||
QHash<QString, QVariantMap> m_toolStates;
|
QHash<QString, QVariantMap> m_toolStates;
|
||||||
QHash<QString, QVariantMap> m_toolStatesPending;
|
QHash<QString, QVariantMap> m_toolStatesPending;
|
||||||
QSet<QQuick3DNode *> m_rotationBlockedNodes;
|
QSet<QQuick3DNode *> m_rotationBlockedNodes;
|
||||||
|
void updateCombinedCameraMoveVector();
|
||||||
|
|
||||||
|
struct CameraMoveKeyData {
|
||||||
|
QQuick3DCamera *camera;
|
||||||
|
QList<QVector3D> moveVectors;
|
||||||
|
QVector3D combinedMoveVector;
|
||||||
|
QTimer timer;
|
||||||
|
};
|
||||||
|
CameraMoveKeyData m_camMoveData;
|
||||||
|
|
||||||
struct SceneEnvData {
|
struct SceneEnvData {
|
||||||
QQuick3DSceneEnvironment::QQuick3DEnvironmentBackgroundTypes backgroundMode;
|
QQuick3DSceneEnvironment::QQuick3DEnvironmentBackgroundTypes backgroundMode;
|
||||||
|
|||||||
@@ -254,8 +254,11 @@ void Qt5InformationNodeInstanceServer::handleInputEvents()
|
|||||||
QGuiApplication::sendEvent(m_editView3DData.window, &me);
|
QGuiApplication::sendEvent(m_editView3DData.window, &me);
|
||||||
|
|
||||||
// Context menu requested
|
// Context menu requested
|
||||||
if (command.button() == Qt::RightButton && command.modifiers() == Qt::NoModifier)
|
if (command.type() == QEvent::MouseButtonPress
|
||||||
|
&& command.buttons() == Qt::RightButton
|
||||||
|
&& command.modifiers() == Qt::NoModifier) {
|
||||||
getNodeAtPos(command.pos());
|
getNodeAtPos(command.pos());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,6 +491,9 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
|
|||||||
auto helper = new QmlDesigner::Internal::GeneralHelper();
|
auto helper = new QmlDesigner::Internal::GeneralHelper();
|
||||||
QObject::connect(helper, &QmlDesigner::Internal::GeneralHelper::toolStateChanged,
|
QObject::connect(helper, &QmlDesigner::Internal::GeneralHelper::toolStateChanged,
|
||||||
this, &Qt5InformationNodeInstanceServer::handleToolStateChanged);
|
this, &Qt5InformationNodeInstanceServer::handleToolStateChanged);
|
||||||
|
QObject::connect(helper, &QmlDesigner::Internal::GeneralHelper::requestRender, this, [this]() {
|
||||||
|
render3DEditView(1);
|
||||||
|
});
|
||||||
engine()->rootContext()->setContextProperty("_generalHelper", helper);
|
engine()->rootContext()->setContextProperty("_generalHelper", helper);
|
||||||
engine()->addImageProvider(QLatin1String("IconGizmoImageProvider"),
|
engine()->addImageProvider(QLatin1String("IconGizmoImageProvider"),
|
||||||
new QmlDesigner::Internal::IconGizmoImageProvider);
|
new QmlDesigner::Internal::IconGizmoImageProvider);
|
||||||
@@ -2417,6 +2423,7 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
|
|||||||
if (!m_editView3DSetupDone)
|
if (!m_editView3DSetupDone)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef QUICK3D_MODULE
|
||||||
QVariantMap updatedToolState;
|
QVariantMap updatedToolState;
|
||||||
QVariantMap updatedViewState;
|
QVariantMap updatedViewState;
|
||||||
int renderCount = 1;
|
int renderCount = 1;
|
||||||
@@ -2498,16 +2505,31 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
|
|||||||
case View3DActionType::ParticlesSeek:
|
case View3DActionType::ParticlesSeek:
|
||||||
m_particleAnimationDriver->setSeekerPosition(command.position());
|
m_particleAnimationDriver->setSeekerPosition(command.position());
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif // QUICK3D_PARTICLES_MODULE
|
||||||
#ifdef QUICK3D_MODULE
|
|
||||||
case View3DActionType::GetNodeAtPos: {
|
case View3DActionType::GetNodeAtPos: {
|
||||||
getNodeAtPos(command.value().toPointF());
|
getNodeAtPos(command.value().toPointF());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
case View3DActionType::SplitViewToggle:
|
case View3DActionType::SplitViewToggle:
|
||||||
updatedToolState.insert("splitView", command.isEnabled());
|
updatedToolState.insert("splitView", command.isEnabled());
|
||||||
break;
|
break;
|
||||||
|
case View3DActionType::FlyModeToggle:
|
||||||
|
updatedToolState.insert("flyMode", command.isEnabled());
|
||||||
|
break;
|
||||||
|
case View3DActionType::EditCameraRotation:
|
||||||
|
QMetaObject::invokeMethod(m_editView3DData.rootItem, "rotateEditCamera",
|
||||||
|
Q_ARG(QVariant, command.value()));
|
||||||
|
break;
|
||||||
|
case View3DActionType::EditCameraMove:
|
||||||
|
QMetaObject::invokeMethod(m_editView3DData.rootItem, "moveEditCamera",
|
||||||
|
Q_ARG(QVariant, command.value()));
|
||||||
|
break;
|
||||||
|
case View3DActionType::EditCameraStopAllMoves: {
|
||||||
|
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
|
||||||
|
if (helper)
|
||||||
|
emit helper->stopAllCameraMoves();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case View3DActionType::ShowWireframe:
|
case View3DActionType::ShowWireframe:
|
||||||
updatedToolState.insert("showWireframe", command.value().toList());
|
updatedToolState.insert("showWireframe", command.value().toList());
|
||||||
break;
|
break;
|
||||||
@@ -2531,6 +2553,7 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
|
|||||||
}
|
}
|
||||||
|
|
||||||
render3DEditView(renderCount);
|
render3DEditView(renderCount);
|
||||||
|
#endif // QUICK3D_MODULE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Qt5InformationNodeInstanceServer::requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command)
|
void Qt5InformationNodeInstanceServer::requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command)
|
||||||
|
|||||||
Reference in New Issue
Block a user