From f3c79302c4f35e4e199869e1947d09e8f904cee3 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Thu, 7 Nov 2024 18:58:31 +0100 Subject: [PATCH] Sketcher: Defining External geos. --- src/Mod/Sketcher/App/SketchObject.cpp | 41 +- src/Mod/Sketcher/App/SketchObjectPyImp.cpp | 17 +- src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp | 28 +- src/Mod/Sketcher/Gui/CommandCreateGeo.cpp | 4 +- .../Sketcher/Gui/DrawSketchHandlerExternal.h | 6 +- .../Gui/EditModeGeometryCoinManager.cpp | 3 + src/Mod/Sketcher/Gui/Resources/Sketcher.qrc | 1 + .../icons/geometry/Sketcher_External.svg | 174 +++++---- .../geometry/Sketcher_External_Constr.svg | 363 ++++++++++++++++++ 9 files changed, 523 insertions(+), 114 deletions(-) create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External_Constr.svg diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 9fe1d3e942..3c4424182e 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -320,7 +320,6 @@ static bool inline checkSmallEdge(const Part::TopoShape &s) { } void SketchObject::buildShape() { - // Shape.setValue(solvedSketch.toShape()); // We use the following instead to map element names @@ -1860,22 +1859,36 @@ int SketchObject::toggleConstruction(int GeoId) // no need to check input data validity as this is an sketchobject managed operation. Base::StateLocker lock(managedoperation, true); - const std::vector& vals = getInternalGeometry(); - if (GeoId < 0 || GeoId >= int(vals.size())) - return -1; + if (GeoId >= 0) { + const std::vector& vals = getInternalGeometry(); + if (GeoId >= int(vals.size())) { + return -1; + } - if (getGeometryFacade(GeoId)->isInternalAligned()) - return -1; + if (getGeometryFacade(GeoId)->isInternalAligned()) { + return -1; + } - // While it may seem that there is not a need to trigger an update at this time, because the - // solver has its own copy of the geometry, and updateColors of the viewprovider may be - // triggered by the clearselection of the UI command, this won't update the elements widget, in - // the accumulative of actions it is judged that it is worth to trigger an update here. + // While it may seem that there is not a need to trigger an update at this time, because the + // solver has its own copy of the geometry, and updateColors of the viewprovider may be + // triggered by the clearselection of the UI command, this won't update the elements widget, in + // the accumulative of actions it is judged that it is worth to trigger an update here. - std::unique_ptr geo(vals[GeoId]->clone()); - auto gft = GeometryFacade::getFacade(geo.get()); - gft->setConstruction(!gft->getConstruction()); - this->Geometry.set1Value(GeoId, std::move(geo)); + auto gft = GeometryFacade::getFacade(vals[GeoId]); + gft->setConstruction(!gft->getConstruction()); + this->Geometry.touch(); + } + else { + if (GeoId > GeoEnum::RefExt) { + return -1; + } + + const std::vector& extGeos = getExternalGeometry(); + auto geo = extGeos[-GeoId - 1]; + auto egf = ExternalGeometryFacade::getFacade(geo); + egf->setFlag(ExternalGeometryExtension::Defining, !egf->testFlag(ExternalGeometryExtension::Defining)); + this->ExternalGeo.touch(); + } solverNeedsUpdate = true; signalSolverUpdate(); // FIXME: In theory this is totally redundant, but now seems required diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp index 56e6af78da..e53c08095f 100644 --- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp +++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp @@ -557,8 +557,19 @@ PyObject* SketchObjectPy::addExternal(PyObject* args) { char* ObjectName; char* SubName; - if (!PyArg_ParseTuple(args, "ss", &ObjectName, &SubName)) { - return nullptr; + PyObject* defining; // this is an optional argument default false + bool isDefining; + if (!PyArg_ParseTuple(args, "ssO!", &ObjectName, &SubName, &PyBool_Type, &defining)) { + PyErr_Clear(); + if (!PyArg_ParseTuple(args, "ss", &ObjectName, &SubName)) { + return nullptr; + } + else { + isDefining = false; + } + } + else { + isDefining = Base::asBoolean(defining); } // get the target object for the external link @@ -579,7 +590,7 @@ PyObject* SketchObjectPy::addExternal(PyObject* args) } // add the external - if (skObj->addExternal(Obj, SubName) < 0) { + if (skObj->addExternal(Obj, SubName, isDefining) < 0) { std::stringstream str; str << "Not able to add external shape element " << SubName; PyErr_SetString(PyExc_ValueError, str.str().c_str()); diff --git a/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp b/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp index b33c7ddc6d..72db9b24d7 100644 --- a/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp +++ b/src/Mod/Sketcher/Gui/CommandAlterGeometry.cpp @@ -115,6 +115,7 @@ CmdSketcherToggleConstruction::CmdSketcherToggleConstruction() rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CreatePeriodicBSplineByInterpolation"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CompCreateBSpline"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_CarbonCopy"); + rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_External"); rcCmdMgr.addCommandMode("ToggleConstruction", "Sketcher_ToggleConstruction"); } @@ -158,8 +159,7 @@ void CmdSketcherToggleConstruction::activated(int iMsg) selection = getSelection().getSelectionEx(nullptr, Sketcher::SketchObject::getClassTypeId()); - Sketcher::SketchObject* Obj = - static_cast(selection[0].getObject()); + auto* Obj = static_cast(selection[0].getObject()); // only one sketch with its subelements are allowed to be selected if (selection.size() != 1) { @@ -185,13 +185,13 @@ void CmdSketcherToggleConstruction::activated(int iMsg) bool verticesonly = true; for (const auto& subname : SubNames) { - if (subname.size() > 4 && subname.substr(0, 4) == "Edge") { + if ((subname.size() > 4 && subname.substr(0, 4) == "Edge") + || (subname.size() > 12 && subname.substr(0, 12) == "ExternalEdge")) { verticesonly = false; } } - for (std::vector::const_iterator it = SubNames.begin(); it != SubNames.end(); - ++it) { + for (const auto& subname : SubNames) { // It was decided to provide a special behaviour: // Vertices will only be toggled to/from construction IF ONLY // vertices are within the group. @@ -205,13 +205,17 @@ void CmdSketcherToggleConstruction::activated(int iMsg) // only handle edges - if (it->size() > 4 && it->substr(0, 4) == "Edge") { - int GeoId = std::atoi(it->substr(4, 4000).c_str()) - 1; + if (subname.size() > 4 && subname.substr(0, 4) == "Edge") { + int geoId = std::atoi(subname.substr(4, 4000).c_str()) - 1; // issue the actual commands to toggle - Gui::cmdAppObjectArgs(selection[0].getObject(), "toggleConstruction(%d) ", GeoId); + Gui::cmdAppObjectArgs(Obj, "toggleConstruction(%d) ", geoId); } - else if (verticesonly && it->size() > 6 && it->substr(0, 6) == "Vertex") { - int vertexId = std::atoi(it->substr(6, 4000).c_str()) - 1; + else if (subname.size() > 12 && subname.substr(0, 12) == "ExternalEdge") { + int geoId = GeoEnum::RefExt - std::atoi(subname.substr(12, 4000).c_str()) + 1; + Gui::cmdAppObjectArgs(Obj, "toggleConstruction(%d) ", geoId); + } + else if (verticesonly && subname.size() > 6 && subname.substr(0, 6) == "Vertex") { + int vertexId = std::atoi(subname.substr(6, 4000).c_str()) - 1; int geoId; PointPos pos; @@ -221,9 +225,7 @@ void CmdSketcherToggleConstruction::activated(int iMsg) if (geo && geo->is()) { // issue the actual commands to toggle - Gui::cmdAppObjectArgs(selection[0].getObject(), - "toggleConstruction(%d) ", - geoId); + Gui::cmdAppObjectArgs(Obj, "toggleConstruction(%d) ", geoId); } } } diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 2fb6b8b295..9f9986080a 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -1436,7 +1436,7 @@ public: // ====================================================================================== -DEF_STD_CMD_A(CmdSketcherExternal) +DEF_STD_CMD_AU(CmdSketcherExternal) CmdSketcherExternal::CmdSketcherExternal() : Command("Sketcher_External") @@ -1452,6 +1452,8 @@ CmdSketcherExternal::CmdSketcherExternal() eType = ForEdit; } +CONSTRUCTION_UPDATE_ACTION(CmdSketcherExternal, "Sketcher_External") + void CmdSketcherExternal::activated(int iMsg) { Q_UNUSED(iMsg); diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h index 3048b68246..cc57af0df5 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h @@ -163,9 +163,11 @@ public: Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add external geometry")); Gui::cmdAppObjectArgs(sketchgui->getObject(), - "addExternal(\"%s\",\"%s\")", + "addExternal(\"%s\",\"%s\", %s)", msg.pObjectName, - msg.pSubName); + msg.pSubName, + isConstructionMode() ? "False" : "True"); + Gui::Command::commitCommand(); // adding external geometry does not require a solve() per se (the DoF is the diff --git a/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp index 02ba759674..afcd044ccf 100644 --- a/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp @@ -421,6 +421,9 @@ void EditModeGeometryCoinManager::updateGeometryColor(const GeoListFacade& geoli if (egf->testFlag(ExternalGeometryExtension::Missing)) { color[i] = drawingParameters.InvalidSketchColor; } + else if (egf->testFlag(ExternalGeometryExtension::Defining)) { + color[i] = drawingParameters.CurveColor; + } else { color[i] = drawingParameters.CurveExternalColor; } diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc index 4821e66fbb..037df41365 100644 --- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc +++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc @@ -199,6 +199,7 @@ icons/geometry/Sketcher_CreateTriangle_Constr.svg icons/geometry/Sketcher_Extend.svg icons/geometry/Sketcher_External.svg + icons/geometry/Sketcher_External_Constr.svg icons/geometry/Sketcher_Split.svg icons/geometry/Sketcher_ToggleConstruction.svg icons/geometry/Sketcher_ToggleConstruction_Constr.svg diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External.svg index a7aa4227c6..da8bb967f2 100644 --- a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External.svg +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External.svg @@ -1,18 +1,41 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - - - + id="g3849" + transform="translate(-60)"> + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External_Constr.svg b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External_Constr.svg new file mode 100644 index 0000000000..a7aa4227c6 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/geometry/Sketcher_External_Constr.svg @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [maxwxyz] + + + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Sketcher/Gui/Resources/icons/Sketcher_CreateArc.svg + + + FreeCAD LGPL2+ + + + 2023-12-19 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +