Gui: Zero out rotation only if more than 1 axis changed

This commit is contained in:
Kacper Donat
2024-12-28 00:01:38 +01:00
parent 178535980e
commit 62cdaaff56
4 changed files with 60 additions and 38 deletions

View File

@@ -128,24 +128,39 @@ void TaskTransform::dragStartCallback(void* data, SoDragger*)
QT_TRANSLATE_NOOP("Command", "Transform"));
firstDrag = false;
}
auto task = static_cast<TaskTransform*>(data);
task->referenceRotation = task->vp->getDraggerPlacement().getRotation();
}
void TaskTransform::dragMotionCallback(void* data, SoDragger* dragger)
{
auto task = static_cast<TaskTransform*>(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

View File

@@ -75,15 +75,6 @@ public:
Base::provideService<App::CenterOfMassProvider>());
~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();

View File

@@ -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<SbVec3f>(placement.getPosition()));

View File

@@ -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: