diff --git a/src/Gui/NaviCube.cpp b/src/Gui/NaviCube.cpp index db95032839..d84e9ad2c2 100644 --- a/src/Gui/NaviCube.cpp +++ b/src/Gui/NaviCube.cpp @@ -54,6 +54,7 @@ #include "Command.h" #include "Action.h" #include "MainWindow.h" +#include "Navigation/NavigationAnimation.h" #include "View3DInventorViewer.h" #include "View3DInventor.h" #include "ViewParams.h" @@ -63,10 +64,6 @@ using namespace Eigen; using namespace std; using namespace Gui; - - - - class NaviCubeImplementation { public: explicit NaviCubeImplementation(Gui::View3DInventorViewer*); @@ -206,6 +203,9 @@ private: map m_LabelTextures; QMenu* m_Menu; + + std::shared_ptr m_flatButtonAnimation; + SbRotation m_flatButtonTargetOrientation; }; int NaviCubeImplementation::m_CubeWidgetSize = 132; @@ -1102,7 +1102,17 @@ bool NaviCubeImplementation::mouseReleased(short x, short y) else { rotation.scaleAngle(rotStepAngle); } - m_View3DInventorViewer->setCameraOrientation(rotation * m_View3DInventorViewer->getCameraOrientation()); + + // If the previous flat button animation is still active then apply the rotation to the + // previous target orientation, otherwise apply the rotation to the current camera orientation + if (m_flatButtonAnimation != nullptr && m_flatButtonAnimation->state() == QAbstractAnimation::Running) { + m_flatButtonTargetOrientation = rotation * m_flatButtonTargetOrientation; + } + else { + m_flatButtonTargetOrientation = rotation * m_View3DInventorViewer->getCameraOrientation(); + } + + m_flatButtonAnimation = m_View3DInventorViewer->setCameraOrientation(m_flatButtonTargetOrientation); } else { return false; diff --git a/src/Gui/Navigation/NavigationAnimation.cpp b/src/Gui/Navigation/NavigationAnimation.cpp index a4932d6825..943af87706 100644 --- a/src/Gui/Navigation/NavigationAnimation.cpp +++ b/src/Gui/Navigation/NavigationAnimation.cpp @@ -33,7 +33,7 @@ NavigationAnimation::NavigationAnimation(NavigationStyle* navigation) void NavigationAnimation::updateCurrentValue(const QVariant& value) { - if (state() == QAbstractAnimation::State::Stopped) { + if (state() != QAbstractAnimation::State::Running) { return; } update(value); diff --git a/src/Gui/Navigation/NavigationAnimation.h b/src/Gui/Navigation/NavigationAnimation.h index d14e8a366a..da337ce6ae 100644 --- a/src/Gui/Navigation/NavigationAnimation.h +++ b/src/Gui/Navigation/NavigationAnimation.h @@ -37,6 +37,7 @@ class GuiExport NavigationAnimation : protected QVariantAnimation Q_OBJECT public: explicit NavigationAnimation(NavigationStyle* navigation); + using QVariantAnimation::state; Q_SIGNALS: void interrupted(); diff --git a/src/Gui/Navigation/NavigationStyle.cpp b/src/Gui/Navigation/NavigationStyle.cpp index 32f9939e3c..3f48db267d 100644 --- a/src/Gui/Navigation/NavigationStyle.cpp +++ b/src/Gui/Navigation/NavigationStyle.cpp @@ -386,15 +386,15 @@ SoCamera* NavigationStyle::getCamera() const return this->viewer->getCamera(); } -void NavigationStyle::setCameraOrientation(const SbRotation& orientation, SbBool moveToCenter) +std::shared_ptr NavigationStyle::setCameraOrientation(const SbRotation& orientation, const SbBool moveToCenter) const { SoCamera* camera = getCamera(); if (!camera) - return; + return {}; animator->stop(); - SbVec3f focalPoint = getFocalPoint(); + const SbVec3f focalPoint = getFocalPoint(); SbVec3f translation(0, 0, 0); if (moveToCenter) { @@ -406,42 +406,48 @@ void NavigationStyle::setCameraOrientation(const SbRotation& orientation, SbBool } } - // Start an animation or set the pose directly + // Start an animation and return it if (isAnimationEnabled()) { - viewer->startAnimation(orientation, focalPoint, translation); + return viewer->startAnimation(orientation, focalPoint, translation); } - else { - // Distance from rotation center to camera position in camera coordinate system - SbVec3f rotationCenterDistanceCam = camera->focalDistance.getValue() * SbVec3f(0, 0, 1); - // Set to the given orientation - camera->orientation = orientation; + // or set the pose directly + + // Distance from rotation center to camera position in camera coordinate system + const SbVec3f rotationCenterDistanceCam = camera->focalDistance.getValue() * SbVec3f(0, 0, 1); - // Distance from rotation center to new camera position in global coordinate system - SbVec3f newRotationCenterDistance; - camera->orientation.getValue().multVec(rotationCenterDistanceCam, newRotationCenterDistance); + // Set to the given orientation + camera->orientation = orientation; - // Reposition camera so the rotation center stays in the same place - // Optionally add translation to move to center - camera->position = focalPoint + newRotationCenterDistance + translation; - } + // Distance from rotation center to new camera position in global coordinate system + SbVec3f newRotationCenterDistance; + camera->orientation.getValue().multVec(rotationCenterDistanceCam, newRotationCenterDistance); + + // Reposition camera so the rotation center stays in the same place + // Optionally add translation to move to center + camera->position = focalPoint + newRotationCenterDistance + translation; + + return {}; } -void NavigationStyle::translateCamera(const SbVec3f& translation) +std::shared_ptr NavigationStyle::translateCamera(const SbVec3f& translation) const { SoCamera* camera = getCamera(); if (!camera) - return; + return {}; animator->stop(); - // Start an animation or set the pose directly + // Start an animation and return it if (isAnimationEnabled()) { - viewer->startAnimation(camera->orientation.getValue(), SbVec3f(0, 0, 0), translation); - } - else { - camera->position = camera->position.getValue() + translation; + return viewer->startAnimation(camera->orientation.getValue(), SbVec3f(0, 0, 0), translation); } + + // or set the pose directly + + camera->position = camera->position.getValue() + translation; + + return {}; } void NavigationStyle::boxZoom(const SbBox2s& box) diff --git a/src/Gui/Navigation/NavigationStyle.h b/src/Gui/Navigation/NavigationStyle.h index cd2fccd0d3..802f497e32 100644 --- a/src/Gui/Navigation/NavigationStyle.h +++ b/src/Gui/Navigation/NavigationStyle.h @@ -150,8 +150,8 @@ public: SbVec3f getFocalPoint() const; SoCamera* getCamera() const; - void setCameraOrientation(const SbRotation& orientation, SbBool moveToCenter = false); - void translateCamera(const SbVec3f& translation); + std::shared_ptr setCameraOrientation(const SbRotation& orientation, SbBool moveToCenter = false) const; + std::shared_ptr translateCamera(const SbVec3f& translation) const; #if (COIN_MAJOR_VERSION * 100 + COIN_MINOR_VERSION * 10 + COIN_MICRO_VERSION < 403) void findBoundingSphere(); diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 10816de6e1..2f6c0e60ae 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -3216,9 +3216,9 @@ void View3DInventorViewer::pubSeekToPoint(const SbVec3f& pos) this->seekToPoint(pos); } -void View3DInventorViewer::setCameraOrientation(const SbRotation& orientation, bool moveToCenter) +std::shared_ptr View3DInventorViewer::setCameraOrientation(const SbRotation& orientation, const bool moveToCenter) const { - navigation->setCameraOrientation(orientation, moveToCenter); + return navigation->setCameraOrientation(orientation, moveToCenter); } void View3DInventorViewer::setCameraType(SoType type) @@ -3629,12 +3629,14 @@ bool View3DInventorViewer::isSpinning() const * @param translation An additional translation on top of the translation caused by the rotation around the rotation center * @param duration The duration in milliseconds * @param wait When false, start the animation and continue (asynchronous). When true, start the animation and wait for the animation to finish (synchronous) + * + * @return The started @class NavigationAnimation */ -void View3DInventorViewer::startAnimation(const SbRotation& orientation, +std::shared_ptr View3DInventorViewer::startAnimation(const SbRotation& orientation, const SbVec3f& rotationCenter, const SbVec3f& translation, int duration, - bool wait) + const bool wait) const { // Currently starts a FixedTimeAnimation. If there is going to be an additional animation like // FixedVelocityAnimation, check the animation type from a parameter and start the right animation @@ -3654,6 +3656,8 @@ void View3DInventorViewer::startAnimation(const SbRotation& orientation, navigation, orientation, rotationCenter, translation, duration, easingCurve); navigation->startAnimating(animation, wait); + + return animation; } /** diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 69b7bdbd46..0c53407303 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -75,7 +75,7 @@ namespace Base { } namespace Gui { - +class NavigationAnimation; class ViewProvider; class SoFCBackgroundGradient; class NavigationStyle; @@ -165,8 +165,8 @@ public: bool isSpinningAnimationEnabled() const; bool isAnimating() const; bool isSpinning() const; - void startAnimation(const SbRotation& orientation, const SbVec3f& rotationCenter, - const SbVec3f& translation, int duration = -1, bool wait = false); + std::shared_ptr startAnimation(const SbRotation& orientation, const SbVec3f& rotationCenter, + const SbVec3f& translation, int duration = -1, bool wait = false) const; void startSpinningAnimation(const SbVec3f& axis, float velocity); void stopAnimating(); @@ -386,10 +386,10 @@ public: /** * Set the camera's orientation. If isAnimationEnabled() returns - * \a true the reorientation is animated, otherwise its directly + * \a true the reorientation is animated and the animation is returned, otherwise its directly * set. */ - void setCameraOrientation(const SbRotation& orientation, bool moveToCenter = false); + std::shared_ptr setCameraOrientation(const SbRotation& orientation, bool moveToCenter = false) const; void setCameraType(SoType type) override; void moveCameraTo(const SbRotation& orientation, const SbVec3f& position, int duration = -1); /**