QmlDesigner: Block changing eulerRotation for 3D Node that has rotation

QtQuick3D doesn't support both rotation and eulerRotation set on same
node, so we delete existing quaternion rotation if user sets an euler
rotation to the node. If node has quaternion rotation animation,
we block any change to eulerRotation in the node.

3D editor also disables the rotation gizmo for blocked nodes.

Task-number: QDS-4335
Change-Id: I4ce7b022c732a9547751f101548ecea948279db8
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2021-05-12 14:15:47 +03:00
parent a3c51cdd4a
commit 125cdcc3a0
19 changed files with 360 additions and 52 deletions
@@ -356,6 +356,24 @@ bool GeneralHelper::isMacOS() const
#endif
}
void GeneralHelper::addRotationBlocks(const QSet<QQuick3DNode *> &nodes)
{
m_rotationBlockedNodes.unite(nodes);
emit rotationBlocksChanged();
}
void GeneralHelper::removeRotationBlocks(const QSet<QQuick3DNode *> &nodes)
{
for (auto node : nodes)
m_rotationBlockedNodes.remove(node);
emit rotationBlocksChanged();
}
bool GeneralHelper::isRotationBlocked(QQuick3DNode *node) const
{
return m_rotationBlockedNodes.contains(node);
}
bool GeneralHelper::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::DynamicPropertyChange) {
@@ -93,11 +93,16 @@ public:
bool isMacOS() const;
void addRotationBlocks(const QSet<QQuick3DNode *> &nodes);
void removeRotationBlocks(const QSet<QQuick3DNode *> &nodes);
Q_INVOKABLE bool isRotationBlocked(QQuick3DNode *node) const;
signals:
void overlayUpdateNeeded();
void toolStateChanged(const QString &sceneId, const QString &tool, const QVariant &toolState);
void hiddenStateChanged(QQuick3DNode *node);
void lockedStateChanged(QQuick3DNode *node);
void rotationBlocksChanged();
protected:
bool eventFilter(QObject *obj, QEvent *event) final;
@@ -110,6 +115,7 @@ private:
QHash<QString, QVariantMap> m_toolStates;
QHash<QString, QVariantMap> m_toolStatesPending;
QSet<QQuick3DNode *> m_gizmoTargets;
QSet<QQuick3DNode *> m_rotationBlockedNodes;
};
}
@@ -63,6 +63,7 @@
#include "inputeventcommand.h"
#include "view3dactioncommand.h"
#include "requestmodelnodepreviewimagecommand.h"
#include "changeauxiliarycommand.h"
#include "dummycontextobject.h"
#include "../editor3d/generalhelper.h"
@@ -288,6 +289,57 @@ void Qt5InformationNodeInstanceServer::resolveImportSupport()
#endif
}
void Qt5InformationNodeInstanceServer::updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges)
{
#ifdef QUICK3D_MODULE
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
if (helper) {
QSet<QQuick3DNode *> blockedNodes;
QSet<QQuick3DNode *> unblockedNodes;
const PropertyName propName = "rotBlocked@internal";
for (const auto &container : valueChanges) {
if (container.name() == propName) {
ServerNodeInstance instance = instanceForId(container.instanceId());
if (instance.isValid()) {
auto node = qobject_cast<QQuick3DNode *>(instance.internalObject());
if (node) {
if (container.value().toBool())
blockedNodes.insert(node);
else
unblockedNodes.insert(node);
}
}
}
}
helper->addRotationBlocks(blockedNodes);
helper->removeRotationBlocks(unblockedNodes);
}
#else
Q_UNUSED(valueChanges)
#endif
}
void Qt5InformationNodeInstanceServer::removeRotationBlocks(const QVector<qint32> &instanceIds)
{
#ifdef QUICK3D_MODULE
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
if (helper) {
QSet<QQuick3DNode *> unblockedNodes;
for (const auto &id : instanceIds) {
ServerNodeInstance instance = instanceForId(id);
if (instance.isValid()) {
auto node = qobject_cast<QQuick3DNode *>(instance.internalObject());
if (node)
unblockedNodes.insert(node);
}
}
helper->removeRotationBlocks(unblockedNodes);
}
#else
Q_UNUSED(instanceIds)
#endif
}
void Qt5InformationNodeInstanceServer::createEditView3D()
{
#ifdef QUICK3D_MODULE
@@ -1492,8 +1544,10 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com
sendChildrenChangedCommand(instanceList);
nodeInstanceClient()->componentCompleted(createComponentCompletedCommand(instanceList));
if (isQuick3DMode())
if (isQuick3DMode()) {
setup3DEditView(instanceList, command.edit3dToolStates);
updateRotationBlocks(command.auxiliaryChanges);
}
QObject::connect(&m_renderModelNodeImageViewTimer, &QTimer::timeout,
this, &Qt5InformationNodeInstanceServer::doRenderModelNodeImageView);
@@ -1656,6 +1710,8 @@ void Qt5InformationNodeInstanceServer::removeInstances(const RemoveInstancesComm
{
int nodeCount = m_3DSceneMap.size();
removeRotationBlocks(command.instanceIds());
Qt5NodeInstanceServer::removeInstances(command);
if (nodeCount != m_3DSceneMap.size()) {
@@ -1741,6 +1797,7 @@ void Qt5InformationNodeInstanceServer::requestModelNodePreviewImage(const Reques
void Qt5InformationNodeInstanceServer::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command)
{
updateRotationBlocks(command.auxiliaryChanges);
Qt5NodeInstanceServer::changeAuxiliaryValues(command);
render3DEditView();
}
@@ -30,6 +30,8 @@
#include "valueschangedcommand.h"
#include "changeselectioncommand.h"
#include "requestmodelnodepreviewimagecommand.h"
#include "propertybindingcontainer.h"
#include "propertyabstractcontainer.h"
#include <QTimer>
#include <QVariant>
@@ -132,6 +134,8 @@ private:
void updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances);
void handleInputEvents();
void resolveImportSupport();
void updateRotationBlocks(const QVector<PropertyValueContainer> &valueChanges);
void removeRotationBlocks(const QVector<qint32> &instanceIds);
void createAuxiliaryQuickView(const QUrl &url, RenderViewData &viewData);