QmlDesigner: Store tool state on per-scene basis

Tool state of the scene is linked to qml id of the scene root, so that
tool states are preserved through delete and undo, which causes
generation of new internal ids for instances.

Tool state storage doesn't currently survive changing of scene root
qml id, as tracking that isn't trivial. It's not enough to simply track
id change commands because model repurposes existing nodes when major
graph changes occur, causing unexpected id changes e.g. when
delete/undo is done.

Change-Id: I74d11ce47e86ce5d29796399c4a91b65980b1597
Fixes: QDS-1536
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2020-02-10 15:32:57 +02:00
parent 841f5be97e
commit 1d71e6ac17
12 changed files with 188 additions and 99 deletions

View File

@@ -40,7 +40,7 @@ CreateSceneCommand::CreateSceneCommand(const QVector<InstanceContainer> &instanc
const QVector<AddImportContainer> &importVector, const QVector<AddImportContainer> &importVector,
const QVector<MockupTypeContainer> &mockupTypeVector, const QVector<MockupTypeContainer> &mockupTypeVector,
const QUrl &fileUrl, const QUrl &fileUrl,
const QVariantMap &edit3dToolStates) const QHash<QString, QVariantMap> &edit3dToolStates)
: m_instanceVector(instanceContainer), : m_instanceVector(instanceContainer),
m_reparentInstanceVector(reparentContainer), m_reparentInstanceVector(reparentContainer),
m_idVector(idVector), m_idVector(idVector),
@@ -99,7 +99,7 @@ QUrl CreateSceneCommand::fileUrl() const
return m_fileUrl; return m_fileUrl;
} }
QVariantMap CreateSceneCommand::edit3dToolStates() const QHash<QString, QVariantMap> CreateSceneCommand::edit3dToolStates() const
{ {
return m_edit3dToolStates; return m_edit3dToolStates;
} }

View File

@@ -54,7 +54,7 @@ public:
const QVector<AddImportContainer> &importVector, const QVector<AddImportContainer> &importVector,
const QVector<MockupTypeContainer> &mockupTypeVector, const QVector<MockupTypeContainer> &mockupTypeVector,
const QUrl &fileUrl, const QUrl &fileUrl,
const QVariantMap &edit3dToolStates); const QHash<QString, QVariantMap> &edit3dToolStates);
QVector<InstanceContainer> instances() const; QVector<InstanceContainer> instances() const;
QVector<ReparentContainer> reparentInstances() const; QVector<ReparentContainer> reparentInstances() const;
@@ -65,7 +65,7 @@ public:
QVector<AddImportContainer> imports() const; QVector<AddImportContainer> imports() const;
QVector<MockupTypeContainer> mockupTypes() const; QVector<MockupTypeContainer> mockupTypes() const;
QUrl fileUrl() const; QUrl fileUrl() const;
QVariantMap edit3dToolStates() const; QHash<QString, QVariantMap> edit3dToolStates() const;
private: private:
QVector<InstanceContainer> m_instanceVector; QVector<InstanceContainer> m_instanceVector;
@@ -77,7 +77,7 @@ private:
QVector<AddImportContainer> m_importVector; QVector<AddImportContainer> m_importVector;
QVector<MockupTypeContainer> m_mockupTypeVector; QVector<MockupTypeContainer> m_mockupTypeVector;
QUrl m_fileUrl; QUrl m_fileUrl;
QVariantMap m_edit3dToolStates; QHash<QString, QVariantMap> m_edit3dToolStates;
}; };
QDataStream &operator<<(QDataStream &out, const CreateSceneCommand &command); QDataStream &operator<<(QDataStream &out, const CreateSceneCommand &command);

View File

@@ -216,9 +216,6 @@ void NodeInstanceServerInterface::registerCommands()
qRegisterMetaType<QPair<int, int>>("QPairIntInt"); qRegisterMetaType<QPair<int, int>>("QPairIntInt");
qRegisterMetaTypeStreamOperators<QPair<int, int>>("QPairIntInt"); qRegisterMetaTypeStreamOperators<QPair<int, int>>("QPairIntInt");
qRegisterMetaType<QPair<QString, QVariant>>("QPairStringVariant");
qRegisterMetaTypeStreamOperators<QPair<QString, QVariant>>("QPairStringVariant");
} }
} }

