4242#include " timelinehighlightwidget.h"
4343#include " GUI/dialogsinterface.h"
4444#include " themesupport.h"
45+ #include < QtMath>
46+ #include < cmath>
4547
4648KeysView::KeysView (BoxScrollWidget *boxesListVisible,
4749 QWidget *parent) :
@@ -792,7 +794,9 @@ void KeysView::handleMouseMove(const QPoint &pos,
792794 dFrame = dX/mPixelsPerFrame ;
793795 mValueInput .setDisplayedValue (dFrame);
794796 }
797+ const auto mods = QApplication::keyboardModifiers ();
795798 const bool ctrlPt = mGPressedPoint && mGPressedPoint ->isCtrlPt ();
799+ const bool shiftPressed = mods & Qt::ShiftModifier;
796800 if (!ctrlPt) dFrame = round (dFrame);
797801 const qreal dDFrame = dFrame - mMoveDFrame ;
798802 const int iDDFrame = qRound (dDFrame);
@@ -809,8 +813,31 @@ void KeysView::handleMouseMove(const QPoint &pos,
809813 const QPointF saved = mGPressedPoint ->getSavedFrameAndValue ();
810814 const qreal rawFrame = saved.x () + dFrameV;
811815 const qreal rawValue = saved.y () + dValue;
812- const qreal newFrame = qBound (mMinMoveFrame , rawFrame, mMaxMoveFrame );
813- const qreal newValue = qBound (mMinMoveVal , rawValue, mMaxMoveVal );
816+ qreal newFrame = qBound (mMinMoveFrame , rawFrame, mMaxMoveFrame );
817+ qreal newValue = qBound (mMinMoveVal , rawValue, mMaxMoveVal );
818+ if (shiftPressed) {
819+ if (const auto parentKey = mGPressedPoint ->getParentKey ()) {
820+ const qreal keyFrame = parentKey->getRelFrame ();
821+ const qreal keyValue = parentKey->getValueForGraph ();
822+ const qreal dx = newFrame - keyFrame;
823+ const qreal dy = newValue - keyValue;
824+ const qreal dxPx = dx * mPixelsPerFrame ;
825+ const qreal dyPx = -dy * mPixelsPerValUnit ;
826+ const qreal lengthPx = qSqrt (dxPx*dxPx + dyPx*dyPx);
827+ if (lengthPx > 0.0 ) {
828+ constexpr qreal snapStep = 15.0 ;
829+ const qreal angleDeg = qRadiansToDegrees (qAtan2 (dyPx, dxPx));
830+ const qreal snappedDeg = std::round (angleDeg / snapStep) * snapStep;
831+ const qreal snappedRad = qDegreesToRadians (snappedDeg);
832+ const qreal snappedDxPx = lengthPx * qCos (snappedRad);
833+ const qreal snappedDyPx = lengthPx * qSin (snappedRad);
834+ newFrame = keyFrame + snappedDxPx / mPixelsPerFrame ;
835+ newValue = keyValue - snappedDyPx / mPixelsPerValUnit ;
836+ }
837+ }
838+ }
839+ newFrame = qBound (mMinMoveFrame , newFrame, mMaxMoveFrame );
840+ newValue = qBound (mMinMoveVal , newValue, mMaxMoveVal );
814841 mGPressedPoint ->setFrameAndValue (newFrame, newValue,
815842 mPixelsPerFrame ,
816843 mPixelsPerValUnit );
0 commit comments