| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <FCConfig.h> |
| |
|
| | #include <memory> |
| |
|
| | #include <QApplication> |
| | #include <QClipboard> |
| | #include <QMessageBox> |
| |
|
| | #include <Inventor/SbString.h> |
| |
|
| | #include <App/Application.h> |
| | #include <Base/Console.h> |
| | #include <Base/Reader.h> |
| | #include <Base/Writer.h> |
| | #include <Gui/Action.h> |
| | #include <Gui/Application.h> |
| | #include <Gui/BitmapFactory.h> |
| | #include <Gui/CommandT.h> |
| | #include <Gui/Document.h> |
| | #include <Gui/MainWindow.h> |
| | #include <Gui/Notifications.h> |
| | #include <Gui/View3DInventor.h> |
| | #include <Gui/Selection/Selection.h> |
| | #include <Gui/Selection/SelectionObject.h> |
| | #include <Mod/Sketcher/App/PythonConverter.h> |
| | #include <Mod/Sketcher/App/SketchObject.h> |
| | #include <Mod/Sketcher/App/SolverGeometryExtension.h> |
| | #include <Gui/Application.h> |
| | #include <Base/ServiceProvider.h> |
| | #include <App/Services.h> |
| |
|
| | #include "CommandSketcherTools.h" |
| | #include "DrawSketchHandler.h" |
| | #include "SketchRectangularArrayDialog.h" |
| | #include "Utils.h" |
| | #include "ViewProviderSketch.h" |
| | #include <Inventor/actions/SoGetBoundingBoxAction.h> |
| |
|
| |
|
| | #include "DrawSketchHandlerTranslate.h" |
| | #include "DrawSketchHandlerOffset.h" |
| | #include "DrawSketchHandlerRotate.h" |
| | #include "DrawSketchHandlerScale.h" |
| | #include "DrawSketchHandlerSymmetry.h" |
| | #include "SnapManager.h" |
| |
|
| | |
| | |
| | using namespace std; |
| | using namespace SketcherGui; |
| | using namespace Sketcher; |
| |
|
| | std::vector<int> getListOfSelectedGeoIds(bool forceInternalSelection) |
| | { |
| | std::vector<int> listOfGeoIds = {}; |
| |
|
| | |
| | std::vector<Gui::SelectionObject> selection; |
| | selection = Gui::Selection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); |
| |
|
| | |
| | if (selection.size() != 1) { |
| | QMessageBox::warning(Gui::getMainWindow(), |
| | QObject::tr("Wrong Selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| | return {}; |
| | } |
| |
|
| | |
| | auto* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject()); |
| | const std::vector<std::string>& subNames = selection[0].getSubNames(); |
| | if (!subNames.empty()) { |
| |
|
| | for (auto& name : subNames) { |
| | if (name.size() > 4 && name.substr(0, 4) == "Edge") { |
| | int geoId = std::atoi(name.substr(4, 4000).c_str()) - 1; |
| | listOfGeoIds.push_back(geoId); |
| | } |
| | else if (name.size() > 12 && name.substr(0, 12) == "ExternalEdge") { |
| | int geoId = -std::atoi(name.substr(12, 4000).c_str()) - 2; |
| | listOfGeoIds.push_back(geoId); |
| | } |
| | else if (name.size() > 6 && name.substr(0, 6) == "Vertex") { |
| | |
| | int VtId = std::atoi(name.substr(6, 4000).c_str()) - 1; |
| | int geoId; |
| | Sketcher::PointPos PosId; |
| | Obj->getGeoVertexIndex(VtId, geoId, PosId); |
| | if (isPoint(*Obj->getGeometry(geoId))) { |
| | if (geoId >= 0) { |
| | listOfGeoIds.push_back(geoId); |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | if (forceInternalSelection) { |
| | const size_t loopSize = listOfGeoIds.size(); |
| | for (size_t i = 0; i < loopSize; i++) { |
| | const Part::Geometry* geo = Obj->getGeometry(listOfGeoIds[i]); |
| | if (isEllipse(*geo) || isArcOfEllipse(*geo) || isArcOfHyperbola(*geo) || isArcOfParabola(*geo) || isBSplineCurve(*geo)) { |
| | const std::vector<Sketcher::Constraint*>& constraints = Obj->Constraints.getValues(); |
| | for (const auto constr : constraints) { |
| | if (constr->Type == InternalAlignment && constr->Second == listOfGeoIds[i]) { |
| | if (std::ranges::find(listOfGeoIds, constr->First) == listOfGeoIds.end()) { |
| | |
| | listOfGeoIds.push_back(constr->First); |
| | } |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | if (listOfGeoIds.empty()) { |
| | Gui::NotifyUserError(Obj, |
| | QT_TRANSLATE_NOOP("Notifications", "Invalid selection"), |
| | QT_TRANSLATE_NOOP("Notifications", "Selection has no valid geometries.")); |
| | } |
| |
|
| | return listOfGeoIds; |
| | } |
| |
|
| | Sketcher::SketchObject* getSketchObject() |
| | { |
| | Gui::Document* doc = Gui::Application::Instance->activeDocument(); |
| | ReleaseHandler(doc); |
| | auto* vp = static_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit()); |
| | return vp->getSketchObject(); |
| | } |
| |
|
| | |
| |
|
| | |
| |
|
| | bool copySelectionToClipboard(Sketcher::SketchObject* obj) { |
| | std::vector<int> listOfGeoId = getListOfSelectedGeoIds(true); |
| | if (listOfGeoId.empty()) { return false; } |
| | sort(listOfGeoId.begin(), listOfGeoId.end()); |
| |
|
| | |
| | std::vector<Part::Geometry*> shapeGeometry; |
| | for (auto geoId : listOfGeoId) { |
| | Part::Geometry* geoNew = obj->getGeometry(geoId)->copy(); |
| | shapeGeometry.push_back(geoNew); |
| | } |
| | std::string geosAsStr = Sketcher::PythonConverter::convert( |
| | "objectStr", |
| | shapeGeometry, |
| | Sketcher::PythonConverter::Mode::OmitInternalGeometry); |
| |
|
| | |
| | std::vector<Sketcher::Constraint*> shapeConstraints; |
| | for (auto constr : obj->Constraints.getValues()) { |
| |
|
| | auto isSelectedGeoOrAxis = [](const std::vector<int>& vec, int value) { |
| | return (std::ranges::find(vec, value) != vec.end()) |
| | || value == GeoEnum::GeoUndef || value == GeoEnum::RtPnt |
| | || value == GeoEnum::VAxis || value == GeoEnum::HAxis; |
| | }; |
| |
|
| | if (!isSelectedGeoOrAxis(listOfGeoId, constr->First) |
| | || !isSelectedGeoOrAxis(listOfGeoId, constr->Second) |
| | || !isSelectedGeoOrAxis(listOfGeoId, constr->Third)) { |
| | continue; |
| | } |
| |
|
| | Constraint* temp = constr->copy(); |
| | for (size_t j = 0; j < listOfGeoId.size(); j++) { |
| | if (temp->First == listOfGeoId[j]) { |
| | temp->First = j; |
| | } |
| | if (temp->Second == listOfGeoId[j]) { |
| | temp->Second = j; |
| | } |
| | if (temp->Third == listOfGeoId[j]) { |
| | temp->Third = j; |
| | } |
| | } |
| | shapeConstraints.push_back(temp); |
| | } |
| | std::string cstrAsStr = Sketcher::PythonConverter::convert("objectStr", shapeConstraints, Sketcher::PythonConverter::GeoIdMode::AddLastGeoIdToGeoIds); |
| |
|
| | std::string exportedData = "# Copied from sketcher. From:\n#objectStr = " + Gui::Command::getObjectCmd(obj) + "\n" |
| | + geosAsStr + "\n" + cstrAsStr; |
| |
|
| | if (!exportedData.empty()) { |
| | QClipboard* clipboard = QGuiApplication::clipboard(); |
| | clipboard->setText(QString::fromStdString(exportedData)); |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|
| | DEF_STD_CMD_A(CmdSketcherCopyClipboard) |
| |
|
| | CmdSketcherCopyClipboard::CmdSketcherCopyClipboard() |
| | : Command("Sketcher_CopyClipboard") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("C&opy Elements"); |
| | sToolTipText = QT_TR_NOOP("Copies the selected geometries and constraints to the clipboard"); |
| | sWhatsThis = "Sketcher_CopyClipboard"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "edit-copy"; |
| | sAccel = keySequenceToAccel(QKeySequence::Copy); |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherCopyClipboard::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | copySelectionToClipboard(getSketchObject()); |
| | } |
| |
|
| | bool CmdSketcherCopyClipboard::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherCut) |
| |
|
| | CmdSketcherCut::CmdSketcherCut() |
| | : Command("Sketcher_Cut") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("C&ut Elements"); |
| | sToolTipText = QT_TR_NOOP("Cuts the selected geometries and constraints to the clipboard"); |
| | sWhatsThis = "Sketcher_Cut"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "edit-cut"; |
| | sAccel = keySequenceToAccel(QKeySequence::Cut); |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherCut::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | if (copySelectionToClipboard(getSketchObject())) { |
| |
|
| | Gui::Document* doc = getActiveGuiDocument(); |
| | ReleaseHandler(doc); |
| | auto* vp = static_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit()); |
| |
|
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cut in Sketcher")); |
| | vp->deleteSelected(); |
| | Gui::Command::commitCommand(); |
| | } |
| | } |
| |
|
| | bool CmdSketcherCut::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherPaste) |
| |
|
| | CmdSketcherPaste::CmdSketcherPaste() |
| | : Command("Sketcher_Paste") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("P&aste Elements"); |
| | sToolTipText = QT_TR_NOOP("Pastes the geometries and constraints from the clipboard into the sketch"); |
| | sWhatsThis = "Sketcher_Paste"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "edit-paste"; |
| | sAccel = keySequenceToAccel(QKeySequence::Paste); |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherPaste::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | Gui::Document* doc = getActiveGuiDocument(); |
| | ReleaseHandler(doc); |
| | auto* vp = static_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit()); |
| | Sketcher::SketchObject* obj = vp->getSketchObject(); |
| |
|
| | std::string data = QGuiApplication::clipboard()->text().toStdString(); |
| | if (data.find("# Copied from sketcher.", 0) == std::string::npos) { |
| | return; |
| | } |
| | data = "objectStr = " + Gui::Command::getObjectCmd(obj) +"\n" + data; |
| |
|
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Paste in Sketcher")); |
| |
|
| | Gui::Command::doCommand(Gui::Command::Doc, data.c_str()); |
| |
|
| | obj->solve(true); |
| | vp->draw(false, false); |
| |
|
| | Gui::Command::commitCommand(); |
| | } |
| |
|
| | bool CmdSketcherPaste::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | |
| | DEF_STD_CMD_A(CmdSketcherSelectConstraints) |
| |
|
| | CmdSketcherSelectConstraints::CmdSketcherSelectConstraints() |
| | : Command("Sketcher_SelectConstraints") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Associated Constraints"); |
| | sToolTipText = |
| | QT_TR_NOOP("Selects the constraints associated with the selected geometrical elements"); |
| | sWhatsThis = "Sketcher_SelectConstraints"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_SelectConstraints"; |
| | sAccel = "Z, K"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectConstraints::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| |
|
| | |
| | std::vector<Gui::SelectionObject> selection; |
| | selection = getSelection().getSelectionEx(nullptr, Sketcher::SketchObject::getClassTypeId()); |
| |
|
| | |
| | Gui::Document* doc = Gui::Application::Instance->activeDocument(); |
| | SketcherGui::ReleaseHandler(doc); |
| |
|
| | |
| | if (selection.size() != 1) { |
| | Gui::TranslatedUserWarning(doc->getDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| |
|
| | return; |
| | } |
| |
|
| | |
| | const std::vector<std::string>& SubNames = selection[0].getSubNames(); |
| | Sketcher::SketchObject* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject()); |
| | const std::vector<Sketcher::Constraint*>& constraints = Obj->Constraints.getValues(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | std::vector<std::string> constraintSubNames; |
| | |
| | int i = 0; |
| | for (auto const& constraint : constraints) { |
| | auto isRelated = [&] (const std::string& subName){ |
| | int geoId; |
| | PointPos pointPos; |
| | Data::IndexedName name = Obj->checkSubName(subName.c_str()); |
| | if (!Obj->geoIdFromShapeType(name, geoId, pointPos)) { |
| | return false; |
| | } |
| | if (pointPos != PointPos::none) { |
| | return constraint->involvesGeoIdAndPosId(geoId, pointPos); |
| | } else { |
| | return constraint->involvesGeoId(geoId); |
| | } |
| | }; |
| |
|
| | if (std::ranges::any_of(SubNames, isRelated)) { |
| | constraintSubNames.push_back(PropertyConstraintList::getConstraintName(i)); |
| | } |
| | ++i; |
| | } |
| |
|
| | if (!constraintSubNames.empty()) |
| | Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); |
| | } |
| |
|
| | bool CmdSketcherSelectConstraints::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | |
| | DEF_STD_CMD_A(CmdSketcherSelectOrigin) |
| |
|
| | CmdSketcherSelectOrigin::CmdSketcherSelectOrigin() |
| | : Command("Sketcher_SelectOrigin") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Origin"); |
| | sToolTipText = QT_TR_NOOP("Selects the local origin point of the sketch"); |
| | sWhatsThis = "Sketcher_SelectOrigin"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_SelectOrigin"; |
| | sAccel = "Z, O"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectOrigin::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | Sketcher::SketchObject * Obj = getSketchObject(); |
| | |
| | |
| | |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| | std::stringstream ss; |
| |
|
| | ss << "RootPoint"; |
| |
|
| | if (Gui::Selection().isSelected(doc_name.c_str(), obj_name.c_str(), ss.str().c_str())) |
| | Gui::Selection().rmvSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); |
| | else |
| | Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); |
| | } |
| |
|
| | bool CmdSketcherSelectOrigin::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | |
| | DEF_STD_CMD_A(CmdSketcherSelectVerticalAxis) |
| |
|
| | CmdSketcherSelectVerticalAxis::CmdSketcherSelectVerticalAxis() |
| | : Command("Sketcher_SelectVerticalAxis") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Vertical Axis"); |
| | sToolTipText = QT_TR_NOOP("Selects the local vertical axis of the sketch"); |
| | sWhatsThis = "Sketcher_SelectVerticalAxis"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_SelectVerticalAxis"; |
| | sAccel = "Z, V"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectVerticalAxis::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| | std::stringstream ss; |
| |
|
| | ss << "V_Axis"; |
| |
|
| | if (Gui::Selection().isSelected(doc_name.c_str(), obj_name.c_str(), ss.str().c_str())) |
| | Gui::Selection().rmvSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); |
| | else |
| | Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); |
| | } |
| |
|
| | bool CmdSketcherSelectVerticalAxis::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | |
| | DEF_STD_CMD_A(CmdSketcherSelectHorizontalAxis) |
| |
|
| | CmdSketcherSelectHorizontalAxis::CmdSketcherSelectHorizontalAxis() |
| | : Command("Sketcher_SelectHorizontalAxis") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Horizontal Axis"); |
| | sToolTipText = QT_TR_NOOP("Selects the local horizontal axis of the sketch"); |
| | sWhatsThis = "Sketcher_SelectHorizontalAxis"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_SelectHorizontalAxis"; |
| | sAccel = "Z, H"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectHorizontalAxis::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| | std::stringstream ss; |
| |
|
| | ss << "H_Axis"; |
| |
|
| | if (Gui::Selection().isSelected(doc_name.c_str(), obj_name.c_str(), ss.str().c_str())) |
| | Gui::Selection().rmvSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); |
| | else |
| | Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str()); |
| | } |
| |
|
| | bool CmdSketcherSelectHorizontalAxis::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherSelectRedundantConstraints) |
| |
|
| | CmdSketcherSelectRedundantConstraints::CmdSketcherSelectRedundantConstraints() |
| | : Command("Sketcher_SelectRedundantConstraints") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Redundant Constraints"); |
| | sToolTipText = QT_TR_NOOP("Selects all redundant constraints"); |
| | sWhatsThis = "Sketcher_SelectRedundantConstraints"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_SelectRedundantConstraints"; |
| | sAccel = "Z, P, R"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectRedundantConstraints::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| |
|
| | |
| | const std::vector<int>& solverredundant = Obj->getLastRedundant(); |
| | const std::vector<Sketcher::Constraint*>& vals = Obj->Constraints.getValues(); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | |
| | std::vector<std::string> constraintSubNames; |
| |
|
| | int i = 0; |
| | for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end(); |
| | ++it, ++i) { |
| | for (std::vector<int>::const_iterator itc = solverredundant.begin(); |
| | itc != solverredundant.end(); |
| | ++itc) { |
| | if ((*itc) - 1 == i) { |
| | constraintSubNames.push_back( |
| | Sketcher::PropertyConstraintList::getConstraintName(i)); |
| | break; |
| | } |
| | } |
| | } |
| |
|
| | if (!constraintSubNames.empty()) |
| | Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); |
| | } |
| |
|
| | bool CmdSketcherSelectRedundantConstraints::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherSelectMalformedConstraints) |
| |
|
| | CmdSketcherSelectMalformedConstraints::CmdSketcherSelectMalformedConstraints() |
| | : Command("Sketcher_SelectMalformedConstraints") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Malformed Constraints"); |
| | sToolTipText = QT_TR_NOOP("Selects all malformed constraints"); |
| | sWhatsThis = "Sketcher_SelectMalformedConstraints"; |
| | sStatusTip = sToolTipText; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectMalformedConstraints::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| |
|
| | |
| | const std::vector<int>& solvermalformed = Obj->getLastMalformedConstraints(); |
| | const std::vector<Sketcher::Constraint*>& vals = Obj->Constraints.getValues(); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | |
| | std::vector<std::string> constraintSubNames; |
| | int i = 0; |
| | for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end(); |
| | ++it, ++i) { |
| | for (std::vector<int>::const_iterator itc = solvermalformed.begin(); |
| | itc != solvermalformed.end(); |
| | ++itc) { |
| | if ((*itc) - 1 == i) { |
| | constraintSubNames.push_back( |
| | Sketcher::PropertyConstraintList::getConstraintName(i)); |
| | break; |
| | } |
| | } |
| | } |
| |
|
| | if (!constraintSubNames.empty()) |
| | Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); |
| | } |
| |
|
| | bool CmdSketcherSelectMalformedConstraints::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherSelectPartiallyRedundantConstraints) |
| |
|
| | CmdSketcherSelectPartiallyRedundantConstraints::CmdSketcherSelectPartiallyRedundantConstraints() |
| | : Command("Sketcher_SelectPartiallyRedundantConstraints") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Partially Redundant Constraints"); |
| | sToolTipText = QT_TR_NOOP("Selects all partially redundant constraints"); |
| | sWhatsThis = "Sketcher_SelectPartiallyRedundantConstraints"; |
| | sStatusTip = sToolTipText; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectPartiallyRedundantConstraints::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| |
|
| | |
| | const std::vector<int>& solverpartiallyredundant = |
| | Obj->getLastPartiallyRedundant(); |
| | const std::vector<Sketcher::Constraint*>& vals = Obj->Constraints.getValues(); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | |
| | std::vector<std::string> constraintSubNames; |
| | int i = 0; |
| | for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end(); |
| | ++it, ++i) { |
| | for (std::vector<int>::const_iterator itc = solverpartiallyredundant.begin(); |
| | itc != solverpartiallyredundant.end(); |
| | ++itc) { |
| | if ((*itc) - 1 == i) { |
| | constraintSubNames.push_back( |
| | Sketcher::PropertyConstraintList::getConstraintName(i)); |
| | break; |
| | } |
| | } |
| | } |
| |
|
| | if (!constraintSubNames.empty()) |
| | Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); |
| | } |
| |
|
| | bool CmdSketcherSelectPartiallyRedundantConstraints::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherSelectConflictingConstraints) |
| |
|
| | CmdSketcherSelectConflictingConstraints::CmdSketcherSelectConflictingConstraints() |
| | : Command("Sketcher_SelectConflictingConstraints") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Conflicting Constraints"); |
| | sToolTipText = QT_TR_NOOP("Selects all conflicting constraints"); |
| | sWhatsThis = "Sketcher_SelectConflictingConstraints"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_SelectConflictingConstraints"; |
| | sAccel = "Z, P, C"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectConflictingConstraints::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| |
|
| | |
| | const std::vector<int>& solverconflicting = Obj->getLastConflicting(); |
| | const std::vector<Sketcher::Constraint*>& vals = Obj->Constraints.getValues(); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | |
| | std::vector<std::string> constraintSubNames; |
| | int i = 0; |
| | for (std::vector<Sketcher::Constraint*>::const_iterator it = vals.begin(); it != vals.end(); |
| | ++it, ++i) { |
| | for (std::vector<int>::const_iterator itc = solverconflicting.begin(); |
| | itc != solverconflicting.end(); |
| | ++itc) { |
| | if ((*itc) - 1 == i) { |
| | constraintSubNames.push_back( |
| | Sketcher::PropertyConstraintList::getConstraintName(i)); |
| | break; |
| | } |
| | } |
| | } |
| |
|
| | if (!constraintSubNames.empty()) |
| | Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames); |
| | } |
| |
|
| | bool CmdSketcherSelectConflictingConstraints::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherSelectElementsAssociatedWithConstraints) |
| |
|
| | CmdSketcherSelectElementsAssociatedWithConstraints:: |
| | CmdSketcherSelectElementsAssociatedWithConstraints() |
| | : Command("Sketcher_SelectElementsAssociatedWithConstraints") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Associated Geometry"); |
| | sToolTipText = |
| | QT_TR_NOOP("Selects the geometrical elements associated with the selected constraints"); |
| | sWhatsThis = "Sketcher_SelectElementsAssociatedWithConstraints"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_SelectElementsAssociatedWithConstraints"; |
| | sAccel = "Z, E"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | std::vector<Gui::SelectionObject> selection = Gui::Selection().getSelectionEx(); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | const std::vector<std::string>& SubNames = selection[0].getSubNames(); |
| | const std::vector<Sketcher::Constraint*>& vals = Obj->Constraints.getValues(); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| | std::stringstream ss; |
| |
|
| | std::vector<std::string> elementSubNames; |
| | |
| | for (std::vector<std::string>::const_iterator it = SubNames.begin(); it != SubNames.end(); |
| | ++it) { |
| | |
| | if (it->size() > 10 && it->substr(0, 10) == "Constraint") { |
| | int ConstrId = Sketcher::PropertyConstraintList::getIndexFromConstraintName(*it); |
| |
|
| | if (ConstrId < static_cast<int>(vals.size())) { |
| | if (vals[ConstrId]->First != GeoEnum::GeoUndef) { |
| | ss.str(std::string()); |
| |
|
| | switch (vals[ConstrId]->FirstPos) { |
| | case Sketcher::PointPos::none: |
| | ss << "Edge" << vals[ConstrId]->First + 1; |
| | break; |
| | case Sketcher::PointPos::start: |
| | case Sketcher::PointPos::end: |
| | case Sketcher::PointPos::mid: |
| | int vertex = Obj->getVertexIndexGeoPos(vals[ConstrId]->First, |
| | vals[ConstrId]->FirstPos); |
| | if (vertex > -1) |
| | ss << "Vertex" << vertex + 1; |
| | break; |
| | } |
| | elementSubNames.push_back(ss.str()); |
| | } |
| |
|
| | if (vals[ConstrId]->Second != GeoEnum::GeoUndef) { |
| | ss.str(std::string()); |
| |
|
| | switch (vals[ConstrId]->SecondPos) { |
| | case Sketcher::PointPos::none: |
| | ss << "Edge" << vals[ConstrId]->Second + 1; |
| | break; |
| | case Sketcher::PointPos::start: |
| | case Sketcher::PointPos::end: |
| | case Sketcher::PointPos::mid: |
| | int vertex = Obj->getVertexIndexGeoPos(vals[ConstrId]->Second, |
| | vals[ConstrId]->SecondPos); |
| | if (vertex > -1) |
| | ss << "Vertex" << vertex + 1; |
| | break; |
| | } |
| |
|
| | elementSubNames.push_back(ss.str()); |
| | } |
| |
|
| | if (vals[ConstrId]->Third != GeoEnum::GeoUndef) { |
| | ss.str(std::string()); |
| |
|
| | switch (vals[ConstrId]->ThirdPos) { |
| | case Sketcher::PointPos::none: |
| | ss << "Edge" << vals[ConstrId]->Third + 1; |
| | break; |
| | case Sketcher::PointPos::start: |
| | case Sketcher::PointPos::end: |
| | case Sketcher::PointPos::mid: |
| | int vertex = Obj->getVertexIndexGeoPos(vals[ConstrId]->Third, |
| | vals[ConstrId]->ThirdPos); |
| | if (vertex > -1) |
| | ss << "Vertex" << vertex + 1; |
| | break; |
| | } |
| |
|
| | elementSubNames.push_back(ss.str()); |
| | } |
| | } |
| | } |
| | } |
| |
|
| | if (elementSubNames.empty()) { |
| | Gui::TranslatedUserWarning(Obj, |
| | QObject::tr("No constraint selected"), |
| | QObject::tr("At least one constraint must be selected")); |
| | } |
| | else { |
| | Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), elementSubNames); |
| | } |
| | } |
| |
|
| | bool CmdSketcherSelectElementsAssociatedWithConstraints::isActive() |
| | { |
| | return isCommandNeedingConstraintActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherSelectElementsWithDoFs) |
| |
|
| | CmdSketcherSelectElementsWithDoFs::CmdSketcherSelectElementsWithDoFs() |
| | : Command("Sketcher_SelectElementsWithDoFs") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Select Under-Constrained Elements"); |
| | sToolTipText = QT_TR_NOOP("Selects geometrical elements where the solver still detects " |
| | "unconstrained degrees of freedom"); |
| | sWhatsThis = "Sketcher_SelectElementsWithDoFs"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_SelectElementsWithDoFs"; |
| | sAccel = "Z, F"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSelectElementsWithDoFs::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | getSelection().clearSelection(); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | std::string doc_name = Obj->getDocument()->getName(); |
| | std::string obj_name = Obj->getNameInDocument(); |
| | std::stringstream ss; |
| |
|
| | auto geos = Obj->getInternalGeometry(); |
| |
|
| | std::vector<std::string> elementSubNames; |
| |
|
| | auto testselectvertex = [&Obj, &ss, &elementSubNames](int geoId, PointPos pos) { |
| | ss.str(std::string()); |
| |
|
| | int vertex = Obj->getVertexIndexGeoPos(geoId, pos); |
| | if (vertex > -1) { |
| | ss << "Vertex" << vertex + 1; |
| |
|
| | elementSubNames.push_back(ss.str()); |
| | } |
| | }; |
| |
|
| | auto testselectedge = [&ss, &elementSubNames](int geoId) { |
| | ss.str(std::string()); |
| |
|
| | ss << "Edge" << geoId + 1; |
| | elementSubNames.push_back(ss.str()); |
| | }; |
| |
|
| | int geoid = 0; |
| |
|
| | for (auto geo : geos) { |
| | if (geo) { |
| | if (geo->hasExtension(Sketcher::SolverGeometryExtension::getClassTypeId())) { |
| |
|
| | auto solvext = std::static_pointer_cast<const Sketcher::SolverGeometryExtension>( |
| | geo->getExtension(Sketcher::SolverGeometryExtension::getClassTypeId()).lock()); |
| |
|
| | if (solvext->getGeometry() |
| | == Sketcher::SolverGeometryExtension::NotFullyConstraint) { |
| | |
| | |
| | if (solvext->getEdge() == SolverGeometryExtension::Dependent) |
| | testselectedge(geoid); |
| | if (solvext->getStart() == SolverGeometryExtension::Dependent) |
| | testselectvertex(geoid, Sketcher::PointPos::start); |
| | if (solvext->getEnd() == SolverGeometryExtension::Dependent) |
| | testselectvertex(geoid, Sketcher::PointPos::end); |
| | if (solvext->getMid() == SolverGeometryExtension::Dependent) |
| | testselectvertex(geoid, Sketcher::PointPos::mid); |
| | } |
| | } |
| | } |
| |
|
| | geoid++; |
| | } |
| |
|
| | if (!elementSubNames.empty()) { |
| | Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), elementSubNames); |
| | } |
| | } |
| |
|
| | bool CmdSketcherSelectElementsWithDoFs::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherRestoreInternalAlignmentGeometry) |
| |
|
| | CmdSketcherRestoreInternalAlignmentGeometry::CmdSketcherRestoreInternalAlignmentGeometry() |
| | : Command("Sketcher_RestoreInternalAlignmentGeometry") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Toggle Internal Geometry"); |
| | sToolTipText = QT_TR_NOOP("Toggles the visibility of all internal geometry"); |
| | sWhatsThis = "Sketcher_RestoreInternalAlignmentGeometry"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Element_Ellipse_All"; |
| | sAccel = "Z, I"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherRestoreInternalAlignmentGeometry::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| |
|
| | |
| | Gui::Document* doc = Gui::Application::Instance->activeDocument(); |
| | SketcherGui::ReleaseHandler(doc); |
| |
|
| | |
| | std::vector<Gui::SelectionObject> selection; |
| | selection = getSelection().getSelectionEx(nullptr, Sketcher::SketchObject::getClassTypeId()); |
| |
|
| | |
| | if (selection.size() != 1) { |
| | Gui::TranslatedUserWarning(doc->getDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| |
|
| | return; |
| | } |
| |
|
| | |
| | const std::vector<std::string>& SubNames = selection[0].getSubNames(); |
| | Sketcher::SketchObject* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject()); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | |
| | auto getEdgeGeoId = [&Obj](const std::string& SubName) { |
| | int GeoId; |
| | Sketcher::PointPos PosId; |
| | getIdsFromName(SubName, Obj, GeoId, PosId); |
| | if (PosId == Sketcher::PointPos::none) |
| | return GeoId; |
| | else |
| | return (int)GeoEnum::GeoUndef; |
| | }; |
| |
|
| | |
| | auto noInternalGeo = [&Obj](const auto& GeoId) { |
| | const Part::Geometry* geo = Obj->getGeometry(GeoId); |
| | bool hasInternalGeo = geo |
| | && (geo->is<Part::GeomEllipse>() |
| | || geo->is<Part::GeomArcOfEllipse>() |
| | || geo->is<Part::GeomArcOfHyperbola>() |
| | || geo->is<Part::GeomArcOfParabola>() |
| | || geo->is<Part::GeomBSplineCurve>()); |
| | return !hasInternalGeo; |
| | }; |
| |
|
| | std::vector<int> SubGeoIds(SubNames.size()); |
| | std::transform(SubNames.begin(), SubNames.end(), SubGeoIds.begin(), getEdgeGeoId); |
| |
|
| | |
| | |
| | std::sort(SubGeoIds.begin(), SubGeoIds.end(), std::greater<>()); |
| | |
| | SubGeoIds.erase(std::unique(SubGeoIds.begin(), SubGeoIds.end()), SubGeoIds.end()); |
| |
|
| | |
| | SubGeoIds.erase(std::remove_if(SubGeoIds.begin(), SubGeoIds.end(), noInternalGeo), |
| | SubGeoIds.end()); |
| |
|
| | |
| | for (const auto& GeoId : SubGeoIds) { |
| | int currentgeoid = Obj->getHighestCurveIndex(); |
| |
|
| | try { |
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Exposing Internal Geometry")); |
| | Gui::cmdAppObjectArgs(Obj, "exposeInternalGeometry(%d)", GeoId); |
| |
|
| | int aftergeoid = Obj->getHighestCurveIndex(); |
| |
|
| | if (aftergeoid == currentgeoid) { |
| | Gui::cmdAppObjectArgs(Obj, "deleteUnusedInternalGeometry(%d)", GeoId); |
| | } |
| | } |
| | catch (const Base::Exception& e) { |
| | Gui::NotifyUserError( |
| | Obj, QT_TRANSLATE_NOOP("Notifications", "Invalid Constraint"), e.what()); |
| | Gui::Command::abortCommand(); |
| |
|
| | tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject*>(Obj)); |
| |
|
| | return; |
| | } |
| |
|
| | Gui::Command::commitCommand(); |
| | tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject*>(Obj)); |
| | } |
| | } |
| |
|
| | bool CmdSketcherRestoreInternalAlignmentGeometry::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherSymmetry) |
| |
|
| | CmdSketcherSymmetry::CmdSketcherSymmetry() |
| | : Command("Sketcher_Symmetry") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Mirror"); |
| | sToolTipText = |
| | QT_TR_NOOP("Creates a mirrored copy of the selected geometry"); |
| | sWhatsThis = "Sketcher_Symmetry"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Symmetry"; |
| | sAccel = "Z, S"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherSymmetry::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | std::vector<int> listOfGeoIds = getListOfSelectedGeoIds(true); |
| |
|
| | if (!listOfGeoIds.empty()) { |
| | ActivateHandler(getActiveGuiDocument(), std::make_unique<DrawSketchHandlerSymmetry>(listOfGeoIds)); |
| | } |
| | getSelection().clearSelection(); |
| | } |
| |
|
| | bool CmdSketcherSymmetry::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | class SketcherCopy: public Gui::Command |
| | { |
| | public: |
| | enum Op |
| | { |
| | Copy, |
| | Clone, |
| | Move |
| | }; |
| | explicit SketcherCopy(const char* name); |
| | void activate(SketcherCopy::Op op); |
| | virtual void activate() = 0; |
| | }; |
| |
|
| | |
| | static const char* cursor_createcopy[] = {"32 32 3 1", |
| | "+ c white", |
| | "# c red", |
| | ". c None", |
| | "................................", |
| | ".......+........................", |
| | ".......+........................", |
| | ".......+........................", |
| | ".......+........................", |
| | ".......+........................", |
| | "................................", |
| | ".+++++...+++++..................", |
| | "................................", |
| | ".......+........................", |
| | ".......+..............###.......", |
| | ".......+..............###.......", |
| | ".......+..............###.......", |
| | ".......+..............###.......", |
| | "......................###.......", |
| | ".....###..............###.......", |
| | ".....###..............###.......", |
| | ".....###..............###.......", |
| | ".....###..............###.......", |
| | ".....###..............###.......", |
| | ".....###..............###.......", |
| | ".....###..............###.......", |
| | ".....###..............###.......", |
| | ".....###..............###.......", |
| | ".....###........................", |
| | ".....###........................", |
| | ".....###........................", |
| | ".....###........................", |
| | "................................", |
| | "................................", |
| | "................................", |
| | "................................"}; |
| |
|
| | class DrawSketchHandlerCopy: public DrawSketchHandler |
| | { |
| | public: |
| | DrawSketchHandlerCopy(string geoidlist, int origingeoid, Sketcher::PointPos originpos, |
| | int nelements, SketcherCopy::Op op) |
| | : Mode(STATUS_SEEK_First) |
| | , snapMode(SnapMode::Free) |
| | , geoIdList(geoidlist) |
| | , Origin() |
| | , OriginGeoId(origingeoid) |
| | , OriginPos(originpos) |
| | , nElements(nelements) |
| | , Op(op) |
| | , EditCurve(2) |
| | {} |
| |
|
| | ~DrawSketchHandlerCopy() override |
| | {} |
| | |
| | enum SelectMode |
| | { |
| | STATUS_SEEK_First, |
| | STATUS_End |
| | }; |
| |
|
| | enum class SnapMode |
| | { |
| | Free, |
| | Snap5Degree |
| | }; |
| |
|
| | void mouseMove(SnapManager::SnapHandle snapHandle) override |
| | { |
| | using std::numbers::pi; |
| | Base::Vector2d onSketchPos = snapHandle.compute(); |
| |
|
| | if (Mode == STATUS_SEEK_First) { |
| |
|
| | if (QApplication::keyboardModifiers() == Qt::ControlModifier) |
| | snapMode = SnapMode::Snap5Degree; |
| | else |
| | snapMode = SnapMode::Free; |
| |
|
| | float length = (onSketchPos - EditCurve[0]).Length(); |
| | float angle = (onSketchPos - EditCurve[0]).Angle(); |
| |
|
| | Base::Vector2d endpoint = onSketchPos; |
| |
|
| | if (snapMode == SnapMode::Snap5Degree) { |
| | angle = round(angle / (pi / 36)) * pi / 36; |
| | endpoint = EditCurve[0] + length * Base::Vector2d(cos(angle), sin(angle)); |
| | } |
| |
|
| | if (showCursorCoords()) { |
| | SbString text; |
| | std::string lengthString = lengthToDisplayFormat(length, 1); |
| | std::string angleString = angleToDisplayFormat(angle * 180.0 / pi, 1); |
| | text.sprintf(" (%s, %s)", lengthString.c_str(), angleString.c_str()); |
| | setPositionText(endpoint, text); |
| | } |
| |
|
| | EditCurve[1] = endpoint; |
| | drawEdit(EditCurve); |
| | } |
| | applyCursor(); |
| | } |
| |
|
| | bool pressButton(Base::Vector2d) override |
| | { |
| | if (Mode == STATUS_SEEK_First) { |
| | drawEdit(EditCurve); |
| | Mode = STATUS_End; |
| | } |
| | return true; |
| | } |
| |
|
| | bool releaseButton(Base::Vector2d onSketchPos) override |
| | { |
| | Q_UNUSED(onSketchPos); |
| | if (Mode == STATUS_End) { |
| | Base::Vector2d vector = EditCurve[1] - EditCurve[0]; |
| | unsetCursor(); |
| | resetPositionText(); |
| |
|
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Copy/clone/move geometry")); |
| |
|
| | try { |
| | if (Op != SketcherCopy::Move) { |
| | Gui::cmdAppObjectArgs(sketchgui->getObject(), |
| | "addCopy(%s, App.Vector(%f, %f, 0), %s)", |
| | geoIdList.c_str(), |
| | vector.x, |
| | vector.y, |
| | (Op == SketcherCopy::Clone ? "True" : "False")); |
| | } |
| | else { |
| | Gui::cmdAppObjectArgs(sketchgui->getObject(), |
| | "addMove(%s, App.Vector(%f, %f, 0))", |
| | geoIdList.c_str(), |
| | vector.x, |
| | vector.y); |
| | } |
| | Gui::Command::commitCommand(); |
| | } |
| | catch (const Base::Exception& e) { |
| | Gui::NotifyUserError( |
| | sketchgui->getObject(), QT_TRANSLATE_NOOP("Notifications", "Error"), e.what()); |
| | Gui::Command::abortCommand(); |
| | } |
| |
|
| | tryAutoRecomputeIfNotSolve( |
| | sketchgui->getObject<Sketcher::SketchObject>()); |
| | EditCurve.clear(); |
| | drawEdit(EditCurve); |
| |
|
| | |
| | sketchgui->purgeHandler(); |
| | } |
| | return true; |
| | } |
| |
|
| | private: |
| | void activated() override |
| | { |
| | setCursor(QPixmap(cursor_createcopy), 7, 7); |
| | Origin = sketchgui->getObject<Sketcher::SketchObject>() |
| | ->getPoint(OriginGeoId, OriginPos); |
| | EditCurve[0] = Base::Vector2d(Origin.x, Origin.y); |
| | } |
| |
|
| | protected: |
| | SelectMode Mode; |
| | SnapMode snapMode; |
| | string geoIdList; |
| | Base::Vector3d Origin; |
| | int OriginGeoId; |
| | Sketcher::PointPos OriginPos; |
| | int nElements; |
| | SketcherCopy::Op Op; |
| | std::vector<Base::Vector2d> EditCurve; |
| | std::vector<AutoConstraint> sugConstr1; |
| | }; |
| |
|
| | |
| | SketcherCopy::SketcherCopy(const char* name) |
| | : Command(name) |
| | {} |
| |
|
| | void SketcherCopy::activate(SketcherCopy::Op op) |
| | { |
| | |
| | std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx(); |
| |
|
| | |
| | if (selection.size() != 1) { |
| | Gui::TranslatedUserWarning(getActiveGuiDocument()->getDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| |
|
| | return; |
| | } |
| |
|
| | |
| | const std::vector<std::string>& SubNames = selection[0].getSubNames(); |
| | if (SubNames.empty()) { |
| | Gui::TranslatedUserWarning(getActiveGuiDocument()->getDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| |
|
| | return; |
| | } |
| |
|
| | Sketcher::SketchObject* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject()); |
| | getSelection().clearSelection(); |
| |
|
| | int LastGeoId = 0; |
| | Sketcher::PointPos LastPointPos = Sketcher::PointPos::none; |
| | const Part::Geometry* LastGeo = nullptr; |
| |
|
| | |
| | std::stringstream stream; |
| | int geoids = 0; |
| | for (std::vector<std::string>::const_iterator it = SubNames.begin(); it != SubNames.end(); |
| | ++it) { |
| | |
| | if (it->size() > 4 && it->substr(0, 4) == "Edge") { |
| | LastGeoId = std::atoi(it->substr(4, 4000).c_str()) - 1; |
| | LastPointPos = Sketcher::PointPos::none; |
| | LastGeo = Obj->getGeometry(LastGeoId); |
| | |
| | if (LastGeoId >= 0) { |
| | geoids++; |
| | stream << LastGeoId << ","; |
| | } |
| | } |
| | else if (it->size() > 6 && it->substr(0, 6) == "Vertex") { |
| | |
| | int VtId = std::atoi(it->substr(6, 4000).c_str()) - 1; |
| | int GeoId; |
| | Sketcher::PointPos PosId; |
| | Obj->getGeoVertexIndex(VtId, GeoId, PosId); |
| | if (Obj->getGeometry(GeoId)->is<Part::GeomPoint>()) { |
| | LastGeoId = GeoId; |
| | LastPointPos = Sketcher::PointPos::start; |
| | |
| | if (LastGeoId >= 0) { |
| | geoids++; |
| | stream << LastGeoId << ","; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | if (SubNames.rbegin()->size() > 6 && SubNames.rbegin()->substr(0, 6) == "Vertex") { |
| | int VtId = std::atoi(SubNames.rbegin()->substr(6, 4000).c_str()) - 1; |
| | int GeoId; |
| | Sketcher::PointPos PosId; |
| | Obj->getGeoVertexIndex(VtId, GeoId, PosId); |
| | if (!Obj->getGeometry(GeoId)->is<Part::GeomPoint>()) { |
| | LastGeoId = GeoId; |
| | LastPointPos = PosId; |
| | } |
| | } |
| |
|
| | if (geoids < 1) { |
| | Gui::TranslatedUserWarning( |
| | Obj, |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("A copy requires at least one selected non-external geometric element")); |
| |
|
| | return; |
| | } |
| |
|
| | std::string geoIdList = stream.str(); |
| |
|
| | |
| | int index = geoIdList.rfind(','); |
| | geoIdList.resize(index); |
| | geoIdList.insert(0, 1, '['); |
| | geoIdList.append(1, ']'); |
| |
|
| | |
| | |
| | |
| | if (LastPointPos == Sketcher::PointPos::none) { |
| | if (LastGeo->is<Part::GeomCircle>() |
| | || LastGeo->is<Part::GeomEllipse>()) { |
| | LastPointPos = Sketcher::PointPos::mid; |
| | } |
| | else { |
| | LastPointPos = Sketcher::PointPos::start; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | ActivateHandler(getActiveGuiDocument(), |
| | std::make_unique<DrawSketchHandlerCopy>(geoIdList, LastGeoId, LastPointPos, geoids, op)); |
| | } |
| |
|
| |
|
| | class CmdSketcherCopy: public SketcherCopy |
| | { |
| | public: |
| | CmdSketcherCopy(); |
| | ~CmdSketcherCopy() override |
| | {} |
| | const char* className() const override |
| | { |
| | return "CmdSketcherCopy"; |
| | } |
| | void activate() override; |
| |
|
| | protected: |
| | void activated(int iMsg) override; |
| | bool isActive() override; |
| | }; |
| |
|
| | CmdSketcherCopy::CmdSketcherCopy() |
| | : SketcherCopy("Sketcher_Copy") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Copy"); |
| | sToolTipText = QT_TR_NOOP( |
| | "Creates a simple copy of the geometry taking as reference the last selected point"); |
| | sWhatsThis = "Sketcher_Copy"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Copy"; |
| | sAccel = "Z, C"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherCopy::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | SketcherCopy::activate(SketcherCopy::Copy); |
| | } |
| |
|
| |
|
| | void CmdSketcherCopy::activate() |
| | { |
| | SketcherCopy::activate(SketcherCopy::Copy); |
| | } |
| |
|
| | bool CmdSketcherCopy::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | class CmdSketcherClone: public SketcherCopy |
| | { |
| | public: |
| | CmdSketcherClone(); |
| | ~CmdSketcherClone() override |
| | {} |
| | const char* className() const override |
| | { |
| | return "CmdSketcherClone"; |
| | } |
| | void activate() override; |
| |
|
| | protected: |
| | void activated(int iMsg) override; |
| | bool isActive() override; |
| | }; |
| |
|
| | CmdSketcherClone::CmdSketcherClone() |
| | : SketcherCopy("Sketcher_Clone") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Clone"); |
| | sToolTipText = |
| | QT_TR_NOOP("Creates a clone of the geometry taking as reference the last selected point"); |
| | sWhatsThis = "Sketcher_Clone"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Clone"; |
| | sAccel = "Z, L"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherClone::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | SketcherCopy::activate(SketcherCopy::Clone); |
| | } |
| |
|
| | void CmdSketcherClone::activate() |
| | { |
| | SketcherCopy::activate(SketcherCopy::Clone); |
| | } |
| |
|
| | bool CmdSketcherClone::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | class CmdSketcherMove: public SketcherCopy |
| | { |
| | public: |
| | CmdSketcherMove(); |
| | ~CmdSketcherMove() override |
| | {} |
| | const char* className() const override |
| | { |
| | return "CmdSketcherMove"; |
| | } |
| | void activate() override; |
| |
|
| | protected: |
| | void activated(int iMsg) override; |
| | bool isActive() override; |
| | }; |
| |
|
| | CmdSketcherMove::CmdSketcherMove() |
| | : SketcherCopy("Sketcher_Move") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Move"); |
| | sToolTipText = QT_TR_NOOP("Moves the geometry taking as reference the last selected point"); |
| | sWhatsThis = "Sketcher_Move"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Move"; |
| | sAccel = "Z, M"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherMove::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | SketcherCopy::activate(SketcherCopy::Move); |
| | } |
| |
|
| | void CmdSketcherMove::activate() |
| | { |
| | SketcherCopy::activate(SketcherCopy::Move); |
| | } |
| |
|
| | bool CmdSketcherMove::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_ACL(CmdSketcherCompCopy) |
| |
|
| | CmdSketcherCompCopy::CmdSketcherCompCopy() |
| | : Command("Sketcher_CompCopy") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Clone"); |
| | sToolTipText = |
| | QT_TR_NOOP("Creates a clone of the geometry taking as reference the last selected point"); |
| | sWhatsThis = "Sketcher_CompCopy"; |
| | sStatusTip = sToolTipText; |
| | sAccel = ""; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherCompCopy::activated(int iMsg) |
| | { |
| | if (iMsg < 0 || iMsg > 2) |
| | return; |
| |
|
| | |
| | |
| | Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction); |
| | QList<QAction*> a = pcAction->actions(); |
| |
|
| | assert(iMsg < a.size()); |
| | pcAction->setIcon(a[iMsg]->icon()); |
| |
|
| | if (iMsg == 0) { |
| | CmdSketcherClone sc; |
| | sc.activate(); |
| | pcAction->setShortcut(QString::fromLatin1(this->getAccel())); |
| | } |
| | else if (iMsg == 1) { |
| | CmdSketcherCopy sc; |
| | sc.activate(); |
| | pcAction->setShortcut(QString::fromLatin1(this->getAccel())); |
| | } |
| | else if (iMsg == 2) { |
| | CmdSketcherMove sc; |
| | sc.activate(); |
| | pcAction->setShortcut(QStringLiteral("")); |
| | } |
| | } |
| |
|
| | Gui::Action* CmdSketcherCompCopy::createAction() |
| | { |
| | Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); |
| | pcAction->setDropDownMenu(true); |
| | applyCommandData(this->className(), pcAction); |
| |
|
| | QAction* clone = pcAction->addAction(QString()); |
| | clone->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Clone")); |
| | QAction* copy = pcAction->addAction(QString()); |
| | copy->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Copy")); |
| | QAction* move = pcAction->addAction(QString()); |
| | move->setIcon(Gui::BitmapFactory().iconFromTheme("Sketcher_Move")); |
| |
|
| | _pcAction = pcAction; |
| | languageChange(); |
| |
|
| | pcAction->setIcon(clone->icon()); |
| | int defaultId = 0; |
| | pcAction->setProperty("defaultAction", QVariant(defaultId)); |
| |
|
| | pcAction->setShortcut(QString::fromLatin1(getAccel())); |
| |
|
| | return pcAction; |
| | } |
| |
|
| | void CmdSketcherCompCopy::languageChange() |
| | { |
| | Command::languageChange(); |
| |
|
| | if (!_pcAction) |
| | return; |
| | Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction); |
| | QList<QAction*> a = pcAction->actions(); |
| |
|
| | QAction* clone = a[0]; |
| | clone->setText(QApplication::translate("Sketcher_CompCopy", "Clone")); |
| | clone->setToolTip(QApplication::translate( |
| | "Sketcher_Clone", |
| | "Creates a clone of the geometry taking as reference the last selected point")); |
| | clone->setStatusTip(QApplication::translate( |
| | "Sketcher_Clone", |
| | "Creates a clone of the geometry taking as reference the last selected point")); |
| | QAction* copy = a[1]; |
| | copy->setText(QApplication::translate("Sketcher_CompCopy", "Copy")); |
| | copy->setToolTip(QApplication::translate( |
| | "Sketcher_Copy", |
| | "Creates a simple copy of the geometry taking as reference the last selected point")); |
| | copy->setStatusTip(QApplication::translate( |
| | "Sketcher_Copy", |
| | "Creates a simple copy of the geometry taking as reference the last selected point")); |
| | QAction* move = a[2]; |
| | move->setText(QApplication::translate("Sketcher_CompCopy", "Move")); |
| | move->setToolTip(QApplication::translate( |
| | "Sketcher_Move", "Moves the geometry taking as reference the last selected point")); |
| | move->setStatusTip(QApplication::translate( |
| | "Sketcher_Move", "Moves the geometry taking as reference the last selected point")); |
| | } |
| |
|
| | bool CmdSketcherCompCopy::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | |
| | |
| | static const char* cursor_createrectangulararray[] = {"32 32 3 1", |
| | "+ c white", |
| | "# c red", |
| | ". c None", |
| | "................................", |
| | ".......+........................", |
| | ".......+........................", |
| | ".......+........................", |
| | ".......+........................", |
| | ".......+........................", |
| | "................................", |
| | ".+++++...+++++..................", |
| | ".......................###......", |
| | ".......+...............###......", |
| | ".......+...............###......", |
| | ".......+...............###......", |
| | ".......+......###......###......", |
| | ".......+......###......###......", |
| | "..............###......###......", |
| | "..............###......###......", |
| | ".....###......###......###......", |
| | ".....###......###......###......", |
| | ".....###......###......###......", |
| | ".....###......###......###......", |
| | ".....###......###......###......", |
| | ".....###......###......###......", |
| | ".....###......###...............", |
| | ".....###......###...............", |
| | ".....###......###...............", |
| | ".....###......###...............", |
| | ".....###........................", |
| | ".....###........................", |
| | ".....###........................", |
| | ".....###........................", |
| | "................................", |
| | "................................"}; |
| |
|
| | class DrawSketchHandlerRectangularArray: public DrawSketchHandler |
| | { |
| | public: |
| | DrawSketchHandlerRectangularArray(string geoidlist, int origingeoid, |
| | Sketcher::PointPos originpos, int nelements, bool clone, |
| | int rows, int cols, bool constraintSeparation, |
| | bool equalVerticalHorizontalSpacing) |
| | : Mode(STATUS_SEEK_First) |
| | , snapMode(SnapMode::Free) |
| | , geoIdList(geoidlist) |
| | , OriginGeoId(origingeoid) |
| | , OriginPos(originpos) |
| | , nElements(nelements) |
| | , Clone(clone) |
| | , Rows(rows) |
| | , Cols(cols) |
| | , ConstraintSeparation(constraintSeparation) |
| | , EqualVerticalHorizontalSpacing(equalVerticalHorizontalSpacing) |
| | , EditCurve(2) |
| | {} |
| |
|
| | ~DrawSketchHandlerRectangularArray() override |
| | {} |
| | |
| | enum SelectMode |
| | { |
| | STATUS_SEEK_First, |
| | STATUS_End |
| | }; |
| |
|
| | enum class SnapMode |
| | { |
| | Free, |
| | Snap5Degree |
| | }; |
| |
|
| | void mouseMove(SnapManager::SnapHandle snapHandle) override |
| | { |
| | using std::numbers::pi; |
| | Base::Vector2d onSketchPos = snapHandle.compute(); |
| |
|
| | if (Mode == STATUS_SEEK_First) { |
| |
|
| | if (QApplication::keyboardModifiers() == Qt::ControlModifier) |
| | snapMode = SnapMode::Snap5Degree; |
| | else |
| | snapMode = SnapMode::Free; |
| |
|
| | float length = (onSketchPos - EditCurve[0]).Length(); |
| | float angle = (onSketchPos - EditCurve[0]).Angle(); |
| |
|
| | Base::Vector2d endpoint = onSketchPos; |
| |
|
| | if (snapMode == SnapMode::Snap5Degree) { |
| | angle = round(angle / (pi / 36)) * pi / 36; |
| | endpoint = EditCurve[0] + length * Base::Vector2d(cos(angle), sin(angle)); |
| | } |
| |
|
| | if (showCursorCoords()) { |
| | SbString text; |
| | std::string lengthString = lengthToDisplayFormat(length, 1); |
| | std::string angleString = angleToDisplayFormat(angle * 180.0 / pi, 1); |
| | text.sprintf(" (%s, %s)", lengthString.c_str(), angleString.c_str()); |
| | setPositionText(endpoint, text); |
| | } |
| |
|
| | EditCurve[1] = endpoint; |
| | drawEdit(EditCurve); |
| | if (seekAutoConstraint( |
| | sugConstr1, endpoint, Base::Vector2d(0.0, 0.0), AutoConstraint::VERTEX)) { |
| | renderSuggestConstraintsCursor(sugConstr1); |
| | return; |
| | } |
| | } |
| | applyCursor(); |
| | } |
| |
|
| | bool pressButton(Base::Vector2d) override |
| | { |
| | if (Mode == STATUS_SEEK_First) { |
| | drawEdit(EditCurve); |
| | Mode = STATUS_End; |
| | } |
| | return true; |
| | } |
| |
|
| | bool releaseButton(Base::Vector2d onSketchPos) override |
| | { |
| | Q_UNUSED(onSketchPos); |
| | if (Mode == STATUS_End) { |
| | Base::Vector2d vector = EditCurve[1] - EditCurve[0]; |
| | unsetCursor(); |
| | resetPositionText(); |
| |
|
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create copy of geometry")); |
| |
|
| | try { |
| | Gui::cmdAppObjectArgs( |
| | sketchgui->getObject(), |
| | "addRectangularArray(%s, App.Vector(%f, %f, 0), %s, %d, %d, %s, %f)", |
| | geoIdList.c_str(), |
| | vector.x, |
| | vector.y, |
| | (Clone ? "True" : "False"), |
| | Cols, |
| | Rows, |
| | (ConstraintSeparation ? "True" : "False"), |
| | (EqualVerticalHorizontalSpacing ? 1.0 : 0.5)); |
| | Gui::Command::commitCommand(); |
| | } |
| | catch (const Base::Exception& e) { |
| | Gui::NotifyUserError( |
| | sketchgui, QT_TRANSLATE_NOOP("Notifications", "Error"), e.what()); |
| | Gui::Command::abortCommand(); |
| | } |
| |
|
| | |
| | if (!sugConstr1.empty()) { |
| | createAutoConstraints(sugConstr1, OriginGeoId + nElements, OriginPos); |
| | sugConstr1.clear(); |
| | } |
| | tryAutoRecomputeIfNotSolve( |
| | sketchgui->getObject<Sketcher::SketchObject>()); |
| |
|
| | EditCurve.clear(); |
| | drawEdit(EditCurve); |
| |
|
| | |
| | sketchgui->purgeHandler(); |
| | } |
| | return true; |
| | } |
| |
|
| | private: |
| | void activated() override |
| | { |
| | setCursor(QPixmap(cursor_createrectangulararray), 7, 7); |
| | Origin = sketchgui->getObject<Sketcher::SketchObject>() |
| | ->getPoint(OriginGeoId, OriginPos); |
| | EditCurve[0] = Base::Vector2d(Origin.x, Origin.y); |
| | } |
| |
|
| | protected: |
| | SelectMode Mode; |
| | SnapMode snapMode; |
| | string geoIdList; |
| | Base::Vector3d Origin; |
| | int OriginGeoId; |
| | Sketcher::PointPos OriginPos; |
| | int nElements; |
| | bool Clone; |
| | int Rows; |
| | int Cols; |
| | bool ConstraintSeparation; |
| | bool EqualVerticalHorizontalSpacing; |
| | std::vector<Base::Vector2d> EditCurve; |
| | std::vector<AutoConstraint> sugConstr1; |
| | }; |
| |
|
| | DEF_STD_CMD_A(CmdSketcherRectangularArray) |
| |
|
| | CmdSketcherRectangularArray::CmdSketcherRectangularArray() |
| | : Command("Sketcher_RectangularArray") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Rectangular Array"); |
| | sToolTipText = QT_TR_NOOP("Creates a rectangular array pattern of the geometry taking as " |
| | "reference the last selected point"); |
| | sWhatsThis = "Sketcher_RectangularArray"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_RectangularArray"; |
| | sAccel = "Z, A"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherRectangularArray::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | |
| | std::vector<Gui::SelectionObject> selection; |
| | selection = getSelection().getSelectionEx(nullptr, Sketcher::SketchObject::getClassTypeId()); |
| |
|
| | |
| | if (selection.size() != 1) { |
| | Gui::TranslatedUserWarning(getActiveGuiDocument()->getDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| |
|
| | return; |
| | } |
| |
|
| | |
| | const std::vector<std::string>& SubNames = selection[0].getSubNames(); |
| | if (SubNames.empty()) { |
| | Gui::TranslatedUserWarning(getActiveGuiDocument()->getDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| | return; |
| | } |
| |
|
| | Sketcher::SketchObject* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject()); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | int LastGeoId = 0; |
| | Sketcher::PointPos LastPointPos = Sketcher::PointPos::none; |
| | const Part::Geometry* LastGeo = nullptr; |
| |
|
| | |
| | std::stringstream stream; |
| | int geoids = 0; |
| |
|
| | for (std::vector<std::string>::const_iterator it = SubNames.begin(); it != SubNames.end(); |
| | ++it) { |
| | |
| | if (it->size() > 4 && it->substr(0, 4) == "Edge") { |
| | LastGeoId = std::atoi(it->substr(4, 4000).c_str()) - 1; |
| | LastPointPos = Sketcher::PointPos::none; |
| | LastGeo = Obj->getGeometry(LastGeoId); |
| |
|
| | |
| | if (LastGeoId >= 0) { |
| | geoids++; |
| | stream << LastGeoId << ","; |
| | } |
| | } |
| | else if (it->size() > 6 && it->substr(0, 6) == "Vertex") { |
| | |
| | int VtId = std::atoi(it->substr(6, 4000).c_str()) - 1; |
| | int GeoId; |
| | Sketcher::PointPos PosId; |
| | Obj->getGeoVertexIndex(VtId, GeoId, PosId); |
| | if (Obj->getGeometry(GeoId)->is<Part::GeomPoint>()) { |
| | LastGeoId = GeoId; |
| | LastPointPos = Sketcher::PointPos::start; |
| | |
| | if (LastGeoId >= 0) { |
| | geoids++; |
| | stream << LastGeoId << ","; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | if (SubNames.rbegin()->size() > 6 && SubNames.rbegin()->substr(0, 6) == "Vertex") { |
| | int VtId = std::atoi(SubNames.rbegin()->substr(6, 4000).c_str()) - 1; |
| | int GeoId; |
| | Sketcher::PointPos PosId; |
| | Obj->getGeoVertexIndex(VtId, GeoId, PosId); |
| | if (!Obj->getGeometry(GeoId)->is<Part::GeomPoint>()) { |
| | LastGeoId = GeoId; |
| | LastPointPos = PosId; |
| | } |
| | } |
| |
|
| | if (geoids < 1) { |
| | Gui::TranslatedUserWarning( |
| | Obj, |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("A copy requires at least one selected non-external geometric element")); |
| |
|
| | return; |
| | } |
| |
|
| | std::string geoIdList = stream.str(); |
| |
|
| | |
| | int index = geoIdList.rfind(','); |
| | geoIdList.resize(index); |
| | geoIdList.insert(0, 1, '['); |
| | geoIdList.append(1, ']'); |
| |
|
| | |
| | |
| | |
| | if (LastPointPos == Sketcher::PointPos::none) { |
| | if (LastGeo->is<Part::GeomCircle>() |
| | || LastGeo->is<Part::GeomEllipse>()) { |
| | LastPointPos = Sketcher::PointPos::mid; |
| | } |
| | else { |
| | LastPointPos = Sketcher::PointPos::start; |
| | } |
| | } |
| |
|
| | |
| | SketchRectangularArrayDialog slad; |
| |
|
| | if (slad.exec() == QDialog::Accepted) { |
| | ActivateHandler(getActiveGuiDocument(), |
| | std::make_unique<DrawSketchHandlerRectangularArray>(geoIdList, |
| | LastGeoId, |
| | LastPointPos, |
| | geoids, |
| | slad.Clone, |
| | slad.Rows, |
| | slad.Cols, |
| | slad.ConstraintSeparation, |
| | slad.EqualVerticalHorizontalSpacing)); |
| | } |
| | } |
| |
|
| | bool CmdSketcherRectangularArray::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherDeleteAllGeometry) |
| |
|
| | CmdSketcherDeleteAllGeometry::CmdSketcherDeleteAllGeometry() |
| | : Command("Sketcher_DeleteAllGeometry") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Delete All Geometry"); |
| | sToolTipText = QT_TR_NOOP("Deletes all geometry and their constraints in the current sketch, " |
| | "with the exception of external geometry"); |
| | sWhatsThis = "Sketcher_DeleteAllGeometry"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_DeleteGeometry"; |
| | sAccel = ""; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherDeleteAllGeometry::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| |
|
| | int ret = QMessageBox::question( |
| | Gui::getMainWindow(), |
| | QObject::tr("Delete All Geometry"), |
| | QObject::tr("Delete all geometry and constraints?"), |
| | QMessageBox::Yes, |
| | QMessageBox::Cancel); |
| | |
| | if (ret == QMessageBox::Yes) { |
| | getSelection().clearSelection(); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | try { |
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Delete all geometry")); |
| | Gui::cmdAppObjectArgs(Obj, "deleteAllGeometry()"); |
| | Gui::Command::commitCommand(); |
| | } |
| | catch (const Base::Exception& e) { |
| | Gui::NotifyUserError( |
| | Obj, QT_TRANSLATE_NOOP("Notifications", "Failed to delete all geometry"), e.what()); |
| | Gui::Command::abortCommand(); |
| | } |
| |
|
| | ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( |
| | "User parameter:BaseApp/Preferences/Mod/Sketcher"); |
| | bool autoRecompute = hGrp->GetBool("AutoRecompute", false); |
| |
|
| | if (autoRecompute) |
| | Gui::Command::updateActive(); |
| | else |
| | Obj->solve(); |
| | } |
| | else if (ret == QMessageBox::Cancel) { |
| | |
| | return; |
| | } |
| | } |
| |
|
| | bool CmdSketcherDeleteAllGeometry::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherDeleteAllConstraints) |
| |
|
| | CmdSketcherDeleteAllConstraints::CmdSketcherDeleteAllConstraints() |
| | : Command("Sketcher_DeleteAllConstraints") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Delete All Constraints"); |
| | sToolTipText = QT_TR_NOOP("Deletes all constraints in the sketch"); |
| | sWhatsThis = "Sketcher_DeleteAllConstraints"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_DeleteConstraints"; |
| | sAccel = ""; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherDeleteAllConstraints::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| |
|
| | int ret = QMessageBox::question( |
| | Gui::getMainWindow(), |
| | QObject::tr("Delete All Constraints"), |
| | QObject::tr("Delete all the constraints in the sketch?"), |
| | QMessageBox::Yes, |
| | QMessageBox::Cancel); |
| |
|
| | if (ret == QMessageBox::Yes) { |
| | getSelection().clearSelection(); |
| | Sketcher::SketchObject* Obj = getSketchObject(); |
| |
|
| | try { |
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Delete all constraints")); |
| | Gui::cmdAppObjectArgs(Obj, "deleteAllConstraints()"); |
| | Gui::Command::commitCommand(); |
| | } |
| | catch (const Base::Exception& e) { |
| | Gui::NotifyUserError( |
| | Obj, |
| | QT_TRANSLATE_NOOP("Notifications", "Failed to delete all constraints"), |
| | e.what()); |
| | Gui::Command::abortCommand(); |
| | } |
| |
|
| | ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( |
| | "User parameter:BaseApp/Preferences/Mod/Sketcher"); |
| | bool autoRecompute = hGrp->GetBool("AutoRecompute", false); |
| |
|
| | if (autoRecompute) |
| | Gui::Command::updateActive(); |
| | else |
| | Obj->solve(); |
| | } |
| | else if (ret == QMessageBox::Cancel) { |
| | |
| | return; |
| | } |
| | } |
| |
|
| | bool CmdSketcherDeleteAllConstraints::isActive() |
| | { |
| | return isCommandActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| |
|
| | DEF_STD_CMD_A(CmdSketcherRemoveAxesAlignment) |
| |
|
| | CmdSketcherRemoveAxesAlignment::CmdSketcherRemoveAxesAlignment() |
| | : Command("Sketcher_RemoveAxesAlignment") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Remove Axes Alignment"); |
| | sToolTipText = QT_TR_NOOP("Modifies the constraints to remove axes alignment while trying to " |
| | "preserve the constraint relationship of the selection"); |
| | sWhatsThis = "Sketcher_RemoveAxesAlignment"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_RemoveAxesAlignment"; |
| | sAccel = "Z, R"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherRemoveAxesAlignment::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | |
| | std::vector<Gui::SelectionObject> selection; |
| | selection = getSelection().getSelectionEx(nullptr, Sketcher::SketchObject::getClassTypeId()); |
| |
|
| | |
| | if (selection.size() != 1) { |
| | Gui::TranslatedUserWarning(getActiveGuiDocument()->getDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| |
|
| | return; |
| | } |
| |
|
| | |
| | const std::vector<std::string>& SubNames = selection[0].getSubNames(); |
| | if (SubNames.empty()) { |
| | Gui::TranslatedUserWarning(getActiveGuiDocument()->getDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| | return; |
| | } |
| |
|
| | Sketcher::SketchObject* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject()); |
| |
|
| | getSelection().clearSelection(); |
| |
|
| | int LastGeoId = 0; |
| |
|
| | |
| | std::stringstream stream; |
| | int geoids = 0; |
| |
|
| | for (std::vector<std::string>::const_iterator it = SubNames.begin(); it != SubNames.end(); |
| | ++it) { |
| | |
| | if (it->size() > 4 && it->substr(0, 4) == "Edge") { |
| | LastGeoId = std::atoi(it->substr(4, 4000).c_str()) - 1; |
| |
|
| | |
| | if (LastGeoId >= 0) { |
| | geoids++; |
| | stream << LastGeoId << ","; |
| | } |
| | } |
| | else if (it->size() > 6 && it->substr(0, 6) == "Vertex") { |
| | |
| | int VtId = std::atoi(it->substr(6, 4000).c_str()) - 1; |
| | int GeoId; |
| | Sketcher::PointPos PosId; |
| | Obj->getGeoVertexIndex(VtId, GeoId, PosId); |
| | if (Obj->getGeometry(GeoId)->is<Part::GeomPoint>()) { |
| | LastGeoId = GeoId; |
| | |
| | if (LastGeoId >= 0) { |
| | geoids++; |
| | stream << LastGeoId << ","; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | if (geoids < 1) { |
| | Gui::TranslatedUserWarning( |
| | Obj, |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Removal of axes alignment requires at least one selected " |
| | "non-external geometric element")); |
| |
|
| | return; |
| | } |
| |
|
| | std::string geoIdList = stream.str(); |
| |
|
| | |
| | int index = geoIdList.rfind(','); |
| | geoIdList.resize(index); |
| | geoIdList.insert(0, 1, '['); |
| | geoIdList.append(1, ']'); |
| |
|
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Remove Axes Alignment")); |
| |
|
| | try { |
| | Gui::cmdAppObjectArgs(Obj, "removeAxesAlignment(%s)", geoIdList.c_str()); |
| | Gui::Command::commitCommand(); |
| | } |
| | catch (const Base::Exception& e) { |
| | Gui::NotifyUserError(Obj, QT_TRANSLATE_NOOP("Notifications", "Error"), e.what()); |
| | Gui::Command::abortCommand(); |
| | } |
| |
|
| | tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject*>(Obj)); |
| | } |
| |
|
| | bool CmdSketcherRemoveAxesAlignment::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| |
|
| | |
| | DEF_STD_CMD_A(CmdSketcherOffset) |
| |
|
| | CmdSketcherOffset::CmdSketcherOffset() |
| | : Command("Sketcher_Offset") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Offset"); |
| | sToolTipText = QT_TR_NOOP("Adds an equidistant closed contour around selected geometry: positive values offset outward, negative values inward"); |
| | sWhatsThis = "Sketcher_Offset"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Offset"; |
| | sAccel = "Z, T"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherOffset::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | std::vector<int> listOfGeoIds = {}; |
| |
|
| | |
| | std::vector<Gui::SelectionObject> selection; |
| | selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); |
| |
|
| | |
| | if (selection.size() != 1) { |
| | Gui::TranslatedUserWarning( |
| | getActiveGuiDocument(), |
| | QObject::tr("Wrong selection"), |
| | QObject::tr("Select elements from a single sketch.")); |
| | return; |
| | } |
| |
|
| | |
| | auto* Obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject()); |
| | const std::vector<std::string>& subNames = selection[0].getSubNames(); |
| | if (!subNames.empty()) { |
| | for (auto& name : subNames) { |
| | int geoId; |
| | if (name.size() > 4 && name.substr(0, 4) == "Edge") { |
| | geoId = std::atoi(name.substr(4, 4000).c_str()) - 1; |
| | } |
| | else if (name.size() > 12 && name.substr(0, 12) == "ExternalEdge") { |
| | geoId = -std::atoi(name.substr(12, 4000).c_str()) - 2; |
| | } |
| | else { |
| | continue; |
| | } |
| |
|
| | const Part::Geometry* geo = Obj->getGeometry(geoId); |
| | if (!isPoint(*geo) |
| | && !isBSplineCurve(*geo) |
| | && !isEllipse(*geo) |
| | && !isArcOfEllipse(*geo) |
| | && !isArcOfHyperbola(*geo) |
| | && !isArcOfParabola(*geo) |
| | && !GeometryFacade::isInternalAligned(geo)) { |
| | |
| | |
| | listOfGeoIds.push_back(geoId); |
| | } |
| | } |
| | } |
| |
|
| | if (listOfGeoIds.size() != 0) { |
| | ActivateHandler(getActiveGuiDocument(), std::make_unique<DrawSketchHandlerOffset>(listOfGeoIds)); |
| | } |
| | else { |
| | getSelection().clearSelection(); |
| | Gui::NotifyUserError(Obj, |
| | QT_TRANSLATE_NOOP("Notifications", "Invalid selection"), |
| | QT_TRANSLATE_NOOP("Notifications", "Selection has no valid geometries. B-splines and points are not supported yet.")); |
| | } |
| | } |
| |
|
| | bool CmdSketcherOffset::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherRotate) |
| |
|
| | CmdSketcherRotate::CmdSketcherRotate() |
| | : Command("Sketcher_Rotate") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Rotate / Polar Transform"); |
| | sToolTipText = QT_TR_NOOP("Rotates the selected geometry by creating 'n' copies, enabling circular pattern creation"); |
| | sWhatsThis = "Sketcher_Rotate"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Rotate"; |
| | sAccel = "Z, P"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherRotate::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | std::vector<int> listOfGeoIds = getListOfSelectedGeoIds(true); |
| |
|
| | if (!listOfGeoIds.empty()) { |
| | ActivateHandler(getActiveGuiDocument(), std::make_unique<DrawSketchHandlerRotate>(listOfGeoIds)); |
| | } |
| | getSelection().clearSelection(); |
| | } |
| |
|
| | bool CmdSketcherRotate::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherScale) |
| |
|
| | CmdSketcherScale::CmdSketcherScale() |
| | : Command("Sketcher_Scale") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Scale"); |
| | sToolTipText = QT_TR_NOOP("Scales the selected geometries"); |
| | sWhatsThis = "Sketcher_Scale"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Scale"; |
| | sAccel = "Z, P, S"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherScale::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | std::vector<int> listOfGeoIds = getListOfSelectedGeoIds(true); |
| |
|
| | if (!listOfGeoIds.empty()) { |
| | ActivateHandler(getActiveGuiDocument(), std::make_unique<DrawSketchHandlerScale>(listOfGeoIds)); |
| | } |
| | getSelection().clearSelection(); |
| | } |
| |
|
| | bool CmdSketcherScale::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | |
| |
|
| | DEF_STD_CMD_A(CmdSketcherTranslate) |
| |
|
| | CmdSketcherTranslate::CmdSketcherTranslate() |
| | : Command("Sketcher_Translate") |
| | { |
| | sAppModule = "Sketcher"; |
| | sGroup = "Sketcher"; |
| | sMenuText = QT_TR_NOOP("Move / Array Transform"); |
| | sToolTipText = QT_TR_NOOP("Translates the selected geometries and enables the creation of 'i' * 'j' copies"); |
| | sWhatsThis = "Sketcher_Translate"; |
| | sStatusTip = sToolTipText; |
| | sPixmap = "Sketcher_Translate"; |
| | sAccel = "W"; |
| | eType = ForEdit; |
| | } |
| |
|
| | void CmdSketcherTranslate::activated(int iMsg) |
| | { |
| | Q_UNUSED(iMsg); |
| | std::vector<int> listOfGeoIds = getListOfSelectedGeoIds(true); |
| |
|
| | if (!listOfGeoIds.empty()) { |
| | ActivateHandler(getActiveGuiDocument(), std::make_unique<DrawSketchHandlerTranslate>(listOfGeoIds)); |
| | } |
| | getSelection().clearSelection(); |
| | } |
| |
|
| | bool CmdSketcherTranslate::isActive() |
| | { |
| | return isCommandNeedingGeometryActive(getActiveGuiDocument()); |
| | } |
| |
|
| | void CreateSketcherCommandsConstraintAccel() |
| | { |
| | Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); |
| |
|
| | rcCmdMgr.addCommand(new CmdSketcherSelectConstraints()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectOrigin()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectVerticalAxis()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectHorizontalAxis()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectRedundantConstraints()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectConflictingConstraints()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectMalformedConstraints()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectPartiallyRedundantConstraints()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectElementsAssociatedWithConstraints()); |
| | rcCmdMgr.addCommand(new CmdSketcherSelectElementsWithDoFs()); |
| | rcCmdMgr.addCommand(new CmdSketcherRestoreInternalAlignmentGeometry()); |
| | rcCmdMgr.addCommand(new CmdSketcherTranslate()); |
| | rcCmdMgr.addCommand(new CmdSketcherOffset()); |
| | rcCmdMgr.addCommand(new CmdSketcherRotate()); |
| | rcCmdMgr.addCommand(new CmdSketcherScale()); |
| | rcCmdMgr.addCommand(new CmdSketcherSymmetry()); |
| | rcCmdMgr.addCommand(new CmdSketcherCopy()); |
| | rcCmdMgr.addCommand(new CmdSketcherClone()); |
| | rcCmdMgr.addCommand(new CmdSketcherMove()); |
| | rcCmdMgr.addCommand(new CmdSketcherCompCopy()); |
| | rcCmdMgr.addCommand(new CmdSketcherRectangularArray()); |
| | rcCmdMgr.addCommand(new CmdSketcherDeleteAllGeometry()); |
| | rcCmdMgr.addCommand(new CmdSketcherDeleteAllConstraints()); |
| | rcCmdMgr.addCommand(new CmdSketcherRemoveAxesAlignment()); |
| | rcCmdMgr.addCommand(new CmdSketcherCopyClipboard()); |
| | rcCmdMgr.addCommand(new CmdSketcherCut()); |
| | rcCmdMgr.addCommand(new CmdSketcherPaste()); |
| | } |
| | |
| |
|
| | void SketcherGui::centerScale(double scaleFactor) |
| | { |
| | Gui::Document* doc = Gui::Application::Instance->activeDocument(); |
| | auto* vp = static_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit()); |
| | auto scaler = DrawSketchHandlerScale::make_centerScaleAll(vp, scaleFactor, false); |
| | scaler->setSketchGui(vp); |
| | scaler->executeCommands(); |
| |
|
| | if (auto* view3d = dynamic_cast<Gui::View3DInventor*>(doc->getActiveView())) { |
| | auto viewer = view3d->getViewer(); |
| | bool isAnimating = viewer->isAnimationEnabled(); |
| |
|
| | viewer->setAnimationEnabled(false); |
| | viewer->scale(scaleFactor); |
| | viewer->setAnimationEnabled(isAnimating); |
| | } |
| | } |
| |
|