View File

@@ -31,7 +31,7 @@ Item {
property Camera camera: null property Camera camera: null
property View3D view3d: null property View3D view3d: null
property string sceneId
property vector3d _lookAtPoint property vector3d _lookAtPoint
property vector3d _pressPoint property vector3d _pressPoint
property vector3d _prevPoint property vector3d _prevPoint
@@ -42,10 +42,13 @@ Item {
property bool _dragging property bool _dragging
property int _button property int _button
property real _zoomFactor: 1 property real _zoomFactor: 1
property real _defaultCameraLookAtDistance: 0
property Camera _prevCamera: null property Camera _prevCamera: null
readonly property vector3d _defaultCameraPosition: Qt.vector3d(0, 600, -600)
readonly property vector3d _defaultCameraRotation: Qt.vector3d(45, 0, 0)
readonly property real _defaultCameraLookAtDistance: _defaultCameraPosition.length()
function restoreCameraState(cameraState) { function restoreCameraState(cameraState)
{
if (!camera) if (!camera)
return; return;
@@ -57,7 +60,21 @@ Item {
_zoomFactor, false); _zoomFactor, false);
} }
function storeCameraState(delay) { function restoreDefaultState()
{
if (!camera)
return;
_lookAtPoint = Qt.vector3d(0, 0, 0);
_zoomFactor = 1;
camera.position = _defaultCameraPosition;
camera.rotation = _defaultCameraRotation;
_generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
_zoomFactor, false);
}
function storeCameraState(delay)
{
if (!camera) if (!camera)
return; return;
@@ -66,7 +83,7 @@ Item {
cameraState[1] = _zoomFactor; cameraState[1] = _zoomFactor;
cameraState[2] = camera.position; cameraState[2] = camera.position;
cameraState[3] = camera.rotation; cameraState[3] = camera.rotation;
_generalHelper.storeToolState("editCamState", cameraState, delay); _generalHelper.storeToolState(sceneId, "editCamState", cameraState, delay);
} }
@@ -92,10 +109,6 @@ Item {
_lookAtPoint, _zoomFactor, true); _lookAtPoint, _zoomFactor, true);
} }
Component.onCompleted: {
cameraCtrl._defaultCameraLookAtDistance = Qt.vector3d(0, 600, -600).length();
}
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

View File

