From f1e8605ea0ea557156206265e0a42f7b3fc1824e Mon Sep 17 00:00:00 2001 From: dish Date: Wed, 5 Jun 2024 09:08:45 +0000 Subject: [PATCH] [bos #35153][EDF](2023-T1) Construction grid. Add vertex snapping of already drawn sketch primitives. --- src/PartSet/PartSet_MouseProcessor.cpp | 7 +- src/PartSet/PartSet_MouseProcessor.h | 9 +- src/PartSet/PartSet_SketcherMgr.cpp | 107 +++++++++++++------- src/PartSet/PartSet_SketcherMgr.h | 7 +- src/PartSet/PartSet_WidgetBSplinePoints.cpp | 1 + src/PartSet/PartSet_WidgetPoint2d.cpp | 6 +- 6 files changed, 91 insertions(+), 46 deletions(-) diff --git a/src/PartSet/PartSet_MouseProcessor.cpp b/src/PartSet/PartSet_MouseProcessor.cpp index 2a68166c4..5c8dbc57e 100644 --- a/src/PartSet/PartSet_MouseProcessor.cpp +++ b/src/PartSet/PartSet_MouseProcessor.cpp @@ -47,15 +47,16 @@ double slightlyChangeVal(double theVal) } -bool PartSet_MouseProcessor::convertPointToLocal( +/*static*/ bool PartSet_MouseProcessor::convertPointToLocal( ModuleBase_IWorkshop* theWorkshop, const std::shared_ptr& theSketch, ModuleBase_IViewWindow* theWindow, const QPoint& theEventPos, double& theX, double& theY, + bool theSnap, bool theHighlight, bool theAddOffset -) const { +) { ModuleBase_IViewer* const viewer = theWorkshop->viewer(); if (!viewer) return false; @@ -68,7 +69,7 @@ bool PartSet_MouseProcessor::convertPointToLocal( const Handle(V3d_View) view = theWindow->v3dView(); PartSet_PreviewSketchPlane* previewPlane = module->sketchMgr()->previewSketchPlane(); - if (!aV3dViewer || !aV3dViewer->Grid()->IsActive() || previewPlane->getGridSnappingMode() == PartSet_PreviewSketchPlane::GridSnappingMode::Off) { + if (!theSnap || !aV3dViewer || !aV3dViewer->Grid()->IsActive() || previewPlane->getGridSnappingMode() == PartSet_PreviewSketchPlane::GridSnappingMode::Off) { const gp_Pnt mousePoint = PartSet_Tools::convertClickToPoint(theEventPos, view); PartSet_Tools::convertTo2D(mousePoint, theSketch, view, theX, theY); return true; diff --git a/src/PartSet/PartSet_MouseProcessor.h b/src/PartSet/PartSet_MouseProcessor.h index 4f759249f..597ecb492 100644 --- a/src/PartSet/PartSet_MouseProcessor.h +++ b/src/PartSet/PartSet_MouseProcessor.h @@ -65,23 +65,24 @@ public: ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) {} - protected: /// \brief Converts position of mouse cursor to local coordinates on sketch plane. /// Snaps on-sketch-plane-coordinates to closest construction grid node. /// \param theEventPos is position of mouse cursor. /// \param theX and \param theY are local coordinates on sketch plane. + /// \param theSnap theX and theY are snapped to construction grid if both theSnap == true and snapping is enabled. /// \param theHighlight If point is snapped, hightlight grid point. /// \param theAddOffset If true, serves as a remedy for odd crash during drawing of a line on a sketch. - /// \return true on success. - virtual bool convertPointToLocal( + /// \returns true on success. + static bool convertPointToLocal( ModuleBase_IWorkshop* theWorkshop, const std::shared_ptr& theSketch, // Passing by reference is intentionally. ModuleBase_IViewWindow* theWindow, const QPoint& theEventPos, double& theX, double& theY, + bool theSnap = true, bool theHighlight = false, bool theAddOffset = false - ) const; + ); }; #endif diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index 6b95b8a53..feb0af9dd 100644 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -177,6 +177,7 @@ PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule) myIsMouseOverWindow(false), myIsMouseOverViewProcessed(true), myIsPopupMenuActive(false), + myLastMouseEventType(QEvent::None), myPreviousUpdateViewerEnabled(true), myExternalPointsMgr(0), myNoDragMoving(false) @@ -384,11 +385,15 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE myMousePoint.setX(theEvent->x()); myMousePoint.setY(theEvent->y()); - if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent)) + if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent)) { + myLastMouseEventType = theEvent->type(); return; - //get2dPoint(theWnd, theEvent, myClickedPoint); - if (!(theEvent->buttons() & Qt::LeftButton)) + } + //get2dPoint(theWnd, theEvent->pos(), myClickedPoint); + if (!(theEvent->buttons() & Qt::LeftButton)) { + myLastMouseEventType = theEvent->type(); return; + } ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); ModuleBase_IViewer* aViewer = aWorkshop->viewer(); @@ -397,8 +402,10 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE ModuleBase_OperationFeature* aFOperation = dynamic_cast (getCurrentOperation()); - if (!aFOperation) + if (!aFOperation) { + myLastMouseEventType = theEvent->type(); return; + } bool isEditing = aFOperation->isEditOperation(); bool aCanDrag = aViewer->canDragByMouse(); @@ -412,21 +419,26 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE // If the current widget is a selector, do nothing, it processes the mouse press ModuleBase_ModelWidget* anActiveWidget = getActiveWidget(); if(anActiveWidget && anActiveWidget->isViewerSelector()) { + myLastMouseEventType = theEvent->type(); return; } } // Use only for sketch operations if (myCurrentSketch) { - if (!PartSet_Tools::sketchPlane(myCurrentSketch)) + if (!PartSet_Tools::sketchPlane(myCurrentSketch)) { + myLastMouseEventType = theEvent->type(); return; + } bool isSketcher = isSketchOperation(aFOperation); bool isSketchOpe = isNestedSketchOperation(aFOperation); // Avoid non-sketch operations - if ((!isSketchOpe) && (!isSketcher)) + if ((!isSketchOpe) && (!isSketcher)) { + myLastMouseEventType = theEvent->type(); return; + } // Ignore creation sketch operation if ((!isSketcher) && (!isEditing)) { @@ -445,6 +457,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE aProcessor->mouseReleased(theWnd, theEvent); } } + myLastMouseEventType = theEvent->type(); return; } bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); @@ -455,11 +468,13 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE // commit previous operation if (!aFOperation->commit()) aFOperation->abort(); + + myLastMouseEventType = theEvent->type(); return; } // Init flyout point for radius rotation FeaturePtr aFeature = myCurrentSelection.begin().key(); - get2dPoint(theWnd, theEvent, myCurrentPoint); + get2dPoint(theWnd, theEvent->pos(), myCurrentPoint); if (isSketcher) { if (aCanDrag) { myIsDragging = true; @@ -523,6 +538,8 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE } } } + + myLastMouseEventType = theEvent->type(); } void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) @@ -535,12 +552,16 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse bool aWasDragging = myIsDragging; myIsDragging = false; - if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) + if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) { + myLastMouseEventType = theEvent->type(); return; + } // if mouse is pressed when it was over view and at release the mouse is out of view, do nothing - if (!myIsMouseOverViewProcessed) + if (!myIsMouseOverViewProcessed) { + myLastMouseEventType = theEvent->type(); return; + } ModuleBase_OperationFeature* aOp = dynamic_cast(getCurrentOperation()); @@ -555,8 +576,10 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse else myNoDragMoving = false; - if (myNoDragMoving) + if (myNoDragMoving) { + myLastMouseEventType = theEvent->type(); return; + } else { ModuleBase_OperationFeature* aOp = dynamic_cast(getCurrentOperation()); @@ -571,8 +594,10 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse myNoDragMoving = !myNoDragMoving; else myNoDragMoving = false; - if (myNoDragMoving) + if (myNoDragMoving) { + myLastMouseEventType = theEvent->type(); return; + } else { restoreSelection(myCurrentSelection); myCurrentSelection.clear(); @@ -627,13 +652,16 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse if (MyModeByDrag && aOp) { aViewer->enableMultiselection(true); QString aOpId = aOp->id(); - if (aOpId == "Sketch") + if (aOpId == "Sketch") { + myLastMouseEventType = theEvent->type(); return; + } QPoint aPnt(theEvent->x(), theEvent->y()); anActiveWidget = getActiveWidget(); if ((aPnt == myMousePoint) && anActiveWidget) { aOp->abort(); + myLastMouseEventType = theEvent->type(); return; } bool aCanRestart = !anActiveWidget && !isEditing; @@ -641,6 +669,7 @@ void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouse module()->launchOperation(aOpId, true); } } + myLastMouseEventType = theEvent->type(); } void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) @@ -659,15 +688,16 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve } #endif - if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent)) + if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent)) { + myLastMouseEventType = theEvent->type(); return; + } ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); XGUI_ModuleConnector* aConnector = dynamic_cast(aWorkshop); XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer(); if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) { - #ifdef DRAGGING_DEBUG QTime t; t.start(); @@ -707,9 +737,11 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve // deselected). This flag should be restored in the slot, processed the mouse release signal. ModuleBase_Operation* aCurrentOperation = getCurrentOperation(); if (!aCurrentOperation) { + myLastMouseEventType = theEvent->type(); return; } if (isSketchOperation(aCurrentOperation)) { + myLastMouseEventType = theEvent->type(); return; // No edit operation activated } @@ -719,13 +751,12 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve #endif Handle(V3d_View) aView = theWnd->v3dView(); - Point aMousePnt; - get2dPoint(theWnd, theEvent, aMousePnt); + Point aMousePnt, aHoverPnt; + get2dPoint(theWnd, theEvent->pos(), aMousePnt, true /*theSnap*/); + get2dPoint(theWnd, theEvent->pos(), aHoverPnt, myLastMouseEventType == QEvent::MouseMove /*theSnap*/); - std::shared_ptr anOriginalPosition = std::shared_ptr( - new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY)); - std::shared_ptr aCurrentPosition = std::shared_ptr( - new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY)); + auto anOriginalPosition = std::shared_ptr(new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY)); + auto aCurrentPosition = std::shared_ptr(new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY)); // 3. the flag to disable the update viewer should be set in order to avoid blinking in the // viewer happens by deselect/select the modified objects. The flag should be restored after @@ -748,8 +779,10 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve anAttLast = anAttributes.end(); for (; anAttIt != anAttLast; anAttIt++) { AttributePtr anAttr = anAttIt->first; + if (anAttr.get() == NULL) continue; + std::string aAttrId = anAttr->id(); DataPtr aData = aFeature->data(); if (aData->isValid()) { @@ -758,8 +791,7 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve aPoint->attributeType() == GeomDataAPI_Point2DArray::typeId()) { bool isImmutable = aPoint->setImmutable(true); - std::shared_ptr aMessage = std::shared_ptr - (new ModelAPI_ObjectMovedMessage(this)); + auto aMessage = std::shared_ptr(new ModelAPI_ObjectMovedMessage(this)); aMessage->setMovedAttribute(aPoint, anAttIt->second); aMessage->setOriginalPosition(anOriginalPosition); aMessage->setCurrentPosition(aCurrentPosition); @@ -771,13 +803,12 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve } } } - else { + else + { // Process selection by feature - std::shared_ptr aSketchFeature = - std::dynamic_pointer_cast(aFeature); + auto aSketchFeature = std::dynamic_pointer_cast(aFeature); if (aSketchFeature) { - std::shared_ptr aMessage = std::shared_ptr - (new ModelAPI_ObjectMovedMessage(this)); + auto aMessage = std::shared_ptr(new ModelAPI_ObjectMovedMessage(this)); aMessage->setMovedObject(aFeature); aMessage->setOriginalPosition(anOriginalPosition); aMessage->setCurrentPosition(aCurrentPosition); @@ -806,8 +837,10 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve #endif myDragDone = true; - myCurrentPoint = aMousePnt; + myCurrentPoint = aHoverPnt; } + + myLastMouseEventType = theEvent->type(); } void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) @@ -830,11 +863,15 @@ void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMo PartSet_WidgetEditor* anEditor = dynamic_cast(aWgt); if (anEditor) anEditor->showPopupEditor(); + + myLastMouseEventType = theEvent->type(); return; } } } } + + myLastMouseEventType = theEvent->type(); } void PartSet_SketcherMgr::onApplicationStarted() @@ -892,14 +929,14 @@ void PartSet_SketcherMgr::onAfterContextMenu() myIsPopupMenuActive = false; } -void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, - Point& thePoint) +void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, const QPoint& theEventPos, Point& thePoint, bool theSnap) { - Handle(V3d_View) aView = theWnd->v3dView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - double aX, anY; - PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, anY); - thePoint.setValue(aX, anY); + double aX = 0, aY = 0; // Coords at sketch plane. + bool success = PartSet_MouseProcessor::convertPointToLocal(workshop()->moduleConnector(), myCurrentSketch, theWnd, theEventPos, aX, aY, theSnap, true, false); + if (!success) + return; + + thePoint.setValue(aX, aY); } void PartSet_SketcherMgr::launchEditing() diff --git a/src/PartSet/PartSet_SketcherMgr.h b/src/PartSet/PartSet_SketcherMgr.h index 312021601..39bad597d 100644 --- a/src/PartSet/PartSet_SketcherMgr.h +++ b/src/PartSet/PartSet_SketcherMgr.h @@ -56,6 +56,7 @@ #include #include #include +#include #include @@ -427,8 +428,9 @@ private: /// Converts mouse position to 2d coordinates. /// Member myCurrentSketch has to be correctly defined - void get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, - Point& thePoint); + /// \param theSnap If true and snapping is enabled, snaps coordinates to the grid. + void get2dPoint(ModuleBase_IViewWindow* theWnd, const QPoint& theEventPos, + Point& thePoint, bool theSnap = false); /// Show distance value editor if it is a distance operation and all attribute references /// are filled by preseletion @@ -500,6 +502,7 @@ private: bool myIsMouseOverWindow; /// the state that the mouse over the view /// the state whether the over view state is processed by mouseMove method bool myIsMouseOverViewProcessed; + QEvent::Type myLastMouseEventType; bool myIsPopupMenuActive; /// the state of the popup menu is shown Point myCurrentPoint; //Point myClickedPoint; diff --git a/src/PartSet/PartSet_WidgetBSplinePoints.cpp b/src/PartSet/PartSet_WidgetBSplinePoints.cpp index 192078248..a05ad5d82 100644 --- a/src/PartSet/PartSet_WidgetBSplinePoints.cpp +++ b/src/PartSet/PartSet_WidgetBSplinePoints.cpp @@ -562,6 +562,7 @@ void PartSet_WidgetBSplinePoints::mouseMoved(ModuleBase_IViewWindow* theWindow, theWindow, theEvent->pos(), aX, aY, + true, true ); diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index dfaccf2ed..f097f9591 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -366,8 +366,10 @@ bool PartSet_WidgetPoint2D::restoreValueCustom() std::shared_ptr aData = myFeature->data(); AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( aData->attribute(attributeID())); + double aValueX = aPoint->isInitialized() ? aPoint->x() : 0.; double aValueY = aPoint->isInitialized() ? aPoint->y() : 0.; + myXSpin->setValue(aValueX); myYSpin->setValue(aValueY); @@ -571,7 +573,7 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo } } if (!aHasPoint) { - bool success = convertPointToLocal(myWorkshop, mySketch, theWindow, theEvent->pos(), aX, aY, false); + bool success = PartSet_MouseProcessor::convertPointToLocal(myWorkshop, mySketch, theWindow, theEvent->pos(), aX, aY, true, false); if (!success) return; } @@ -742,7 +744,7 @@ void PartSet_WidgetPoint2D::mouseMoved(ModuleBase_IViewWindow* theWindow, QMouse return; double aX = 0, aY = 0; // Coords at sketch plane. - bool success = convertPointToLocal(myWorkshop, mySketch, theWindow, theEvent->pos(), aX, aY, true, true); + bool success = PartSet_MouseProcessor::convertPointToLocal(myWorkshop, mySketch, theWindow, theEvent->pos(), aX, aY, true, true, true); if (!success) return; -- 2.39.2