forked from qt-creator/qt-creator
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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,42 +268,45 @@ 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)
|
||||||
{
|
{
|
||||||
const QString stateKey = QStringLiteral("windowState");
|
if (m_toolStates.contains(globalStateId)) {
|
||||||
if (toolStates.contains(stateKey)) {
|
const QVariantMap &globalStateMap = m_toolStates[globalStateId];
|
||||||
QVariantMap windowState = toolStates[stateKey].value<QVariantMap>();
|
const QString stateKey = QStringLiteral("windowState");
|
||||||
|
if (globalStateMap.contains(stateKey)) {
|
||||||
|
QVariantMap windowState = globalStateMap[stateKey].value<QVariantMap>();
|
||||||
|
|
||||||
doRestoreWindowState(w, windowState);
|
|
||||||
|
|
||||||
// If the mouse cursor at puppet launch time is in a different screen than the one where the
|
|
||||||
// view geometry was saved on, the initial position and size can be incorrect, but if
|
|
||||||
// we reset the geometry again asynchronously, it should end up with correct geometry.
|
|
||||||
QTimer::singleShot(0, [this, w, windowState]() {
|
|
||||||
doRestoreWindowState(w, windowState);
|
doRestoreWindowState(w, windowState);
|
||||||
|
|
||||||
QTimer::singleShot(0, [w]() {
|
// If the mouse cursor at puppet launch time is in a different screen than the one where the
|
||||||
// Make sure that the window is at least partially visible on the screen
|
// view geometry was saved on, the initial position and size can be incorrect, but if
|
||||||
QRect geo = w->geometry();
|
// we reset the geometry again asynchronously, it should end up with correct geometry.
|
||||||
QRect sRect = w->screen()->geometry();
|
QTimer::singleShot(0, [this, w, windowState]() {
|
||||||
if (geo.left() > sRect.right() - 150)
|
doRestoreWindowState(w, windowState);
|
||||||
geo.moveRight(sRect.right());
|
|
||||||
if (geo.right() < sRect.left() + 150)
|
QTimer::singleShot(0, [w]() {
|
||||||
geo.moveLeft(sRect.left());
|
// Make sure that the window is at least partially visible on the screen
|
||||||
if (geo.top() > sRect.bottom() - 150)
|
QRect geo = w->geometry();
|
||||||
geo.moveBottom(sRect.bottom());
|
QRect sRect = w->screen()->geometry();
|
||||||
if (geo.bottom() < sRect.top() + 150)
|
if (geo.left() > sRect.right() - 150)
|
||||||
geo.moveTop(sRect.top());
|
geo.moveRight(sRect.right());
|
||||||
if (geo.width() > sRect.width())
|
if (geo.right() < sRect.left() + 150)
|
||||||
geo.setWidth(sRect.width());
|
geo.moveLeft(sRect.left());
|
||||||
if (geo.height() > sRect.height())
|
if (geo.top() > sRect.bottom() - 150)
|
||||||
geo.setHeight(sRect.height());
|
geo.moveBottom(sRect.bottom());
|
||||||
w->setGeometry(geo);
|
if (geo.bottom() < sRect.top() + 150)
|
||||||
|
geo.moveTop(sRect.top());
|
||||||
|
if (geo.width() > sRect.width())
|
||||||
|
geo.setWidth(sRect.width());
|
||||||
|
if (geo.height() > sRect.height())
|
||||||
|
geo.setHeight(sRect.height());
|
||||||
|
w->setGeometry(geo);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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()
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user