@@ -61,9 +61,9 @@ Window {
signal commitObjectProperty(var object, var propName) signal commitObjectProperty(var object, var propName)
signal changeObjectProperty(var object, var propName) signal changeObjectProperty(var object, var propName)
onUsePerspectiveChanged: _generalHelper.storeToolState("usePerspective", usePerspective) onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective)
onShowEditLightChanged: _generalHelper.storeToolState("showEditLight", showEditLight) onShowEditLightChanged: _generalHelper.storeToolState(sceneId,"showEditLight", showEditLight)
onGlobalOrientationChanged: _generalHelper.storeToolState("globalOrientation", globalOrientation) onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
onActiveSceneChanged: { onActiveSceneChanged: {
if (editView) { if (editView) {
@@ -86,39 +86,57 @@ Window {
editView.cameraZoomFactor = Qt.binding(function() {return cameraControl._zoomFactor;}); editView.cameraZoomFactor = Qt.binding(function() {return cameraControl._zoomFactor;});
selectionBoxes.length = 0; selectionBoxes.length = 0;
updateToolStates();
} }
} }
} }
// Disables edit view update if scene doesn't match current activeScene. // Disables edit view update if scene doesn't match current activeScene.
// If it matches, updates are enabled. // If it matches, updates are enabled.
function enableEditViewUpdate(scene) { function enableEditViewUpdate(scene)
{
if (editView) if (editView)
_generalHelper.enableItemUpdate(editView, (scene && scene === activeScene)); _generalHelper.enableItemUpdate(editView, (scene && scene === activeScene));
} }
function updateToolStates(toolStates) {
// Init the stored state so we don't unnecessarily reflect changes back to creator
_generalHelper.initToolStates(toolStates);
_generalHelper.restoreWindowState(viewWindow, toolStates); function restoreWindowState()
{
// It is expected that tool states have been initialized before calling this
_generalHelper.restoreWindowState(viewWindow);
}
function updateToolStates()
{
var toolStates = _generalHelper.getToolStates(sceneId);
if ("showEditLight" in toolStates) if ("showEditLight" in toolStates)
showEditLight = toolStates.showEditLight; showEditLight = toolStates.showEditLight;
else
showEditLight = false;
if ("usePerspective" in toolStates) if ("usePerspective" in toolStates)
usePerspective = toolStates.usePerspective; usePerspective = toolStates.usePerspective;
else
usePerspective = false;
if ("globalOrientation" in toolStates) if ("globalOrientation" in toolStates)
globalOrientation = toolStates.globalOrientation; globalOrientation = toolStates.globalOrientation;
else
globalOrientation = false;
var groupIndex; var groupIndex;
var group; var group;
var i; var i;
btnSelectItem.selected = false;
btnSelectGroup.selected = true;
if ("groupSelect" in toolStates) { if ("groupSelect" in toolStates) {
groupIndex = toolStates.groupSelect; groupIndex = toolStates.groupSelect;
group = toolbarButtons.buttonGroups["groupSelect"]; group = toolbarButtons.buttonGroups["groupSelect"];
for (i = 0; i < group.length; ++i) for (i = 0; i < group.length; ++i)
group[i].selected = (i === groupIndex); group[i].selected = (i === groupIndex);
} }
btnRotate.selected = false;
btnScale.selected = false;
btnMove.selected = true;
if ("groupTransform" in toolStates) { if ("groupTransform" in toolStates) {
groupIndex = toolStates.groupTransform; groupIndex = toolStates.groupTransform;
group = toolbarButtons.buttonGroups["groupTransform"]; group = toolbarButtons.buttonGroups["groupTransform"];
@@ -128,9 +146,12 @@ Window {
if ("editCamState" in toolStates) if ("editCamState" in toolStates)
cameraControl.restoreCameraState(toolStates.editCamState); cameraControl.restoreCameraState(toolStates.editCamState);
else
cameraControl.restoreDefaultState();
} }
function ensureSelectionBoxes(count) { function ensureSelectionBoxes(count)
{
var needMore = count - selectionBoxes.length var needMore = count - selectionBoxes.length
if (needMore > 0) { if (needMore > 0) {
var component = Qt.createComponent("SelectionBox.qml"); var component = Qt.createComponent("SelectionBox.qml");
@@ -149,7 +170,8 @@ Window {
} }
} }
function selectObjects(objects) { function selectObjects(objects)
{
// Create selection boxes as necessary. One more box than is actually needed is created, so // Create selection boxes as necessary. One more box than is actually needed is created, so
// that we always have a previously created box to use for new selection. // that we always have a previously created box to use for new selection.
// This fixes an occasional visual glitch when creating a new box. // This fixes an occasional visual glitch when creating a new box.
@@ -168,7 +190,8 @@ Window {
selectedNode = objects[0]; selectedNode = objects[0];
} }
function handleObjectClicked(object, multi) { function handleObjectClicked(object, multi)
{
var theObject = object; var theObject = object;
if (btnSelectGroup.selected) { if (btnSelectGroup.selected) {
while (theObject && theObject !== activeScene && theObject.parent !== activeScene) while (theObject && theObject !== activeScene && theObject.parent !== activeScene)
@@ -511,6 +534,7 @@ Window {
camera: viewWindow.editView ? viewWindow.editView.camera : null camera: viewWindow.editView ? viewWindow.editView.camera : null
anchors.fill: parent anchors.fill: parent
view3d: viewWindow.editView view3d: viewWindow.editView
sceneId: viewWindow.sceneId
} }
} }
@@ -540,6 +564,7 @@ Window {
currentShortcut: selected ? "" : shortcut currentShortcut: selected ? "" : shortcut
tool: "item_selection" tool: "item_selection"
buttonGroup: "groupSelect" buttonGroup: "groupSelect"
sceneId: viewWindow.sceneId
} }
ToolBarButton { ToolBarButton {
@@ -549,6 +574,7 @@ Window {
currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut
tool: "group_selection" tool: "group_selection"
buttonGroup: "groupSelect" buttonGroup: "groupSelect"
sceneId: viewWindow.sceneId
} }
Rectangle { // separator Rectangle { // separator
@@ -566,6 +592,7 @@ Window {
currentShortcut: shortcut currentShortcut: shortcut
tool: "move" tool: "move"
buttonGroup: "groupTransform" buttonGroup: "groupTransform"
sceneId: viewWindow.sceneId
} }
ToolBarButton { ToolBarButton {
@@ -575,6 +602,7 @@ Window {
currentShortcut: shortcut currentShortcut: shortcut
tool: "rotate" tool: "rotate"
buttonGroup: "groupTransform" buttonGroup: "groupTransform"
sceneId: viewWindow.sceneId
} }
ToolBarButton { ToolBarButton {
@@ -584,6 +612,7 @@ Window {
currentShortcut: shortcut currentShortcut: shortcut
tool: "scale" tool: "scale"
buttonGroup: "groupTransform" buttonGroup: "groupTransform"
sceneId: viewWindow.sceneId
} }
Rectangle { // separator Rectangle { // separator

View File

@@ -35,6 +35,7 @@ Rectangle {
property string tool property string tool
property string buttonGroup property string buttonGroup
property bool togglable: true property bool togglable: true
property string sceneId
property int _buttonGroupIndex: -1 property int _buttonGroupIndex: -1
property var _buttonGroupArray: [] property var _buttonGroupArray: []
@@ -89,7 +90,7 @@ Rectangle {
root.selected = true; root.selected = true;
if (_buttonGroupIndex >= 0) if (_buttonGroupIndex >= 0)
_generalHelper.storeToolState(root.buttonGroup, root._buttonGroupIndex) _generalHelper.storeToolState(sceneId, root.buttonGroup, root._buttonGroupIndex)
if (!root.togglable) { if (!root.togglable) {
// Deselect button after a short while (selection acts as simple click indicator) // Deselect button after a short while (selection acts as simple click indicator)

View File

@@ -48,6 +48,8 @@
namespace QmlDesigner { namespace QmlDesigner {
namespace Internal { namespace Internal {
const QString globalStateId = QStringLiteral("@GTS"); // global tool state
GeneralHelper::GeneralHelper() GeneralHelper::GeneralHelper()
: QObject() : QObject()
{ {
@@ -228,10 +230,13 @@ QQuick3DNode *GeneralHelper::resolvePick(QQuick3DNode *pickNode)
return pickNode; return pickNode;
} }
void GeneralHelper::storeToolState(const QString &tool, const QVariant &state, int delay) void GeneralHelper::storeToolState(const QString &sceneId, const QString &tool, const QVariant &state,
int delay)
{ {
if (delay > 0) { if (delay > 0) {
m_toolStatesPending.insert(tool, state); QVariantMap sceneToolState;
sceneToolState.insert(tool, state);
m_toolStatesPending.insert(sceneId, sceneToolState);
m_toolStateUpdateTimer.start(delay); m_toolStateUpdateTimer.start(delay);
} else { } else {
if (m_toolStateUpdateTimer.isActive()) if (m_toolStateUpdateTimer.isActive())
@@ -242,16 +247,17 @@ void GeneralHelper::storeToolState(const QString &tool, const QVariant &state, i
theState = state.value<QVariantList>(); theState = state.value<QVariantList>();
else else
theState = state; theState = state;
if (m_toolStates[tool] != theState) { QVariantMap &sceneToolState = m_toolStates[sceneId];
m_toolStates.insert(tool, theState); if (sceneToolState[tool] != theState) {
emit toolStateChanged(tool, theState); sceneToolState.insert(tool, theState);
emit toolStateChanged(sceneId, tool, theState);
} }
} }
} }
void GeneralHelper::initToolStates(const QVariantMap &toolStates) void GeneralHelper::initToolStates(const QString &sceneId, const QVariantMap &toolStates)
{ {
m_toolStates = toolStates; m_toolStates[sceneId] = toolStates;
} }
void GeneralHelper::storeWindowState(QQuickWindow *w) void GeneralHelper::storeWindowState(QQuickWindow *w)
@@ -262,14 +268,16 @@ void GeneralHelper::storeWindowState(QQuickWindow *w)
windowState.insert("maximized", maximized); windowState.insert("maximized", maximized);
windowState.insert("geometry", geometry); windowState.insert("geometry", geometry);
storeToolState("windowState", windowState, 500); storeToolState(globalStateId, "windowState", windowState, 500);
} }
void GeneralHelper::restoreWindowState(QQuickWindow *w, const QVariantMap &toolStates) void GeneralHelper::restoreWindowState(QQuickWindow *w)
{ {
if (m_toolStates.contains(globalStateId)) {
const QVariantMap &globalStateMap = m_toolStates[globalStateId];
const QString stateKey = QStringLiteral("windowState"); const QString stateKey = QStringLiteral("windowState");
if (toolStates.contains(stateKey)) { if (globalStateMap.contains(stateKey)) {
QVariantMap windowState = toolStates[stateKey].value<QVariantMap>(); QVariantMap windowState = globalStateMap[stateKey].value<QVariantMap>();
doRestoreWindowState(w, windowState); doRestoreWindowState(w, windowState);
@@ -300,6 +308,7 @@ void GeneralHelper::restoreWindowState(QQuickWindow *w, const QVariantMap &toolS
}); });
} }
} }
}
void GeneralHelper::enableItemUpdate(QQuickItem *item, bool enable) void GeneralHelper::enableItemUpdate(QQuickItem *item, bool enable)
{ {
@@ -307,6 +316,14 @@ void GeneralHelper::enableItemUpdate(QQuickItem *item, bool enable)
item->setFlag(QQuickItem::ItemHasContents, enable); item->setFlag(QQuickItem::ItemHasContents, enable);
} }
QVariantMap GeneralHelper::getToolStates(const QString &sceneId)
{
handlePendingToolStateUpdate();
if (m_toolStates.contains(sceneId))
return m_toolStates[sceneId];
return {};
}
void GeneralHelper::doRestoreWindowState(QQuickWindow *w, const QVariantMap &windowState) void GeneralHelper::doRestoreWindowState(QQuickWindow *w, const QVariantMap &windowState)
{ {
const QString geoKey = QStringLiteral("geometry"); const QString geoKey = QStringLiteral("geometry");
@@ -336,10 +353,15 @@ bool GeneralHelper::isMacOS() const
void GeneralHelper::handlePendingToolStateUpdate() void GeneralHelper::handlePendingToolStateUpdate()
{ {
m_toolStateUpdateTimer.stop(); m_toolStateUpdateTimer.stop();
auto it = m_toolStatesPending.constBegin(); auto sceneIt = m_toolStatesPending.constBegin();
while (it != m_toolStatesPending.constEnd()) { while (sceneIt != m_toolStatesPending.constEnd()) {
storeToolState(it.key(), it.value()); const QVariantMap &sceneToolState = sceneIt.value();
++it; auto toolIt = sceneToolState.constBegin();
while (toolIt != sceneToolState.constEnd()) {
storeToolState(sceneIt.key(), toolIt.key(), toolIt.value());
++toolIt;
}
++sceneIt;
} }
m_toolStatesPending.clear(); m_toolStatesPending.clear();
} }

View File

@@ -71,17 +71,19 @@ public:
Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property, Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property,
const QVariant& value); const QVariant& value);
Q_INVOKABLE QQuick3DNode *resolvePick(QQuick3DNode *pickNode); Q_INVOKABLE QQuick3DNode *resolvePick(QQuick3DNode *pickNode);
Q_INVOKABLE void storeToolState(const QString &tool, const QVariant &state, int delayEmit = 0); Q_INVOKABLE void storeToolState(const QString &sceneId, const QString &tool,
Q_INVOKABLE void initToolStates(const QVariantMap &toolStates); const QVariant &state, int delayEmit = 0);
void initToolStates(const QString &sceneId, const QVariantMap &toolStates);
Q_INVOKABLE void storeWindowState(QQuickWindow *w); Q_INVOKABLE void storeWindowState(QQuickWindow *w);
Q_INVOKABLE void restoreWindowState(QQuickWindow *w, const QVariantMap &toolStates); void restoreWindowState(QQuickWindow *w);
Q_INVOKABLE void enableItemUpdate(QQuickItem *item, bool enable); Q_INVOKABLE void enableItemUpdate(QQuickItem *item, bool enable);
Q_INVOKABLE QVariantMap getToolStates(const QString &sceneId);
bool isMacOS() const; bool isMacOS() const;
signals: signals:
void overlayUpdateNeeded(); void overlayUpdateNeeded();
void toolStateChanged(const QString &tool, const QVariant &toolState); void toolStateChanged(const QString &sceneId, const QString &tool, const QVariant &toolState);
private slots: private slots:
void doRestoreWindowState(QQuickWindow *w, const QVariantMap &windowState); void doRestoreWindowState(QQuickWindow *w, const QVariantMap &windowState);
@@ -91,8 +93,8 @@ private:
QTimer m_overlayUpdateTimer; QTimer m_overlayUpdateTimer;
QTimer m_toolStateUpdateTimer; QTimer m_toolStateUpdateTimer;
QVariantMap m_toolStates; QHash<QString, QVariantMap> m_toolStates;
QVariantMap m_toolStatesPending; QHash<QString, QVariantMap> m_toolStatesPending;
}; };
} }

View File

@@ -110,14 +110,8 @@ bool Qt5InformationNodeInstanceServer::eventFilter(QObject *, QEvent *event)
QDropEvent *dropEvent = static_cast<QDropEvent *>(event); QDropEvent *dropEvent = static_cast<QDropEvent *>(event);
QByteArray data = dropEvent->mimeData()->data(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo")); QByteArray data = dropEvent->mimeData()->data(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"));
if (!data.isEmpty()) { if (!data.isEmpty()) {
ServerNodeInstance sceneInstance;
if (hasInstanceForObject(m_active3DScene))
sceneInstance = instanceForObject(m_active3DScene);
else if (hasInstanceForObject(m_active3DView))
sceneInstance = instanceForObject(m_active3DView);
nodeInstanceClient()->library3DItemDropped(createDrop3DLibraryItemCommand( nodeInstanceClient()->library3DItemDropped(createDrop3DLibraryItemCommand(
data, sceneInstance.instanceId())); data, active3DSceneInstance().instanceId()));
} }
} break; } break;
@@ -178,6 +172,7 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
QObject::connect(helper, &QmlDesigner::Internal::GeneralHelper::toolStateChanged, QObject::connect(helper, &QmlDesigner::Internal::GeneralHelper::toolStateChanged,
this, &Qt5InformationNodeInstanceServer::handleToolStateChanged); this, &Qt5InformationNodeInstanceServer::handleToolStateChanged);
engine->rootContext()->setContextProperty("_generalHelper", helper); engine->rootContext()->setContextProperty("_generalHelper", helper);
m_3dHelper = helper;
qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D"); qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D");
qmlRegisterType<QmlDesigner::Internal::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry"); qmlRegisterType<QmlDesigner::Internal::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry");
qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry"); qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry");
@@ -326,10 +321,14 @@ void Qt5InformationNodeInstanceServer::handleObjectPropertyChange(const QVariant
m_changedProperty = propertyName; m_changedProperty = propertyName;
} }
void Qt5InformationNodeInstanceServer::handleToolStateChanged(const QString &tool, void Qt5InformationNodeInstanceServer::handleToolStateChanged(const QString &sceneId,
const QString &tool,
const QVariant &toolState) const QVariant &toolState)
{ {
QPair<QString, QVariant> data = {tool, toolState}; QVariantList data;
data << sceneId;
data << tool;
data << toolState;
nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::Edit3DToolState, nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::Edit3DToolState,
QVariant::fromValue(data)}); QVariant::fromValue(data)});
} }
@@ -385,17 +384,17 @@ void Qt5InformationNodeInstanceServer::updateActiveSceneToEditView3D()
QMetaObject::invokeMethod(m_editView3D, "enableEditViewUpdate", QMetaObject::invokeMethod(m_editView3D, "enableEditViewUpdate",
Q_ARG(QVariant, activeSceneVar)); Q_ARG(QVariant, activeSceneVar));
ServerNodeInstance sceneInstance = active3DSceneInstance();
QVariant sceneInstanceVar;
QQmlProperty sceneIdProperty(m_editView3D, "sceneId", context());
if (sceneInstance.isValid())
sceneInstanceVar = QVariant::fromValue(sceneInstance.id());
sceneIdProperty.write(sceneInstanceVar);
QQmlProperty sceneProperty(m_editView3D, "activeScene", context()); QQmlProperty sceneProperty(m_editView3D, "activeScene", context());
sceneProperty.write(activeSceneVar); sceneProperty.write(activeSceneVar);
QString sceneId;
if (hasInstanceForObject(m_active3DScene))
sceneId = instanceForObject(m_active3DScene).id();
if (m_active3DView && sceneId.isEmpty() && hasInstanceForObject(m_active3DView))
sceneId = instanceForObject(m_active3DView).id();
updateView3DRect(m_active3DView); updateView3DRect(m_active3DView);
QQmlProperty viewIdProperty(m_editView3D, "sceneId", context());
viewIdProperty.write(QVariant::fromValue(sceneId));
} }
void Qt5InformationNodeInstanceServer::removeNode3D(QObject *node) void Qt5InformationNodeInstanceServer::removeNode3D(QObject *node)
@@ -454,6 +453,16 @@ void Qt5InformationNodeInstanceServer::resolveSceneRoots()
#endif #endif
} }
ServerNodeInstance Qt5InformationNodeInstanceServer::active3DSceneInstance() const
{
ServerNodeInstance sceneInstance;
if (hasInstanceForObject(m_active3DScene))
sceneInstance = instanceForObject(m_active3DScene);
else if (hasInstanceForObject(m_active3DView))
sceneInstance = instanceForObject(m_active3DView);
return sceneInstance;
}
Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) : Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
Qt5NodeInstanceServer(nodeInstanceClient) Qt5NodeInstanceServer(nodeInstanceClient)
{ {
@@ -756,8 +765,9 @@ QObject *Qt5InformationNodeInstanceServer::find3DSceneRoot(QObject *obj) const
} }
void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeInstance> &instanceList, void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeInstance> &instanceList,
const QVariantMap &toolStates) const QHash<QString, QVariantMap> &toolStates)
{ {
#ifdef QUICK3D_MODULE
ServerNodeInstance root = rootNodeInstance(); ServerNodeInstance root = rootNodeInstance();
add3DViewPorts(instanceList); add3DViewPorts(instanceList);
@@ -776,12 +786,21 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeIns
return; return;
} }
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
if (helper) {
auto it = toolStates.constBegin();
while (it != toolStates.constEnd()) {
helper->initToolStates(it.key(), it.value());
++it;
}
helper->restoreWindowState(qobject_cast<QQuickWindow *>(m_editView3D));
}
updateActiveSceneToEditView3D(); updateActiveSceneToEditView3D();
createCameraAndLightGizmos(instanceList); createCameraAndLightGizmos(instanceList);
QMetaObject::invokeMethod(m_editView3D, "updateToolStates", Q_ARG(QVariant, toolStates));
} }
#endif
} }
void Qt5InformationNodeInstanceServer::collectItemChangesAndSendChangeCommands() void Qt5InformationNodeInstanceServer::collectItemChangesAndSendChangeCommands()

