From 62cdaaff56efc797dc8044782b977ef5b3aa5d33 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sat, 28 Dec 2024 00:01:38 +0100 Subject: [PATCH] Gui: Zero out rotation only if more than 1 axis changed --- src/Gui/TaskCSysDragger.cpp | 62 ++++++++++++++++++--------------- src/Gui/TaskCSysDragger.h | 18 +++++----- src/Gui/ViewProviderDragger.cpp | 5 +++ src/Gui/ViewProviderDragger.h | 13 +++++++ 4 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/Gui/TaskCSysDragger.cpp b/src/Gui/TaskCSysDragger.cpp index 15d3a0bff4..baf6217739 100644 --- a/src/Gui/TaskCSysDragger.cpp +++ b/src/Gui/TaskCSysDragger.cpp @@ -128,24 +128,39 @@ void TaskTransform::dragStartCallback(void* data, SoDragger*) QT_TRANSLATE_NOOP("Command", "Transform")); firstDrag = false; } - - auto task = static_cast(data); - - task->referenceRotation = task->vp->getDraggerPlacement().getRotation(); } void TaskTransform::dragMotionCallback(void* data, SoDragger* dragger) { auto task = static_cast(data); - const auto currentRotation = task->referencePlacement.getRotation(); + const auto currentRotation = task->vp->getOriginalDraggerPlacement().getRotation(); const auto updatedRotation = task->vp->getDraggerPlacement().getRotation(); + const auto rotationAxisHasChanged = [task](auto first, auto second) { + double alpha, beta, gamma; + + (first.inverse() * second).getEulerAngles(task->eulerSequence(), alpha, beta, gamma); + + auto angles = {alpha, beta, gamma}; + const int changed = std::count_if(angles.begin(), angles.end(), [](double angle) { + return std::fabs(angle) > tolerance; + }); + + // if representation of both differs by more than one axis the axis of rotation must be + // different + return changed > 1; + }; + if (!updatedRotation.isSame(currentRotation, tolerance)) { task->resetReferencePlacement(); - } else { - task->updatePositionAndRotationUi(); + + if (rotationAxisHasChanged(task->referenceRotation, updatedRotation)) { + task->referenceRotation = currentRotation; + } } + + task->updatePositionAndRotationUi(); } void TaskTransform::loadPlacementModeItems() const @@ -283,11 +298,7 @@ void TaskTransform::savePreferences() void TaskTransform::updatePositionAndRotationUi() const { - auto referencePlacement = currentCoordinateSystem().origin; - - if (positionMode == PositionMode::Local) { - referencePlacement.setRotation(referenceRotation); - } + const auto referencePlacement = currentCoordinateSystem().origin; const auto xyzPlacement = vp->getDraggerPlacement(); const auto uvwPlacement = referencePlacement.inverse() * xyzPlacement; @@ -317,24 +328,17 @@ void TaskTransform::updatePositionAndRotationUi() const z->setValue(fixNegativeZero(gamma)); }; - auto setValues = [&](const Base::Placement& placement, - auto* px, - auto* py, - auto* pz, - auto* rx, - auto* ry, - auto* rz) { - setPositionValues(placement.getPosition(), px, py, pz); - setRotationValues(placement.getRotation(), rx, ry, rz); - }; + setPositionValues(uvwPlacement.getPosition(), + ui->xPositionSpinBox, + ui->yPositionSpinBox, + ui->zPositionSpinBox); - setValues(uvwPlacement, - ui->xPositionSpinBox, - ui->yPositionSpinBox, - ui->zPositionSpinBox, - ui->xRotationSpinBox, - ui->yRotationSpinBox, - ui->zRotationSpinBox); + setRotationValues(positionMode == PositionMode::Local + ? referenceRotation.inverse() * xyzPlacement.getRotation() + : uvwPlacement.getRotation(), + ui->xRotationSpinBox, + ui->yRotationSpinBox, + ui->zRotationSpinBox); } void TaskTransform::updateInputLabels() const diff --git a/src/Gui/TaskCSysDragger.h b/src/Gui/TaskCSysDragger.h index ade395b2d8..0f7fed2cca 100644 --- a/src/Gui/TaskCSysDragger.h +++ b/src/Gui/TaskCSysDragger.h @@ -75,15 +75,6 @@ public: Base::provideService()); ~TaskTransform() override; - void setSelectionMode(SelectionMode mode); - SelectionMode getSelectionMode() const; - - CoordinateSystem globalCoordinateSystem() const; - CoordinateSystem localCoordinateSystem() const; - CoordinateSystem currentCoordinateSystem() const; - - Base::Rotation::EulerSequence eulerSequence() const; - private: void onSelectionChanged(const SelectionChanges& msg) override; @@ -107,6 +98,15 @@ private: static void dragStartCallback(void* data, SoDragger* d); static void dragMotionCallback(void* data, SoDragger* d); + void setSelectionMode(SelectionMode mode); + SelectionMode getSelectionMode() const; + + CoordinateSystem globalCoordinateSystem() const; + CoordinateSystem localCoordinateSystem() const; + CoordinateSystem currentCoordinateSystem() const; + + Base::Rotation::EulerSequence eulerSequence() const; + void setupGui(); void loadPreferences(); diff --git a/src/Gui/ViewProviderDragger.cpp b/src/Gui/ViewProviderDragger.cpp index cf37d474a8..2484ee197e 100644 --- a/src/Gui/ViewProviderDragger.cpp +++ b/src/Gui/ViewProviderDragger.cpp @@ -308,6 +308,11 @@ Base::Placement ViewProviderDragger::getDraggerPlacement() const ); } +Base::Placement ViewProviderDragger::getOriginalDraggerPlacement() const +{ + return draggerPlacement; +} + void ViewProviderDragger::setDraggerPlacement(const Base::Placement& placement) { csysDragger->translation.setValue(Base::convertTo(placement.getPosition())); diff --git a/src/Gui/ViewProviderDragger.h b/src/Gui/ViewProviderDragger.h index a2d9686bbb..21808413a7 100644 --- a/src/Gui/ViewProviderDragger.h +++ b/src/Gui/ViewProviderDragger.h @@ -56,10 +56,16 @@ public: /// destructor. ~ViewProviderDragger() override; + /// Origin used when object is transformed. It temporarily changes the origin of object. + /// Dragger is normally placed at the transform origin, unless explicitly overridden via + /// ViewProviderDragger#setDraggerPlacement() method. App::PropertyPlacement TransformOrigin; + /// Convenience method to obtain the transform origin Base::Placement getTransformOrigin() const { return TransformOrigin.getValue(); } + /// Convenience method to set the transform origin void setTransformOrigin(const Base::Placement& placement); + /// Resets transform origin to the object origin void resetTransformOrigin(); public: @@ -74,11 +80,18 @@ public: /*! synchronize From FC placement to Coin placement*/ static void updateTransform(const Base::Placement &from, SoTransform *to); + /// updates placement of object based on dragger position void updatePlacementFromDragger(); + /// updates transform of object based on dragger position, can be used to preview movement void updateTransformFromDragger(); + /// Gets object placement relative to its coordinate system Base::Placement getObjectPlacement() const; + /// Gets current dragger placement, including current dragger movement Base::Placement getDraggerPlacement() const; + /// Gets original dragger placement, without current dragger movement + Base::Placement getOriginalDraggerPlacement() const; + /// Sets placement of dragger relative to objects origin void setDraggerPlacement(const Base::Placement& placement); protected: