forked from qt-creator/qt-creator
QmlDesigner: Use transactions in 3D Edit View
We send a ValuesModifiedCommand 'immediately' when the item is moved. This means the 2D form editor and property editor update while moving nodes in the 3D edit view. The updates are 'compressed' by 100ms. This is to avoid performance issues. The timer could be reduced to 50ms or even 10ms, but 100ms feel acceptable at least for me. The code was a bit refactored. Qt5InformationNodeInstanceServer::modifyVariantValue() can be used later to update other Vector3D based properties like rotation and scale. There is one issue left. MouseArea3D emits 'onReleased' only after the mouse is moved again. This delays the 'commit' of the transaction which is annoying and can triggers bugs. Change-Id: I834a1e2658278ff8dd39678f39e51735dee91b65 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -43,6 +43,7 @@ Model {
|
||||
property var _targetStartPos
|
||||
|
||||
signal positionCommit()
|
||||
signal positionMove()
|
||||
|
||||
materials: DefaultMaterial {
|
||||
id: material
|
||||
@@ -85,6 +86,7 @@ Model {
|
||||
return;
|
||||
|
||||
targetNode.position = posInParent(mouseArea, pointerPosition);
|
||||
arrow.positionMove();
|
||||
}
|
||||
|
||||
function handleReleased(mouseArea, pointerPosition)
|
||||
|
@@ -46,6 +46,7 @@ Window {
|
||||
|
||||
signal objectClicked(var object)
|
||||
signal commitObjectPosition(var object)
|
||||
signal moveObjectPosition(var object)
|
||||
|
||||
function selectObject(object) {
|
||||
selectedNode = object;
|
||||
@@ -70,6 +71,7 @@ Window {
|
||||
targetNode: viewWindow.selectedNode
|
||||
position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
|
||||
: Qt.vector3d(0, 0, 0)
|
||||
|
||||
rotation: globalControl.checked || !viewWindow.selectedNode
|
||||
? Qt.vector3d(0, 0, 0)
|
||||
: viewWindow.selectedNode.sceneRotation
|
||||
@@ -78,6 +80,7 @@ Window {
|
||||
view3D: overlayView
|
||||
|
||||
onPositionCommit: viewWindow.commitObjectPosition(selectedNode)
|
||||
onPositionMove: viewWindow.moveObjectPosition(selectedNode)
|
||||
}
|
||||
|
||||
AutoScaleHelper {
|
||||
|
@@ -41,6 +41,7 @@ Node {
|
||||
property alias arrowZ: arrowZ
|
||||
|
||||
signal positionCommit()
|
||||
signal positionMove()
|
||||
|
||||
Arrow {
|
||||
id: arrowX
|
||||
@@ -52,6 +53,7 @@ Node {
|
||||
view3D: arrows.view3D
|
||||
|
||||
onPositionCommit: arrows.positionCommit()
|
||||
onPositionMove: arrows.positionMove()
|
||||
}
|
||||
|
||||
Arrow {
|
||||
@@ -64,6 +66,7 @@ Node {
|
||||
view3D: arrows.view3D
|
||||
|
||||
onPositionCommit: arrows.positionCommit()
|
||||
onPositionMove: arrows.positionMove()
|
||||
}
|
||||
|
||||
Arrow {
|
||||
@@ -76,5 +79,6 @@ Node {
|
||||
view3D: arrows.view3D
|
||||
|
||||
onPositionCommit: arrows.positionCommit()
|
||||
onPositionMove: arrows.positionMove()
|
||||
}
|
||||
}
|
||||
|
@@ -98,6 +98,10 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
|
||||
QObject::connect(window, SIGNAL(objectClicked(QVariant)), this, SLOT(objectClicked(QVariant)));
|
||||
QObject::connect(window, SIGNAL(commitObjectPosition(QVariant)),
|
||||
this, SLOT(handleObjectPositionCommit(QVariant)));
|
||||
QObject::connect(window, SIGNAL(moveObjectPosition(QVariant)),
|
||||
this, SLOT(handleObjectPositionMove(QVariant)));
|
||||
QObject::connect(&m_moveTimer, &QTimer::timeout,
|
||||
this, &Qt5InformationNodeInstanceServer::handleObjectPositionMoveTimeout);
|
||||
|
||||
//For macOS we have to use the 4.1 core profile
|
||||
QSurfaceFormat surfaceFormat = window->requestedFormat();
|
||||
@@ -149,21 +153,54 @@ Qt5InformationNodeInstanceServer::vectorToPropertyValue(
|
||||
return result;
|
||||
}
|
||||
|
||||
void Qt5InformationNodeInstanceServer::modifyVariantValue(
|
||||
const QVariant &node,
|
||||
const PropertyName &propertyName,
|
||||
ValuesModifiedCommand::TransactionOption option)
|
||||
{
|
||||
PropertyName targetPopertyName;
|
||||
|
||||
// Position is a special case, because the position can be 'position.x 'or simply 'x'.
|
||||
// We prefer 'x'.
|
||||
if (propertyName != "position")
|
||||
targetPopertyName = propertyName;
|
||||
|
||||
auto *obj = node.value<QObject *>();
|
||||
if (obj) {
|
||||
// We do have to split position into position.x, position.y, position.z
|
||||
ValuesModifiedCommand command = createValuesModifiedCommand(vectorToPropertyValue(
|
||||
instanceForObject(obj),
|
||||
targetPopertyName,
|
||||
obj->property(propertyName)));
|
||||
|
||||
command.transactionOption = option;
|
||||
|
||||
nodeInstanceClient()->valuesModified(command);
|
||||
}
|
||||
}
|
||||
|
||||
void Qt5InformationNodeInstanceServer::handleObjectPositionCommit(const QVariant &object)
|
||||
{
|
||||
auto *obj = object.value<QObject *>();
|
||||
if (obj) {
|
||||
/* We do have to split position into position.x, position.y, position.z */
|
||||
nodeInstanceClient()->valuesModified(createValuesModifiedCommand(vectorToPropertyValue(
|
||||
instanceForObject(obj),
|
||||
"position",
|
||||
obj->property("position"))));
|
||||
modifyVariantValue(object, "position", ValuesModifiedCommand::TransactionOption::End);
|
||||
m_movedNode = {};
|
||||
m_moveTimer.stop();
|
||||
}
|
||||
|
||||
void Qt5InformationNodeInstanceServer::handleObjectPositionMove(const QVariant &object)
|
||||
{
|
||||
if (m_movedNode.isNull()) {
|
||||
modifyVariantValue(object, "position", ValuesModifiedCommand::TransactionOption::Start);
|
||||
} else {
|
||||
if (!m_moveTimer.isActive())
|
||||
m_moveTimer.start();
|
||||
}
|
||||
m_movedNode = object;
|
||||
}
|
||||
|
||||
Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
|
||||
Qt5NodeInstanceServer(nodeInstanceClient)
|
||||
{
|
||||
m_moveTimer.setInterval(100);
|
||||
}
|
||||
|
||||
void Qt5InformationNodeInstanceServer::sendTokenBack()
|
||||
@@ -236,6 +273,11 @@ void Qt5InformationNodeInstanceServer::modifyProperties(
|
||||
nodeInstanceClient()->valuesModified(createValuesModifiedCommand(properties));
|
||||
}
|
||||
|
||||
void Qt5InformationNodeInstanceServer::handleObjectPositionMoveTimeout()
|
||||
{
|
||||
modifyVariantValue(m_movedNode, "position", ValuesModifiedCommand::TransactionOption::None);
|
||||
}
|
||||
|
||||
QObject *Qt5InformationNodeInstanceServer::findRootNodeOf3DViewport(
|
||||
const QList<ServerNodeInstance> &instanceList) const
|
||||
{
|
||||
|
@@ -27,6 +27,10 @@
|
||||
|
||||
#include "qt5nodeinstanceserver.h"
|
||||
#include "tokencommand.h"
|
||||
#include "valueschangedcommand.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QVariant>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -47,6 +51,7 @@ public:
|
||||
private slots:
|
||||
void objectClicked(const QVariant &object);
|
||||
void handleObjectPositionCommit(const QVariant &object);
|
||||
void handleObjectPositionMove(const QVariant &object);
|
||||
|
||||
protected:
|
||||
void collectItemChangesAndSendChangeCommands() override;
|
||||
@@ -58,17 +63,23 @@ protected:
|
||||
void modifyProperties(const QVector<InstancePropertyValueTriple> &properties);
|
||||
|
||||
private:
|
||||
void handleObjectPositionMoveTimeout();
|
||||
QObject *createEditView3D(QQmlEngine *engine);
|
||||
void setup3DEditView(const QList<ServerNodeInstance> &instanceList);
|
||||
QObject *findRootNodeOf3DViewport(const QList<ServerNodeInstance> &instanceList) const;
|
||||
QVector<InstancePropertyValueTriple> vectorToPropertyValue(const ServerNodeInstance &instance,
|
||||
const PropertyName &propertyName,
|
||||
const QVariant &variant);
|
||||
void modifyVariantValue(const QVariant &node,
|
||||
const PropertyName &propertyName,
|
||||
ValuesModifiedCommand::TransactionOption option);
|
||||
|
||||
QObject *m_editView3D = nullptr;
|
||||
QSet<ServerNodeInstance> m_parentChangedSet;
|
||||
QList<ServerNodeInstance> m_completedComponentList;
|
||||
QList<TokenCommand> m_tokenList;
|
||||
QTimer m_moveTimer;
|
||||
QVariant m_movedNode;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
Reference in New Issue
Block a user