diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 1e9cc01984..dc3aa1699d 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1153,12 +1153,7 @@ void SketchObject::reverseAngleConstraintToSupplementary(Constraint* constr, int { std::swap(constr->First, constr->Second); std::swap(constr->FirstPos, constr->SecondPos); - if (constr->FirstPos == constr->SecondPos) { - constr->FirstPos = (constr->FirstPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start; - } - else { - constr->SecondPos = (constr->SecondPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start; - } + constr->FirstPos = (constr->FirstPos == Sketcher::PointPos::start) ? Sketcher::PointPos::end : Sketcher::PointPos::start; // Edit the expression if any, else modify constraint value directly if (constraintHasExpression(constNum)) { diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index aa597f70fd..c16e538737 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -52,6 +52,7 @@ #include "ViewProviderSketch.h" #include "ui_InsertDatum.h" #include +#include "SnapManager.h" // Remove this after pre-commit hook is activated // clang-format off @@ -1033,7 +1034,7 @@ public: Gui::Selection().rmvSelectionGate(); } - void mouseMove(Base::Vector2d /*onSketchPos*/) override + void mouseMove(SnapManager::SnapHandle snapHandle) override {} bool pressButton(Base::Vector2d /*onSketchPos*/) override @@ -1835,13 +1836,16 @@ public: } } - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { if (hasBeenAborted()) { resetTool(); return; } + //All snap Positions except of edges, because it results in jumps on angle constraints + SnapType mask = static_cast(static_cast(SnapType::All) & ~static_cast(SnapType::Edge)); + Base::Vector2d onSketchPos = snapHandle.compute(mask); previousOnSketchPos = onSketchPos; //Change distance constraint based on position of mouse. diff --git a/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp b/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp index a5a135fee7..0a13e5d849 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp @@ -39,6 +39,7 @@ #include "DrawSketchHandler.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" using namespace std; @@ -765,9 +766,10 @@ public: ~DrawSketchHandlerBSplineInsertKnot() override {} - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { auto bsp = static_cast(Obj->getGeometry(GeoId)); + Base::Vector2d onSketchPos = snapHandle.compute(); // get closest parameter using OCC // TODO: This is called every time we move the cursor. Can get overwhelming. diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index 12ed1e1946..1eb1d33858 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -64,6 +64,7 @@ #include "DrawSketchHandlerRotate.h" #include "DrawSketchHandlerScale.h" #include "DrawSketchHandlerSymmetry.h" +#include "SnapManager.h" // Hint: this is to prevent to re-format big parts of the file. Remove it later again. // clang-format off @@ -1211,9 +1212,10 @@ public: Snap5Degree }; - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { using std::numbers::pi; + Base::Vector2d onSketchPos = snapHandle.compute(); if (Mode == STATUS_SEEK_First) { @@ -1789,9 +1791,10 @@ public: Snap5Degree }; - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { using std::numbers::pi; + Base::Vector2d onSketchPos = snapHandle.compute(); if (Mode == STATUS_SEEK_First) { diff --git a/src/Mod/Sketcher/Gui/DrawSketchControllableHandler.h b/src/Mod/Sketcher/Gui/DrawSketchControllableHandler.h index c1fa7151a2..2067ed4397 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchControllableHandler.h +++ b/src/Mod/Sketcher/Gui/DrawSketchControllableHandler.h @@ -27,6 +27,7 @@ #include #include "DrawSketchDefaultHandler.h" +#include "SnapManager.h" namespace SketcherGui { @@ -79,8 +80,9 @@ public: /** @name functions NOT intended for specialisation or further overriding */ //@{ - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { + Base::Vector2d onSketchPos = snapHandle.compute(); toolWidgetManager.mouseMoved(onSketchPos); toolWidgetManager.enforceControlParameters(onSketchPos); diff --git a/src/Mod/Sketcher/Gui/DrawSketchController.h b/src/Mod/Sketcher/Gui/DrawSketchController.h index 7e676094cc..f2fede79f7 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchController.h +++ b/src/Mod/Sketcher/Gui/DrawSketchController.h @@ -333,7 +333,8 @@ public: handler->reset(); // reset of handler to restart. } - handler->mouseMove(prevCursorPosition); + auto snapHandle = std::make_unique(nullptr, prevCursorPosition); + handler->mouseMove(*snapHandle); } //@} @@ -534,7 +535,9 @@ public: virtual void afterHandlerModeChanged() { if (handler && (!handler->isState(SelectModeT::End) || handler->continuousMode)) { - handler->mouseMove(prevCursorPosition); + auto snapHandle = + std::make_unique(nullptr, prevCursorPosition); + handler->mouseMove(*snapHandle); } } @@ -624,7 +627,8 @@ protected: /// change void finishControlsChanged() { - handler->mouseMove(prevCursorPosition); + auto snapHandle = std::make_unique(nullptr, prevCursorPosition); + handler->mouseMove(*snapHandle); auto currentstate = handler->state(); // ensure that object at point is preselected, so that autoconstraints are generated @@ -645,7 +649,9 @@ protected: // reset) if (shouldProcessLastPosWithNextState) { // mode has changed, so reprocess the previous position to the new widget state - handler->mouseMove(prevCursorPosition); + auto snapHandle = + std::make_unique(nullptr, prevCursorPosition); + handler->mouseMove(*snapHandle); } } diff --git a/src/Mod/Sketcher/Gui/DrawSketchDefaultHandler.h b/src/Mod/Sketcher/Gui/DrawSketchDefaultHandler.h index 9ce22093e6..a1cd631128 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchDefaultHandler.h +++ b/src/Mod/Sketcher/Gui/DrawSketchDefaultHandler.h @@ -39,6 +39,7 @@ #include "AutoConstraint.h" #include "DrawSketchHandler.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" #include "Utils.h" @@ -425,9 +426,9 @@ public: * overridden/specialised instead. */ //@{ - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { - updateDataAndDrawToPosition(onSketchPos); + updateDataAndDrawToPosition(snapHandle.compute()); } bool pressButton(Base::Vector2d onSketchPos) override diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.h b/src/Mod/Sketcher/Gui/DrawSketchHandler.h index 1df188fc7a..935b9078ba 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.h @@ -39,6 +39,7 @@ #include "AutoConstraint.h" #include "Utils.h" +#include "SnapManager.h" class QWidget; @@ -154,7 +155,7 @@ public: void setSketchGui(ViewProviderSketch* vp); void deactivate() override; - virtual void mouseMove(Base::Vector2d pos) = 0; + virtual void mouseMove(SnapManager::SnapHandle snapHandle) = 0; virtual bool pressButton(Base::Vector2d pos) = 0; virtual bool releaseButton(Base::Vector2d pos) = 0; diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfEllipse.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfEllipse.h index 810a3fb748..14bf10d685 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfEllipse.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfEllipse.h @@ -34,6 +34,7 @@ #include "GeometryCreationMode.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" namespace SketcherGui @@ -67,9 +68,10 @@ public: STATUS_Close }; - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { using std::numbers::pi; + Base::Vector2d onSketchPos = snapHandle.compute(); if (Mode == STATUS_SEEK_First) { setPositionText(onSketchPos); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfHyperbola.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfHyperbola.h index 565609b819..39503a7b2e 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfHyperbola.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfHyperbola.h @@ -36,6 +36,7 @@ #include "GeometryCreationMode.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" namespace SketcherGui @@ -64,8 +65,9 @@ public: STATUS_Close }; - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { + Base::Vector2d onSketchPos = snapHandle.compute(); if (Mode == STATUS_SEEK_First) { setPositionText(onSketchPos); seekAndRenderAutoConstraint(sugConstr1, onSketchPos, Base::Vector2d(0.f, 0.f)); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfParabola.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfParabola.h index b5b273f5b8..9edaf33fcd 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfParabola.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerArcOfParabola.h @@ -37,6 +37,7 @@ #include "GeometryCreationMode.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" namespace SketcherGui { @@ -67,8 +68,9 @@ public: STATUS_Close }; - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { + Base::Vector2d onSketchPos = snapHandle.compute(); if (Mode == STATUS_SEEK_First) { setPositionText(onSketchPos); seekAndRenderAutoConstraint(sugConstr1, onSketchPos, Base::Vector2d(0.f, 0.f)); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerCarbonCopy.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerCarbonCopy.h index 40e1ec98ba..89d4b4fc68 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerCarbonCopy.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerCarbonCopy.h @@ -39,6 +39,7 @@ #include "GeometryCreationMode.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" namespace SketcherGui @@ -127,9 +128,9 @@ public: Gui::Selection().rmvSelectionGate(); } - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { - Q_UNUSED(onSketchPos); + Q_UNUSED(snapHandle); if (Gui::Selection().getPreselection().pObjectName) { applyCursor(); } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerExtend.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerExtend.h index e05bd4917a..324e013848 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerExtend.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerExtend.h @@ -34,6 +34,7 @@ #include "GeometryCreationMode.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" namespace SketcherGui @@ -107,9 +108,9 @@ public: STATUS_SEEK_Second, }; - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { - Q_UNUSED(onSketchPos); + Base::Vector2d onSketchPos = snapHandle.compute(); using std::numbers::pi; diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h index fc3591236b..97d67a5d31 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h @@ -41,6 +41,7 @@ #include "Utils.h" #include "ViewProviderSketch.h" #include +#include "SnapManager.h" namespace SketcherGui @@ -133,9 +134,9 @@ public: Gui::Selection().rmvSelectionGate(); } - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { - Q_UNUSED(onSketchPos); + Q_UNUSED(snapHandle); if (Gui::Selection().getPreselection().pObjectName) { applyCursor(); } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerLineSet.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerLineSet.h index bc4f902921..b8f2bf022a 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerLineSet.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerLineSet.h @@ -39,6 +39,7 @@ #include "GeometryCreationMode.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" namespace SketcherGui @@ -181,16 +182,18 @@ public: else { EditCurve.resize(32); } - mouseMove(onSketchPos); // trigger an update of EditCurve + auto snapHandle = std::make_unique(nullptr, onSketchPos); + mouseMove(*snapHandle); // trigger an update of EditCurve } else { DrawSketchHandler::registerPressedKey(pressed, key); } } - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { using std::numbers::pi; + Base::Vector2d onSketchPos = snapHandle.compute(); suppressTransition = false; if (Mode == STATUS_SEEK_First) { @@ -711,7 +714,8 @@ public: SegmentMode = SEGMENT_MODE_Line; SnapMode = SNAP_MODE_Free; EditCurve[1] = EditCurve[0]; - mouseMove(onSketchPos); // trigger an update of EditCurve + auto snapHandle = std::make_unique(nullptr, onSketchPos); + mouseMove(*snapHandle); // trigger an update of EditCurve } } diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerSplitting.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerSplitting.h index 2d052ed4e0..4b900218a8 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerSplitting.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerSplitting.h @@ -34,6 +34,7 @@ #include "GeometryCreationMode.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" namespace SketcherGui @@ -100,9 +101,9 @@ public: Gui::Selection().rmvSelectionGate(); } - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { - Q_UNUSED(onSketchPos); + Q_UNUSED(snapHandle); } bool pressButton(Base::Vector2d onSketchPos) override diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerTrimming.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerTrimming.h index d2a359a6b5..35e9616bb8 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerTrimming.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerTrimming.h @@ -37,6 +37,7 @@ #include "GeometryCreationMode.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "SnapManager.h" namespace SketcherGui @@ -88,9 +89,9 @@ public: Gui::Selection().rmvSelectionGate(); } - void mouseMove(Base::Vector2d onSketchPos) override + void mouseMove(SnapManager::SnapHandle snapHandle) override { - Q_UNUSED(onSketchPos); + Base::Vector2d onSketchPos = snapHandle.compute(); if (mousePressed) { executeCommands(onSketchPos); return; diff --git a/src/Mod/Sketcher/Gui/SnapManager.cpp b/src/Mod/Sketcher/Gui/SnapManager.cpp index 7c66724a13..4b894bc2fb 100644 --- a/src/Mod/Sketcher/Gui/SnapManager.cpp +++ b/src/Mod/Sketcher/Gui/SnapManager.cpp @@ -184,55 +184,62 @@ SnapManager::SnapManager(ViewProviderSketch& vp) SnapManager::~SnapManager() {} -bool SnapManager::snap(double& x, double& y) +Base::Vector2d SnapManager::snap(Base::Vector2d inputPos, SnapType mask) { if (!snapRequested) { - return false; + return inputPos; } - // In order of priority : + Base::Vector2d snapPos; + + // In order of priority: // 1 - Snap at an angle - if (angleSnapRequested && QApplication::keyboardModifiers() == Qt::ControlModifier) { - return snapAtAngle(x, y); + if ((static_cast(mask) & static_cast(SnapType::Angle)) && angleSnapRequested + && QApplication::keyboardModifiers() == Qt::ControlModifier + && snapAtAngle(inputPos, snapPos)) { + return snapPos; } else { lastMouseAngle = 0.0; } // 2 - Snap to objects - if (snapToObjectsRequested && snapToObject(x, y)) { - return true; + if ((static_cast(mask) + & (static_cast(SnapType::Point) | static_cast(SnapType::Edge))) + && snapToObjectsRequested && snapToObject(inputPos, snapPos, mask)) { + return snapPos; } // 3 - Snap to grid - if (snapToGridRequested /*&& viewProvider.ShowGrid.getValue() */) { // Snap to grid is enabled - // even if the grid is not - // visible. - return snapToGrid(x, y); + if ((static_cast(mask) & static_cast(SnapType::Grid)) && snapToGridRequested + && snapToGrid(inputPos, snapPos) + /*&& viewProvider.ShowGrid.getValue() */) { // Snap to grid is + // enabled + // even if the grid is not + // visible. + + return snapPos; } - return false; + return inputPos; } -bool SnapManager::snapAtAngle(double& x, double& y) +bool SnapManager::snapAtAngle(Base::Vector2d inputPos, Base::Vector2d& snapPos) { - Base::Vector2d pointToOverride(x, y); - double length = (pointToOverride - referencePoint).Length(); + double length = (inputPos - referencePoint).Length(); - double angle1 = (pointToOverride - referencePoint).Angle(); + double angle1 = (inputPos - referencePoint).Angle(); double angle2 = angle1 + (angle1 < 0. ? 2 : -2) * std::numbers::pi; lastMouseAngle = abs(angle1 - lastMouseAngle) < abs(angle2 - lastMouseAngle) ? angle1 : angle2; double angle = round(lastMouseAngle / snapAngle) * snapAngle; - pointToOverride = referencePoint + length * Base::Vector2d(cos(angle), sin(angle)); - x = pointToOverride.x; - y = pointToOverride.y; + snapPos = referencePoint + length * Base::Vector2d(cos(angle), sin(angle)); return true; } -bool SnapManager::snapToObject(double& x, double& y) +bool SnapManager::snapToObject(Base::Vector2d inputPos, Base::Vector2d& snapPos, SnapType mask) { Sketcher::SketchObject* Obj = viewProvider.getSketchObject(); int geoId = GeoEnum::GeoUndef; @@ -242,7 +249,7 @@ bool SnapManager::snapToObject(double& x, double& y) int CrsId = ViewProviderSketchSnapAttorney::getPreselectCross(viewProvider); int CrvId = ViewProviderSketchSnapAttorney::getPreselectCurve(viewProvider); - if (CrsId == 0 || VtId >= 0) { + if ((static_cast(mask) & static_cast(SnapType::Point)) && (CrsId == 0 || VtId >= 0)) { if (CrsId == 0) { geoId = Sketcher::GeoEnum::RtPnt; posId = Sketcher::PointPos::start; @@ -251,78 +258,81 @@ bool SnapManager::snapToObject(double& x, double& y) Obj->getGeoVertexIndex(VtId, geoId, posId); } - x = Obj->getPoint(geoId, posId).x; - y = Obj->getPoint(geoId, posId).y; + snapPos.x = Obj->getPoint(geoId, posId).x; + snapPos.y = Obj->getPoint(geoId, posId).y; return true; } - else if (CrsId == 1) { // H_Axis - y = 0; - return true; - } - else if (CrsId == 2) { // V_Axis - x = 0; - return true; - } - else if (CrvId >= 0 || CrvId <= Sketcher::GeoEnum::RefExt) { // Curves - - const Part::Geometry* geo = Obj->getGeometry(CrvId); - - Base::Vector3d pointToOverride(x, y, 0.); - - double pointParam = 0.0; - auto curve = dynamic_cast(geo); - if (curve) { - try { - curve->closestParameter(pointToOverride, pointParam); - pointToOverride = curve->pointAtParameter(pointParam); - } - catch (Base::CADKernelError& e) { - e.reportException(); - return false; - } - - // If it is a line, then we check if we need to snap to the middle. - if (geo->is()) { - const Part::GeomLineSegment* line = static_cast(geo); - snapToLineMiddle(pointToOverride, line); - } - - // If it is an arc, then we check if we need to snap to the middle (not the center). - if (geo->is()) { - const Part::GeomArcOfCircle* arc = static_cast(geo); - snapToArcMiddle(pointToOverride, arc); - } - - x = pointToOverride.x; - y = pointToOverride.y; - + else if (static_cast(mask) & static_cast(SnapType::Edge)) { + if (CrsId == 1) { // H_Axis + snapPos.y = 0; return true; } - } + else if (CrsId == 2) { // V_Axis + snapPos.x = 0; + return true; + } + else if (CrvId >= 0 || CrvId <= Sketcher::GeoEnum::RefExt) { // Curves + const Part::Geometry* geo = Obj->getGeometry(CrvId); + + Base::Vector3d pointToOverride(inputPos.x, inputPos.y, 0.); + + double pointParam = 0.0; + auto curve = dynamic_cast(geo); + if (curve) { + try { + curve->closestParameter(pointToOverride, pointParam); + pointToOverride = curve->pointAtParameter(pointParam); + } + catch (Base::CADKernelError& e) { + e.reportException(); + return false; + } + + // If it is a line, then we check if we need to snap to the middle. + if (geo->is()) { + const Part::GeomLineSegment* line = + static_cast(geo); + snapToLineMiddle(pointToOverride, line); + } + + // If it is an arc, then we check if we need to snap to the middle (not the center). + if (geo->is()) { + const Part::GeomArcOfCircle* arc = + static_cast(geo); + snapToArcMiddle(pointToOverride, arc); + } + + snapPos.x = pointToOverride.x; + snapPos.y = pointToOverride.y; + + return true; + } + } + } return false; } -bool SnapManager::snapToGrid(double& x, double& y) +bool SnapManager::snapToGrid(Base::Vector2d inputPos, Base::Vector2d& snapPos) { // Snap Tolerance in pixels const double snapTol = viewProvider.getGridSize() / 5; - double tmpX = x, tmpY = y; + double tmpX = inputPos.x, tmpY = inputPos.y; viewProvider.getClosestGridPoint(tmpX, tmpY); bool snapped = false; // Check if x within snap tolerance - if (x < tmpX + snapTol && x > tmpX - snapTol) { - x = tmpX; // Snap X Mouse Position + if (inputPos.x < tmpX + snapTol && inputPos.x > tmpX - snapTol) { + snapPos.x = tmpX; // Snap X Mouse Position snapped = true; } // Check if y within snap tolerance - if (y < tmpY + snapTol && y > tmpY - snapTol) { - y = tmpY; // Snap Y Mouse Position + if (inputPos.y < tmpY + snapTol && inputPos.y > tmpY - snapTol) { + snapPos.y = tmpY; // Snap Y Mouse Position snapped = true; } @@ -389,3 +399,11 @@ void SnapManager::setAngleSnapping(bool enable, Base::Vector2d referencepoint) angleSnapRequested = enable; referencePoint = referencepoint; } + +Base::Vector2d SketcherGui::SnapManager::SnapHandle::compute(SnapType mask) +{ + if (!mgr) { + return cursorPos; + } + return mgr->snap(cursorPos, mask); +} diff --git a/src/Mod/Sketcher/Gui/SnapManager.h b/src/Mod/Sketcher/Gui/SnapManager.h index 400b27aea8..562004aaa0 100644 --- a/src/Mod/Sketcher/Gui/SnapManager.h +++ b/src/Mod/Sketcher/Gui/SnapManager.h @@ -51,6 +51,17 @@ private: friend class SnapManager; }; +enum class SnapType +{ + None = 0x0, + Angle = 0x1, + Point = 0x2, + Edge = 0x4, + Grid = 0x8, + + All = Angle | Point | Edge | Grid +}; + /* This class is used to manage the overriding of mouse pointer coordinates in Sketcher * (in Edit-Mode) depending on the situation. Those situations are in priority order : * 1 - Snap at angle: For tools like Slot, Arc, Line, Ellipse, this enables to constrain the angle @@ -99,16 +110,29 @@ public: explicit SnapManager(ViewProviderSketch& vp); ~SnapManager(); - bool snap(double& x, double& y); - bool snapAtAngle(double& x, double& y); - bool snapToObject(double& x, double& y); - bool snapToGrid(double& x, double& y); + Base::Vector2d snap(Base::Vector2d inputPos, SnapType mask); + bool snapAtAngle(Base::Vector2d inputPos, Base::Vector2d& snapPos); + bool snapToObject(Base::Vector2d inputPos, Base::Vector2d& snapPos, SnapType mask); + bool snapToGrid(Base::Vector2d inputPos, Base::Vector2d& snapPos); bool snapToLineMiddle(Base::Vector3d& pointToOverride, const Part::GeomLineSegment* line); bool snapToArcMiddle(Base::Vector3d& pointToOverride, const Part::GeomArcOfCircle* arc); void setAngleSnapping(bool enable, Base::Vector2d referencepoint); + struct SnapHandle + { + SnapManager* mgr = nullptr; + Base::Vector2d cursorPos; + + SnapHandle(SnapManager* m, const Base::Vector2d& cursorPos) + : mgr(m) + , cursorPos(cursorPos) + {} + + Base::Vector2d compute(SnapType mask = SnapType::All); + }; + private: /// Reference to ViewProviderSketch in order to access the public and the Attorney Interface ViewProviderSketch& viewProvider; diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index a5f83934bf..ab6ec1d169 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -963,9 +963,10 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe } } + std::unique_ptr snapHandle; try { getCoordsOnSketchPlane(pos, normal, x, y); - snapManager->snap(x, y); + snapHandle = std::make_unique(snapManager.get(), Base::Vector2d(x, y)); } catch (const Base::ZeroDivisionError&) { return false; @@ -1436,10 +1437,11 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor SbLine line; getProjectingLine(cursorPos, viewer, line); - double x, y; + std::unique_ptr snapHandle; try { + double x, y; getCoordsOnSketchPlane(line.getPosition(), line.getDirection(), x, y); - snapManager->snap(x, y); + snapHandle = std::make_unique(snapManager.get(), Base::Vector2d(x, y)); } catch (const Base::ZeroDivisionError&) { return false; @@ -1488,27 +1490,31 @@ bool ViewProviderSketch::mouseMove(const SbVec2s& cursorPos, Gui::View3DInventor } resetPreselectPoint(); return true; - case STATUS_SELECT_Constraint: + case STATUS_SELECT_Constraint: { setSketchMode(STATUS_SKETCH_DragConstraint); drag.DragConstraintSet = preselection.PreselectConstraintSet; - drag.xInit = x; - drag.yInit = y; + Base::Vector2d selectionPos = snapHandle->compute(); + drag.xInit = selectionPos.x; + drag.yInit = selectionPos.y; resetPreselectPoint(); return true; + } case STATUS_SKETCH_Drag: { - doDragStep(x, y); + Base::Vector2d dragPos = snapHandle->compute(); + doDragStep(dragPos.x, dragPos.y); return true; } case STATUS_SKETCH_DragConstraint: if (!drag.DragConstraintSet.empty()) { + Base::Vector2d dragPos = snapHandle->compute(); auto idset = drag.DragConstraintSet; for (int id : idset) { - moveConstraint(id, Base::Vector2d(x, y)); + moveConstraint(id, Base::Vector2d(dragPos.x, dragPos.y)); } } return true; case STATUS_SKETCH_UseHandler: - sketchHandler->mouseMove(Base::Vector2d(x, y)); + sketchHandler->mouseMove(*snapHandle); if (preselectChanged) { editCoinManager->drawConstraintIcons(); sketchHandler->applyCursor(); @@ -1617,7 +1623,7 @@ void ViewProviderSketch::initDragging(int geoId, Sketcher::PointPos pos, Gui::Vi getProjectingLine(DoubleClick::prvCursorPos, viewer, line2); getCoordsOnSketchPlane( line2.getPosition(), line2.getDirection(), drag.xInit, drag.yInit); - snapManager->snap(drag.xInit, drag.yInit); + snapManager->snap(Base::Vector2d(drag.xInit, drag.yInit), SnapType::All); }; if (drag.Dragged.size() == 1 && pos == Sketcher::PointPos::none) {