View File

@@ -62,7 +62,8 @@ private slots:
void handleSelectionChanged(const QVariant &objs); void handleSelectionChanged(const QVariant &objs);
void handleObjectPropertyCommit(const QVariant &object, const QVariant &propName); void handleObjectPropertyCommit(const QVariant &object, const QVariant &propName);
void handleObjectPropertyChange(const QVariant &object, const QVariant &propName); void handleObjectPropertyChange(const QVariant &object, const QVariant &propName);
void handleToolStateChanged(const QString &tool, const QVariant &toolState); void handleToolStateChanged(const QString &sceneId, const QString &tool,
const QVariant &toolState);
void handleView3DSizeChange(); void handleView3DSizeChange();
void handleView3DDestroyed(QObject *obj); void handleView3DDestroyed(QObject *obj);
void handleNode3DDestroyed(QObject *obj); void handleNode3DDestroyed(QObject *obj);
@@ -83,7 +84,7 @@ private:
void handleSelectionChangeTimeout(); void handleSelectionChangeTimeout();
QObject *createEditView3D(QQmlEngine *engine); QObject *createEditView3D(QQmlEngine *engine);
void setup3DEditView(const QList<ServerNodeInstance> &instanceList, void setup3DEditView(const QList<ServerNodeInstance> &instanceList,
const QVariantMap &toolStates); const QHash<QString, QVariantMap> &toolStates);
void createCameraAndLightGizmos(const QList<ServerNodeInstance> &instanceList) const; void createCameraAndLightGizmos(const QList<ServerNodeInstance> &instanceList) const;
void add3DViewPorts(const QList<ServerNodeInstance> &instanceList); void add3DViewPorts(const QList<ServerNodeInstance> &instanceList);
void add3DScenes(const QList<ServerNodeInstance> &instanceList); void add3DScenes(const QList<ServerNodeInstance> &instanceList);
@@ -102,6 +103,7 @@ private:
void updateActiveSceneToEditView3D(); void updateActiveSceneToEditView3D();
void removeNode3D(QObject *node); void removeNode3D(QObject *node);
void resolveSceneRoots(); void resolveSceneRoots();
ServerNodeInstance active3DSceneInstance() const;
QObject *m_editView3D = nullptr; QObject *m_editView3D = nullptr;
QSet<QObject *> m_view3Ds; QSet<QObject *> m_view3Ds;
@@ -116,6 +118,7 @@ private:
QVariant m_changedNode; QVariant m_changedNode;
PropertyName m_changedProperty; PropertyName m_changedProperty;
ChangeSelectionCommand m_pendingSelectionChangeCommand; ChangeSelectionCommand m_pendingSelectionChangeCommand;
QObject *m_3dHelper = nullptr;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -211,7 +211,7 @@ private: // functions
ProjectExplorer::Target *m_currentTarget = nullptr; ProjectExplorer::Target *m_currentTarget = nullptr;
int m_restartProcessTimerId; int m_restartProcessTimerId;
RewriterTransaction m_puppetTransaction; RewriterTransaction m_puppetTransaction;
QVariantMap m_edit3DToolStates; QHash<QString, QVariantMap> m_edit3DToolStates; // Key: instance qml id, value: related tool states
}; };
} // namespace ProxyNodeInstanceView } // namespace ProxyNodeInstanceView

View File

@@ -1464,8 +1464,11 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand
handlePuppetKeyPress(key, modifiers); handlePuppetKeyPress(key, modifiers);
} else if (command.type() == PuppetToCreatorCommand::Edit3DToolState) { } else if (command.type() == PuppetToCreatorCommand::Edit3DToolState) {
if (!m_nodeInstanceServer.isNull()) { if (!m_nodeInstanceServer.isNull()) {
auto data = qvariant_cast<QPair<QString, QVariant>>(command.data()); auto data = qvariant_cast<QVariantList>(command.data());
m_edit3DToolStates[data.first] = data.second; if (data.size() == 3) {
QString qmlId = data[0].toString();
m_edit3DToolStates[qmlId].insert(data[1].toString(), data[2]);
}
} }
} }
} }