| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include <QSignalBlocker>
|
| | #include <QAction>
|
| |
|
| |
|
| | #include <App/Document.h>
|
| | #include <Base/Tools.h>
|
| | #include <Base/UnitsApi.h>
|
| | #include <Gui/Command.h>
|
| | #include <Gui/Tools.h>
|
| | #include <Gui/Inventor/Draggers/Gizmo.h>
|
| | #include <Gui/Inventor/Draggers/SoLinearDragger.h>
|
| | #include <Gui/Inventor/Draggers/SoRotationDragger.h>
|
| | #include <Mod/PartDesign/App/FeatureExtrude.h>
|
| | #include <Mod/Part/App/GizmoHelper.h>
|
| |
|
| | #include "ui_TaskPadPocketParameters.h"
|
| | #include "TaskExtrudeParameters.h"
|
| | #include "TaskTransformedParameters.h"
|
| | #include "ReferenceSelection.h"
|
| |
|
| |
|
| | using namespace PartDesignGui;
|
| | using namespace Gui;
|
| |
|
| |
|
| |
|
| | TaskExtrudeParameters::TaskExtrudeParameters(
|
| | ViewProviderExtrude* SketchBasedView,
|
| | QWidget* parent,
|
| | const std::string& pixmapname,
|
| | const QString& parname
|
| | )
|
| | : TaskSketchBasedParameters(SketchBasedView, parent, pixmapname, parname)
|
| | , propReferenceAxis(nullptr)
|
| | , ui(new Ui_TaskPadPocketParameters)
|
| | {
|
| |
|
| | proxy = new QWidget(this);
|
| | ui->setupUi(proxy);
|
| | handleLineFaceNameNo(ui->lineFaceName);
|
| | handleLineFaceNameNo(ui->lineFaceName2);
|
| |
|
| | Gui::ButtonGroup* group = new Gui::ButtonGroup(this);
|
| | group->addButton(ui->checkBoxReversed);
|
| | group->setExclusive(true);
|
| |
|
| | this->groupLayout()->addWidget(proxy);
|
| | }
|
| |
|
| | void TaskExtrudeParameters::setupDialog()
|
| | {
|
| | auto createRemoveAction = [this]() -> QAction* {
|
| | auto action = new QAction(tr("Remove"), this);
|
| | action->setShortcut(Gui::QtTools::deleteKeySequence());
|
| | action->setShortcutVisibleInContextMenu(true);
|
| | return action;
|
| | };
|
| |
|
| | unselectShapeFaceAction = createRemoveAction();
|
| | unselectShapeFaceAction2 = createRemoveAction();
|
| |
|
| | createSideControllers();
|
| |
|
| |
|
| | auto extrude = getObject<PartDesign::FeatureExtrude>();
|
| |
|
| | int UserDecimals = Base::UnitsApi::getDecimals();
|
| | ui->XDirectionEdit->setDecimals(UserDecimals);
|
| | ui->YDirectionEdit->setDecimals(UserDecimals);
|
| | ui->ZDirectionEdit->setDecimals(UserDecimals);
|
| |
|
| | ui->checkBoxAlongDirection->setChecked(extrude->AlongSketchNormal.getValue());
|
| |
|
| | ui->XDirectionEdit->setValue(extrude->Direction.getValue().x);
|
| | ui->YDirectionEdit->setValue(extrude->Direction.getValue().y);
|
| | ui->ZDirectionEdit->setValue(extrude->Direction.getValue().z);
|
| |
|
| | ui->XDirectionEdit->bind(App::ObjectIdentifier::parse(extrude, "Direction.x"));
|
| | ui->YDirectionEdit->bind(App::ObjectIdentifier::parse(extrude, "Direction.y"));
|
| | ui->ZDirectionEdit->bind(App::ObjectIdentifier::parse(extrude, "Direction.z"));
|
| |
|
| | ui->checkBoxReversed->setChecked(extrude->Reversed.getValue());
|
| |
|
| |
|
| | setupSideDialog(m_side1);
|
| | setupSideDialog(m_side2);
|
| |
|
| |
|
| | translateSidesList(extrude->SideType.getValue());
|
| |
|
| | connectSlots();
|
| |
|
| | this->propReferenceAxis = &(extrude->ReferenceAxis);
|
| | updateUI(Side::First);
|
| |
|
| | setupGizmos();
|
| |
|
| |
|
| |
|
| | tryRecomputeFeature();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::setupSideDialog(SideController& side)
|
| | {
|
| |
|
| | Base::Quantity length = side.Length->getQuantityValue();
|
| | Base::Quantity offset = side.Offset->getQuantityValue();
|
| | Base::Quantity taper = side.TaperAngle->getQuantityValue();
|
| | int typeIndex = side.Type->getValue();
|
| |
|
| |
|
| |
|
| | if (typeIndex > static_cast<int>(Mode::ToShape)) {
|
| | typeIndex--;
|
| | }
|
| |
|
| |
|
| | side.lengthEdit->setValue(length);
|
| | side.offsetEdit->setValue(offset);
|
| | side.taperEdit->setMinimum(side.TaperAngle->getMinimum());
|
| | side.taperEdit->setMaximum(side.TaperAngle->getMaximum());
|
| | side.taperEdit->setSingleStep(side.TaperAngle->getStepSize());
|
| | side.taperEdit->setValue(taper);
|
| |
|
| |
|
| | side.lengthEdit->bind(*side.Length);
|
| | side.offsetEdit->bind(*side.Offset);
|
| | side.taperEdit->bind(*side.TaperAngle);
|
| |
|
| |
|
| | App::DocumentObject* faceObj = side.UpToFace->getValue();
|
| | std::vector<std::string> subStrings = side.UpToFace->getSubValues();
|
| | std::string upToFaceName;
|
| | int faceId = -1;
|
| | if (faceObj && !subStrings.empty()) {
|
| | upToFaceName = subStrings.front();
|
| | if (upToFaceName.rfind("Face", 0) == 0) {
|
| | faceId = std::atoi(&upToFaceName[4]);
|
| | }
|
| | }
|
| |
|
| | if (faceObj && PartDesign::Feature::isDatum(faceObj)) {
|
| | side.lineFaceName->setText(QString::fromUtf8(faceObj->Label.getValue()));
|
| | side.lineFaceName->setProperty("FeatureName", QByteArray(faceObj->getNameInDocument()));
|
| | }
|
| | else if (faceObj && faceId >= 0) {
|
| | side.lineFaceName->setText(QStringLiteral("%1:%2%3").arg(
|
| | QString::fromUtf8(faceObj->Label.getValue()),
|
| | tr("Face"),
|
| | QString::number(faceId)
|
| | ));
|
| | side.lineFaceName->setProperty("FeatureName", QByteArray(faceObj->getNameInDocument()));
|
| | }
|
| | else {
|
| | side.lineFaceName->clear();
|
| | side.lineFaceName->setProperty("FeatureName", QVariant());
|
| | }
|
| | side.lineFaceName->setProperty("FaceName", QByteArray(upToFaceName.c_str()));
|
| |
|
| |
|
| | updateShapeName(side.lineShapeName, *side.UpToShape);
|
| | updateShapeFaces(side.listWidgetReferences, *side.UpToShape);
|
| |
|
| |
|
| | translateModeList(side.changeMode, typeIndex);
|
| |
|
| | side.listWidgetReferences->addAction(side.unselectShapeFaceAction);
|
| | side.listWidgetReferences->setContextMenuPolicy(Qt::ActionsContextMenu);
|
| | side.checkBoxAllFaces->setChecked(side.listWidgetReferences->count() == 0);
|
| | }
|
| |
|
| | void TaskExtrudeParameters::createSideControllers()
|
| | {
|
| | auto extrude = getObject<PartDesign::FeatureExtrude>();
|
| |
|
| |
|
| | m_side1.changeMode = ui->changeMode;
|
| | m_side1.labelLength = ui->labelLength;
|
| | m_side1.labelOffset = ui->labelOffset;
|
| | m_side1.labelTaperAngle = ui->labelTaperAngle;
|
| | m_side1.lengthEdit = ui->lengthEdit;
|
| | m_side1.offsetEdit = ui->offsetEdit;
|
| | m_side1.taperEdit = ui->taperEdit;
|
| | m_side1.lineFaceName = ui->lineFaceName;
|
| | m_side1.buttonFace = ui->buttonFace;
|
| | m_side1.lineShapeName = ui->lineShapeName;
|
| | m_side1.buttonShape = ui->buttonShape;
|
| | m_side1.listWidgetReferences = ui->listWidgetReferences;
|
| | m_side1.buttonShapeFace = ui->buttonShapeFace;
|
| | m_side1.checkBoxAllFaces = ui->checkBoxAllFaces;
|
| | m_side1.upToShapeList = ui->upToShapeList;
|
| | m_side1.upToShapeFaces = ui->upToShapeFaces;
|
| | m_side1.unselectShapeFaceAction = unselectShapeFaceAction;
|
| |
|
| | m_side1.Type = &extrude->Type;
|
| | m_side1.Length = &extrude->Length;
|
| | m_side1.Offset = &extrude->Offset;
|
| | m_side1.TaperAngle = &extrude->TaperAngle;
|
| | m_side1.UpToFace = &extrude->UpToFace;
|
| | m_side1.UpToShape = &extrude->UpToShape;
|
| |
|
| |
|
| | m_side2.changeMode = ui->changeMode2;
|
| | m_side2.labelLength = ui->labelLength2;
|
| | m_side2.labelOffset = ui->labelOffset2;
|
| | m_side2.labelTaperAngle = ui->labelTaperAngle2;
|
| | m_side2.lengthEdit = ui->lengthEdit2;
|
| | m_side2.offsetEdit = ui->offsetEdit2;
|
| | m_side2.taperEdit = ui->taperEdit2;
|
| | m_side2.lineFaceName = ui->lineFaceName2;
|
| | m_side2.buttonFace = ui->buttonFace2;
|
| | m_side2.lineShapeName = ui->lineShapeName2;
|
| | m_side2.buttonShape = ui->buttonShape2;
|
| | m_side2.listWidgetReferences = ui->listWidgetReferences2;
|
| | m_side2.buttonShapeFace = ui->buttonShapeFace2;
|
| | m_side2.checkBoxAllFaces = ui->checkBoxAllFaces2;
|
| | m_side2.upToShapeList = ui->upToShapeList2;
|
| | m_side2.upToShapeFaces = ui->upToShapeFaces2;
|
| | m_side2.unselectShapeFaceAction = unselectShapeFaceAction2;
|
| |
|
| | m_side2.Type = &extrude->Type2;
|
| | m_side2.Length = &extrude->Length2;
|
| | m_side2.Offset = &extrude->Offset2;
|
| | m_side2.TaperAngle = &extrude->TaperAngle2;
|
| | m_side2.UpToFace = &extrude->UpToFace2;
|
| | m_side2.UpToShape = &extrude->UpToShape2;
|
| | }
|
| |
|
| | void TaskExtrudeParameters::readValuesFromHistory()
|
| | {
|
| | ui->lengthEdit->setToLastUsedValue();
|
| | ui->lengthEdit->selectNumber();
|
| | ui->lengthEdit2->setToLastUsedValue();
|
| | ui->lengthEdit2->selectNumber();
|
| | ui->offsetEdit->setToLastUsedValue();
|
| | ui->offsetEdit->selectNumber();
|
| | ui->offsetEdit2->setToLastUsedValue();
|
| | ui->offsetEdit2->selectNumber();
|
| | ui->taperEdit->setToLastUsedValue();
|
| | ui->taperEdit->selectNumber();
|
| | ui->taperEdit2->setToLastUsedValue();
|
| | ui->taperEdit2->selectNumber();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::connectSlots()
|
| | {
|
| | QMetaObject::connectSlotsByName(this);
|
| |
|
| | auto connectSideSlots = [this](auto& side, Side sideEnum, auto modeChangedSlot) {
|
| | connect(
|
| | side.lengthEdit,
|
| | qOverload<double>(&Gui::PrefQuantitySpinBox::valueChanged),
|
| | this,
|
| | [this, sideEnum](double val) { onLengthChanged(val, sideEnum); }
|
| | );
|
| | connect(
|
| | side.offsetEdit,
|
| | qOverload<double>(&Gui::PrefQuantitySpinBox::valueChanged),
|
| | this,
|
| | [this, sideEnum](double val) { onOffsetChanged(val, sideEnum); }
|
| | );
|
| | connect(
|
| | side.taperEdit,
|
| | qOverload<double>(&Gui::PrefQuantitySpinBox::valueChanged),
|
| | this,
|
| | [this, sideEnum](double val) { onTaperChanged(val, sideEnum); }
|
| | );
|
| | connect(side.changeMode, qOverload<int>(&QComboBox::currentIndexChanged), this, modeChangedSlot);
|
| | connect(side.buttonFace, &QToolButton::toggled, this, [this, sideEnum](bool checked) {
|
| | onSelectFaceToggle(checked, sideEnum);
|
| | });
|
| | connect(side.lineFaceName, &QLineEdit::textEdited, this, [this, sideEnum](const QString& text) {
|
| | onFaceName(text, sideEnum);
|
| | });
|
| | connect(side.checkBoxAllFaces, &QCheckBox::toggled, this, [this, sideEnum](bool checked) {
|
| | onAllFacesToggled(checked, sideEnum);
|
| | });
|
| | connect(side.buttonShape, &QToolButton::toggled, this, [this, sideEnum](bool checked) {
|
| | onSelectShapeToggle(checked, sideEnum);
|
| | });
|
| | connect(side.buttonShapeFace, &QToolButton::toggled, this, [this, sideEnum](bool checked) {
|
| | onSelectShapeFacesToggle(checked, sideEnum);
|
| | });
|
| | connect(side.unselectShapeFaceAction, &QAction::triggered, this, [this, sideEnum]() {
|
| | onUnselectShapeFacesTrigger(sideEnum);
|
| | });
|
| | };
|
| |
|
| |
|
| | connectSideSlots(m_side1, Side::First, &TaskExtrudeParameters::onModeChanged_Side1);
|
| | connectSideSlots(m_side2, Side::Second, &TaskExtrudeParameters::onModeChanged_Side2);
|
| |
|
| |
|
| | connect(ui->directionCB, qOverload<int>(&QComboBox::activated),
|
| | this, &TaskExtrudeParameters::onDirectionCBChanged);
|
| | connect(ui->checkBoxAlongDirection, &QCheckBox::toggled,
|
| | this, &TaskExtrudeParameters::onAlongSketchNormalChanged);
|
| | connect(ui->XDirectionEdit, qOverload<double>(&QDoubleSpinBox::valueChanged),
|
| | this, &TaskExtrudeParameters::onXDirectionEditChanged);
|
| | connect(ui->YDirectionEdit, qOverload<double>(&QDoubleSpinBox::valueChanged),
|
| | this, &TaskExtrudeParameters::onYDirectionEditChanged);
|
| | connect(ui->ZDirectionEdit, qOverload<double>(&QDoubleSpinBox::valueChanged),
|
| | this, &TaskExtrudeParameters::onZDirectionEditChanged);
|
| | connect(ui->checkBoxReversed, &QCheckBox::toggled,
|
| | this, &TaskExtrudeParameters::onReversedChanged);
|
| | connect(ui->sidesMode, qOverload<int>(&QComboBox::currentIndexChanged),
|
| | this, &TaskExtrudeParameters::onSidesModeChanged);
|
| | connect(ui->checkBoxUpdateView, &QCheckBox::toggled,
|
| | this, &TaskExtrudeParameters::onUpdateView);
|
| |
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onModeChanged_Side1(int index)
|
| | {
|
| | onModeChanged(index, Side::First);
|
| | setGizmoPositions();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onModeChanged_Side2(int index)
|
| | {
|
| | onModeChanged(index, Side::Second);
|
| | setGizmoPositions();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onSelectShapeFacesToggle(bool checked, Side side)
|
| | {
|
| | auto& sideCtrl = getSideController(side);
|
| | if (checked) {
|
| | setSelectionMode(SelectShapeFaces, side);
|
| | sideCtrl.buttonShapeFace->setText(tr("Preview"));
|
| | }
|
| | else {
|
| | setSelectionMode(None);
|
| | sideCtrl.buttonShapeFace->setText(tr("Select Faces"));
|
| | }
|
| | }
|
| |
|
| | void PartDesignGui::TaskExtrudeParameters::onUnselectShapeFacesTrigger(Side side)
|
| | {
|
| | auto& sideCtrl = getSideController(side);
|
| |
|
| | auto selected = sideCtrl.listWidgetReferences->selectedItems();
|
| | auto faces = getShapeFaces(*sideCtrl.UpToShape);
|
| |
|
| |
|
| | faces.erase(std::remove_if(faces.begin(), faces.end(), [selected](const std::string& face) {
|
| | for (auto& item : selected) {
|
| | if (item->text().toStdString() == face) {
|
| | return true;
|
| | }
|
| | }
|
| |
|
| | return false;
|
| | }));
|
| |
|
| | sideCtrl.UpToShape->setValue(sideCtrl.UpToShape->getValue(), faces);
|
| |
|
| | updateShapeFaces(sideCtrl.listWidgetReferences, *sideCtrl.UpToShape);
|
| | }
|
| |
|
| | void TaskExtrudeParameters::setSelectionMode(SelectionMode mode, Side side)
|
| | {
|
| | if (selectionMode == mode && activeSelectionSide == side) {
|
| | return;
|
| | }
|
| |
|
| | const auto updateCheckedForSide = [mode, side](
|
| | Side relatedSide,
|
| | QAbstractButton* buttonFace,
|
| | QAbstractButton* buttonShape,
|
| | QAbstractButton* buttonShapeFace
|
| | ) {
|
| | buttonFace->setChecked(mode == SelectFace && side == relatedSide);
|
| | buttonShape->setChecked(mode == SelectShape && side == relatedSide);
|
| | buttonShapeFace->setChecked(mode == SelectShapeFaces && side == relatedSide);
|
| | };
|
| | updateCheckedForSide(Side::First, ui->buttonFace, ui->buttonShape, ui->buttonShapeFace);
|
| | updateCheckedForSide(Side::Second, ui->buttonFace2, ui->buttonShape2, ui->buttonShapeFace2);
|
| |
|
| | selectionMode = mode;
|
| | activeSelectionSide = side;
|
| |
|
| | switch (mode) {
|
| | case SelectShape:
|
| | onSelectReference(AllowSelection::WHOLE);
|
| | Gui::Selection().addSelectionGate(new SelectionFilterGate("SELECT Part::Feature COUNT 1"));
|
| | break;
|
| | case SelectFace:
|
| | onSelectReference(AllowSelection::FACE);
|
| | break;
|
| | case SelectShapeFaces: {
|
| | onSelectReference(AllowSelection::FACE);
|
| | auto& sideCtrl = getSideController(activeSelectionSide);
|
| | getViewObject<ViewProviderExtrude>()->highlightShapeFaces(
|
| | getShapeFaces(*sideCtrl.UpToShape)
|
| | );
|
| | break;
|
| | }
|
| | case SelectReferenceAxis:
|
| | onSelectReference(AllowSelection::EDGE | AllowSelection::PLANAR | AllowSelection::CIRCLE);
|
| | break;
|
| | default:
|
| | getViewObject<ViewProviderExtrude>()->highlightShapeFaces({});
|
| | onSelectReference(AllowSelection::NONE);
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::tryRecomputeFeature()
|
| | {
|
| | try {
|
| |
|
| | recomputeFeature();
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | e.reportException();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
|
| | {
|
| | auto& sideCtrl = getSideController(activeSelectionSide);
|
| |
|
| | if (msg.Type == Gui::SelectionChanges::AddSelection) {
|
| | switch (selectionMode) {
|
| | case SelectShape:
|
| | selectedShape(msg, sideCtrl);
|
| | break;
|
| | case SelectShapeFaces:
|
| | selectedShapeFace(msg, sideCtrl);
|
| | break;
|
| |
|
| | case SelectFace:
|
| | selectedFace(msg, sideCtrl);
|
| | break;
|
| |
|
| | case SelectReferenceAxis:
|
| | selectedReferenceAxis(msg);
|
| | break;
|
| |
|
| | default:
|
| |
|
| | break;
|
| | }
|
| | }
|
| | else if (msg.Type == Gui::SelectionChanges::ClrSelection) {
|
| | if (selectionMode == SelectFace) {
|
| | clearFaceName(sideCtrl.lineFaceName);
|
| | }
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::selectedReferenceAxis(const Gui::SelectionChanges& msg)
|
| | {
|
| | std::vector<std::string> edge;
|
| | App::DocumentObject* selObj;
|
| |
|
| | if (getReferencedSelection(getObject(), msg, selObj, edge) && selObj) {
|
| | setSelectionMode(None);
|
| |
|
| | propReferenceAxis->setValue(selObj, edge);
|
| | tryRecomputeFeature();
|
| |
|
| |
|
| | fillDirectionCombo();
|
| |
|
| | setGizmoPositions();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::selectedShapeFace(const Gui::SelectionChanges& msg, SideController& side)
|
| | {
|
| | auto extrude = getObject<PartDesign::FeatureExtrude>();
|
| | auto document = extrude->getDocument();
|
| |
|
| | if (strcmp(msg.pDocName, document->getName()) != 0) {
|
| | return;
|
| | }
|
| |
|
| |
|
| | auto base = static_cast<Part::Feature*>(side.UpToShape->getValue());
|
| | if (!base) {
|
| | base = static_cast<Part::Feature*>(extrude);
|
| | }
|
| | else if (strcmp(msg.pObjectName, base->getNameInDocument()) != 0) {
|
| | return;
|
| | }
|
| |
|
| | std::vector<std::string> faces = getShapeFaces(*side.UpToShape);
|
| | const std::string subName(msg.pSubName);
|
| |
|
| | if (subName.empty()) {
|
| | return;
|
| | }
|
| |
|
| |
|
| | if (const auto positionInList = std::ranges::find(faces, subName); positionInList != faces.end()) {
|
| | faces.erase(positionInList);
|
| | }
|
| | else {
|
| | faces.push_back(subName);
|
| | }
|
| |
|
| | side.UpToShape->setValue(base, faces);
|
| |
|
| | updateShapeFaces(side.listWidgetReferences, *side.UpToShape);
|
| |
|
| | tryRecomputeFeature();
|
| | }
|
| |
|
| | void PartDesignGui::TaskExtrudeParameters::selectedFace(
|
| | const Gui::SelectionChanges& msg,
|
| | SideController& side
|
| | )
|
| | {
|
| | QString refText = onAddSelection(msg, *side.UpToFace);
|
| |
|
| | if (refText.length() > 0) {
|
| | QSignalBlocker block(side.lineFaceName);
|
| |
|
| | side.lineFaceName->setText(refText);
|
| | side.lineFaceName->setProperty("FeatureName", QByteArray(msg.pObjectName));
|
| | side.lineFaceName->setProperty("FaceName", QByteArray(msg.pSubName));
|
| |
|
| |
|
| | side.buttonFace->setChecked(false);
|
| | }
|
| | else {
|
| | clearFaceName(side.lineFaceName);
|
| | }
|
| |
|
| | setSelectionMode(None);
|
| | }
|
| |
|
| | void PartDesignGui::TaskExtrudeParameters::selectedShape(
|
| | const Gui::SelectionChanges& msg,
|
| | SideController& side
|
| | )
|
| | {
|
| | auto document = getObject()->getDocument();
|
| |
|
| | if (strcmp(msg.pDocName, document->getName()) != 0) {
|
| | return;
|
| | }
|
| |
|
| | Gui::Selection().clearSelection();
|
| |
|
| | auto ref = document->getObject(msg.pObjectName);
|
| |
|
| | side.UpToShape->setValue(ref);
|
| |
|
| | side.checkBoxAllFaces->setChecked(true);
|
| |
|
| | setSelectionMode(None);
|
| |
|
| | updateShapeName(side.lineShapeName, *side.UpToShape);
|
| | updateShapeFaces(side.listWidgetReferences, *side.UpToShape);
|
| |
|
| | tryRecomputeFeature();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::clearFaceName(QLineEdit* lineEdit)
|
| | {
|
| | QSignalBlocker block(lineEdit);
|
| | lineEdit->clear();
|
| | lineEdit->setProperty("FeatureName", QVariant());
|
| | lineEdit->setProperty("FaceName", QVariant());
|
| | }
|
| |
|
| | void TaskExtrudeParameters::updateShapeName(QLineEdit* lineEdit, App::PropertyLinkSubList& prop)
|
| | {
|
| | QSignalBlocker block(lineEdit);
|
| |
|
| | auto shape = prop.getValue();
|
| |
|
| | if (shape) {
|
| | lineEdit->setText(QString::fromStdString(shape->getFullName()));
|
| | }
|
| | else {
|
| | lineEdit->setText({});
|
| | lineEdit->setPlaceholderText(tr("No shape selected"));
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::updateShapeFaces(QListWidget* list, App::PropertyLinkSubList& prop)
|
| | {
|
| | auto faces = getShapeFaces(prop);
|
| |
|
| | list->clear();
|
| | for (auto& ref : faces) {
|
| | list->addItem(QString::fromStdString(ref));
|
| | }
|
| |
|
| | if (selectionMode == SelectShapeFaces) {
|
| | getViewObject<ViewProviderExtrude>()->highlightShapeFaces(faces);
|
| | }
|
| | }
|
| |
|
| | std::vector<std::string> PartDesignGui::TaskExtrudeParameters::getShapeFaces(
|
| | App::PropertyLinkSubList& prop
|
| | )
|
| | {
|
| | std::vector<std::string> faces;
|
| |
|
| | auto allRefs = prop.getSubValues();
|
| |
|
| | std::copy_if(allRefs.begin(), allRefs.end(), std::back_inserter(faces), [](const std::string& ref) {
|
| | return boost::starts_with(ref, "Face");
|
| | });
|
| |
|
| | return faces;
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onLengthChanged(double len, Side side)
|
| | {
|
| | getSideController(side).Length->setValue(len);
|
| | tryRecomputeFeature();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onOffsetChanged(double len, Side side)
|
| | {
|
| | getSideController(side).Offset->setValue(len);
|
| | tryRecomputeFeature();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onTaperChanged(double angle, Side side)
|
| | {
|
| | getSideController(side).TaperAngle->setValue(angle);
|
| | tryRecomputeFeature();
|
| | }
|
| |
|
| | bool TaskExtrudeParameters::hasProfileFace(PartDesign::ProfileBased* profile) const
|
| | {
|
| | try {
|
| | Part::Feature* pcFeature = profile->getVerifiedObject();
|
| | Base::Vector3d SketchVector = profile->getProfileNormal();
|
| | Q_UNUSED(pcFeature)
|
| | Q_UNUSED(SketchVector)
|
| | return true;
|
| | }
|
| | catch (const Base::Exception&) {
|
| | }
|
| |
|
| | return false;
|
| | }
|
| |
|
| | void TaskExtrudeParameters::fillDirectionCombo()
|
| | {
|
| | Base::StateLocker lock(getUpdateBlockRef(), true);
|
| |
|
| | if (axesInList.empty()) {
|
| | bool hasFace = false;
|
| | ui->directionCB->clear();
|
| |
|
| |
|
| | auto pcFeat = getObject<PartDesign::ProfileBased>();
|
| | Part::Part2DObject* pcSketch = dynamic_cast<Part::Part2DObject*>(pcFeat->Profile.getValue());
|
| |
|
| | if (!pcSketch) {
|
| | hasFace = hasProfileFace(pcFeat);
|
| | }
|
| |
|
| | if (pcSketch) {
|
| | addAxisToCombo(pcSketch, "N_Axis", tr("Sketch normal"));
|
| | }
|
| | else if (hasFace) {
|
| | addAxisToCombo(pcFeat->Profile.getValue(), std::string(), tr("Face normal"), false);
|
| | }
|
| |
|
| |
|
| | addAxisToCombo(nullptr, std::string(), tr("Select reference…"));
|
| |
|
| |
|
| | if (pcSketch) {
|
| | addAxisToCombo(pcSketch, "N_Axis", tr("Custom direction"));
|
| | }
|
| | else if (hasFace) {
|
| | addAxisToCombo(pcFeat->Profile.getValue(), std::string(), tr("Custom direction"), false);
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| | int indexOfCurrent = -1;
|
| | App::DocumentObject* ax = propReferenceAxis->getValue();
|
| | const std::vector<std::string>& subList = propReferenceAxis->getSubValues();
|
| | for (size_t i = 0; i < axesInList.size(); i++) {
|
| | if (ax == axesInList[i]->getValue() && subList == axesInList[i]->getSubValues()) {
|
| | indexOfCurrent = i;
|
| | break;
|
| | }
|
| | }
|
| |
|
| | if (indexOfCurrent == -1 && ax) {
|
| | assert(subList.size() <= 1);
|
| | std::string sub;
|
| | if (!subList.empty()) {
|
| | sub = subList[0];
|
| | }
|
| | addAxisToCombo(ax, sub, getRefStr(ax, subList));
|
| | indexOfCurrent = axesInList.size() - 1;
|
| |
|
| | ui->checkBoxAlongDirection->setEnabled(true);
|
| |
|
| | ui->XDirectionEdit->setEnabled(false);
|
| | ui->YDirectionEdit->setEnabled(false);
|
| | ui->ZDirectionEdit->setEnabled(false);
|
| | }
|
| |
|
| |
|
| | auto extrude = getObject<PartDesign::FeatureExtrude>();
|
| | bool hasCustom = extrude->UseCustomVector.getValue();
|
| | if (indexOfCurrent != -1 && !hasCustom) {
|
| | ui->directionCB->setCurrentIndex(indexOfCurrent);
|
| | updateDirectionEdits();
|
| | setDirectionMode(indexOfCurrent);
|
| | }
|
| | if (hasCustom) {
|
| | ui->directionCB->setCurrentIndex(DirectionModes::Custom);
|
| | setDirectionMode(ui->directionCB->currentIndex());
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::addAxisToCombo(
|
| | App::DocumentObject* linkObj,
|
| | std::string linkSubname,
|
| | QString itemText,
|
| | bool hasSketch
|
| | )
|
| | {
|
| | this->ui->directionCB->addItem(itemText);
|
| | this->axesInList.emplace_back(new App::PropertyLinkSub);
|
| | App::PropertyLinkSub& lnk = *(axesInList.back());
|
| |
|
| |
|
| | if (hasSketch) {
|
| | lnk.setValue(linkObj, std::vector<std::string>(1, linkSubname));
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::updateWholeUI(Type type, Side side)
|
| | {
|
| | SidesMode sidesMode = static_cast<SidesMode>(ui->sidesMode->currentIndex());
|
| | Mode mode1 = static_cast<Mode>(ui->changeMode->currentIndex());
|
| | Mode mode2 = static_cast<Mode>(ui->changeMode2->currentIndex());
|
| |
|
| |
|
| | const bool isSide2GroupVisible = (sidesMode == SidesMode::TwoSides);
|
| | ui->side1Label->setVisible(isSide2GroupVisible);
|
| | ui->side2Label->setVisible(isSide2GroupVisible);
|
| | ui->line2->setVisible(isSide2GroupVisible);
|
| | ui->typeLabel2->setVisible(isSide2GroupVisible);
|
| | ui->changeMode2->setVisible(isSide2GroupVisible);
|
| |
|
| |
|
| |
|
| | updateSideUI(m_side1, type, mode1, true, (side == Side::First));
|
| |
|
| | updateSideUI(m_side2, type, mode2, isSide2GroupVisible, (side == Side::Second));
|
| |
|
| | ui->checkBoxReversed->setEnabled(sidesMode != SidesMode::Symmetric || mode1 != Mode::Dimension);
|
| | }
|
| |
|
| | void TaskExtrudeParameters::updateSideUI(
|
| | const SideController& s,
|
| | Type featureType,
|
| | Mode sideMode,
|
| | bool isParentVisible,
|
| | bool setFocus
|
| | )
|
| | {
|
| |
|
| | bool isLengthVisible = false;
|
| | bool isOffsetVisible = false;
|
| | bool isTaperVisible = false;
|
| | bool isFaceVisible = false;
|
| | bool isShapeVisible = false;
|
| |
|
| |
|
| | if (sideMode == Mode::Dimension) {
|
| | isLengthVisible = true;
|
| | isTaperVisible = true;
|
| | if (setFocus) {
|
| | s.lengthEdit->selectNumber();
|
| | QMetaObject::invokeMethod(s.lengthEdit, "setFocus", Qt::QueuedConnection);
|
| | }
|
| | }
|
| | else if (sideMode == Mode::ThroughAll && featureType == Type::Pocket) {
|
| | isTaperVisible = true;
|
| | }
|
| | else if (sideMode == Mode::ToLast && featureType == Type::Pad) {
|
| | isOffsetVisible = true;
|
| | }
|
| | else if (sideMode == Mode::ToFirst) {
|
| | isOffsetVisible = true;
|
| | }
|
| | else if (sideMode == Mode::ToFace) {
|
| | isOffsetVisible = true;
|
| | isFaceVisible = true;
|
| | if (setFocus) {
|
| | QMetaObject::invokeMethod(s.lineFaceName, "setFocus", Qt::QueuedConnection);
|
| |
|
| | if (s.lineFaceName->property("FeatureName").isNull()) {
|
| | s.buttonFace->setChecked(true);
|
| | }
|
| | }
|
| | }
|
| | else if (sideMode == Mode::ToShape) {
|
| | isShapeVisible = true;
|
| | if (setFocus) {
|
| | if (!s.checkBoxAllFaces->isChecked()) {
|
| | s.buttonShapeFace->setChecked(true);
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| | const bool finalLengthVisible = isParentVisible && isLengthVisible;
|
| | s.labelLength->setVisible(finalLengthVisible);
|
| | s.lengthEdit->setVisible(finalLengthVisible);
|
| | s.lengthEdit->setEnabled(finalLengthVisible);
|
| |
|
| | const bool finalOffsetVisible = isParentVisible && isOffsetVisible;
|
| | s.labelOffset->setVisible(finalOffsetVisible);
|
| | s.offsetEdit->setVisible(finalOffsetVisible);
|
| | s.offsetEdit->setEnabled(finalOffsetVisible);
|
| |
|
| | const bool finalTaperVisible = isParentVisible && isTaperVisible;
|
| | s.labelTaperAngle->setVisible(finalTaperVisible);
|
| | s.taperEdit->setVisible(finalTaperVisible);
|
| | s.taperEdit->setEnabled(finalTaperVisible);
|
| |
|
| | s.buttonFace->setVisible(isParentVisible && isFaceVisible);
|
| | s.lineFaceName->setVisible(isParentVisible && isFaceVisible);
|
| | if (!isFaceVisible) {
|
| | s.buttonFace->setChecked(false);
|
| | }
|
| |
|
| | s.upToShapeList->setVisible(isParentVisible && isShapeVisible);
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onDirectionCBChanged(int num)
|
| | {
|
| | if (axesInList.empty()) {
|
| | return;
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | App::PropertyLinkSub& lnk = *(axesInList[num]);
|
| |
|
| | if (num == DirectionModes::Select) {
|
| |
|
| | setSelectionMode(SelectReferenceAxis);
|
| | setDirectionMode(num);
|
| | }
|
| | else if (auto extrude = getObject<PartDesign::FeatureExtrude>()) {
|
| | if (lnk.getValue()) {
|
| | if (!extrude->getDocument()->isIn(lnk.getValue())) {
|
| | Base::Console().error("Object was deleted\n");
|
| | return;
|
| | }
|
| | propReferenceAxis->Paste(lnk);
|
| | }
|
| |
|
| |
|
| | setSelectionMode(None);
|
| | setDirectionMode(num);
|
| |
|
| | extrude->ReferenceAxis.setValue(lnk.getValue(), lnk.getSubValues());
|
| | tryRecomputeFeature();
|
| | updateDirectionEdits();
|
| |
|
| | setGizmoPositions();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onAlongSketchNormalChanged(bool on)
|
| | {
|
| | if (auto extrude = getObject<PartDesign::FeatureExtrude>()) {
|
| | extrude->AlongSketchNormal.setValue(on);
|
| | tryRecomputeFeature();
|
| |
|
| | setGizmoPositions();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onAllFacesToggled(bool on, Side side)
|
| | {
|
| | auto& sideCtrl = getSideController(side);
|
| | sideCtrl.upToShapeFaces->setVisible(!on);
|
| | sideCtrl.buttonShapeFace->setChecked(false);
|
| |
|
| | if (on) {
|
| | if (auto extrude = getObject<PartDesign::FeatureExtrude>()) {
|
| | extrude->UpToShape.setValue(extrude->UpToShape.getValue());
|
| | updateShapeFaces(sideCtrl.listWidgetReferences, *sideCtrl.UpToShape);
|
| | tryRecomputeFeature();
|
| | }
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onXDirectionEditChanged(double len)
|
| | {
|
| | if (auto extrude = getObject<PartDesign::FeatureExtrude>()) {
|
| | extrude->Direction
|
| | .setValue(len, extrude->Direction.getValue().y, extrude->Direction.getValue().z);
|
| | tryRecomputeFeature();
|
| |
|
| |
|
| |
|
| | updateDirectionEdits();
|
| | setGizmoPositions();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onYDirectionEditChanged(double len)
|
| | {
|
| | if (auto extrude = getObject<PartDesign::FeatureExtrude>()) {
|
| | extrude->Direction
|
| | .setValue(extrude->Direction.getValue().x, len, extrude->Direction.getValue().z);
|
| | tryRecomputeFeature();
|
| | updateDirectionEdits();
|
| | setGizmoPositions();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onZDirectionEditChanged(double len)
|
| | {
|
| | if (auto extrude = getObject<PartDesign::FeatureExtrude>()) {
|
| | extrude->Direction
|
| | .setValue(extrude->Direction.getValue().x, extrude->Direction.getValue().y, len);
|
| | tryRecomputeFeature();
|
| | updateDirectionEdits();
|
| | setGizmoPositions();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::updateDirectionEdits()
|
| | {
|
| | auto extrude = getObject<PartDesign::FeatureExtrude>();
|
| |
|
| | QSignalBlocker xdir(ui->XDirectionEdit);
|
| | QSignalBlocker ydir(ui->YDirectionEdit);
|
| | QSignalBlocker zdir(ui->ZDirectionEdit);
|
| | ui->XDirectionEdit->setValue(extrude->Direction.getValue().x);
|
| | ui->YDirectionEdit->setValue(extrude->Direction.getValue().y);
|
| | ui->ZDirectionEdit->setValue(extrude->Direction.getValue().z);
|
| | }
|
| |
|
| | void TaskExtrudeParameters::setDirectionMode(int index)
|
| | {
|
| | auto extrude = getObject<PartDesign::FeatureExtrude>();
|
| | if (!extrude) {
|
| | return;
|
| | }
|
| |
|
| | switch (index) {
|
| |
|
| | case DirectionModes::Normal:
|
| | ui->groupBoxDirection->hide();
|
| |
|
| | extrude->UseCustomVector.setValue(false);
|
| | ui->XDirectionEdit->setEnabled(false);
|
| | ui->YDirectionEdit->setEnabled(false);
|
| | ui->ZDirectionEdit->setEnabled(false);
|
| |
|
| | ui->checkBoxAlongDirection->setEnabled(false);
|
| | ui->checkBoxAlongDirection->hide();
|
| |
|
| | break;
|
| |
|
| |
|
| |
|
| |
|
| | case DirectionModes::Custom:
|
| | ui->groupBoxDirection->show();
|
| |
|
| | extrude->UseCustomVector.setValue(true);
|
| | ui->XDirectionEdit->setEnabled(true);
|
| | ui->YDirectionEdit->setEnabled(true);
|
| | ui->ZDirectionEdit->setEnabled(true);
|
| |
|
| | ui->checkBoxAlongDirection->setEnabled(true);
|
| | ui->checkBoxAlongDirection->show();
|
| | break;
|
| |
|
| | default:
|
| | ui->groupBoxDirection->show();
|
| |
|
| | updateDirectionEdits();
|
| |
|
| | extrude->UseCustomVector.setValue(false);
|
| | ui->XDirectionEdit->setEnabled(false);
|
| | ui->YDirectionEdit->setEnabled(false);
|
| | ui->ZDirectionEdit->setEnabled(false);
|
| |
|
| | ui->checkBoxAlongDirection->setEnabled(true);
|
| | ui->checkBoxAlongDirection->show();
|
| | break;
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onReversedChanged(bool on)
|
| | {
|
| | if (auto extrude = getObject<PartDesign::FeatureExtrude>()) {
|
| | extrude->Reversed.setValue(on);
|
| |
|
| | tryRecomputeFeature();
|
| | updateDirectionEdits();
|
| |
|
| | setGizmoPositions();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::getReferenceAxis(App::DocumentObject*& obj, std::vector<std::string>& sub) const
|
| | {
|
| | if (axesInList.empty()) {
|
| | throw Base::RuntimeError("Not initialized!");
|
| | }
|
| |
|
| | int num = ui->directionCB->currentIndex();
|
| | const App::PropertyLinkSub& lnk = *(axesInList[num]);
|
| | if (!lnk.getValue()) {
|
| |
|
| |
|
| | obj = nullptr;
|
| | sub.clear();
|
| | }
|
| | else {
|
| | auto pcDirection = getObject<PartDesign::ProfileBased>();
|
| | if (!pcDirection->getDocument()->isIn(lnk.getValue())) {
|
| | throw Base::RuntimeError("Object was deleted");
|
| | }
|
| |
|
| | obj = lnk.getValue();
|
| | sub = lnk.getSubValues();
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onSelectFaceToggle(const bool checked, Side side)
|
| | {
|
| | auto& sideCtrl = getSideController(side);
|
| | if (checked) {
|
| | handleLineFaceNameClick(sideCtrl.lineFaceName);
|
| | setSelectionMode(SelectFace, side);
|
| | }
|
| | else {
|
| | handleLineFaceNameNo(sideCtrl.lineFaceName);
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onSelectShapeToggle(bool checked, Side side)
|
| | {
|
| | auto& sideCtrl = getSideController(side);
|
| | if (checked) {
|
| | setSelectionMode(SelectShape, side);
|
| | sideCtrl.lineShapeName->setText({});
|
| | sideCtrl.lineShapeName->setPlaceholderText(tr("Click on a shape in the model"));
|
| | }
|
| | else {
|
| | setSelectionMode(None);
|
| | updateShapeName(sideCtrl.lineShapeName, *sideCtrl.UpToShape);
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onFaceName(const QString& text, Side side)
|
| | {
|
| | auto& sideCtrl = getSideController(side);
|
| | changeFaceName(sideCtrl.lineFaceName, text);
|
| | }
|
| |
|
| | void TaskExtrudeParameters::changeFaceName(QLineEdit* lineEdit, const QString& text)
|
| | {
|
| | if (text.isEmpty()) {
|
| |
|
| | lineEdit->setProperty("FeatureName", QVariant());
|
| | lineEdit->setProperty("FaceName", QVariant());
|
| | }
|
| | else {
|
| |
|
| | QStringList parts = text.split(QChar::fromLatin1(':'));
|
| | QString label = parts[0];
|
| | QVariant name = objectNameByLabel(label, lineEdit->property("FeatureName"));
|
| | if (name.isValid()) {
|
| | parts[0] = name.toString();
|
| | QString uptoface = parts.join(QStringLiteral(":"));
|
| | lineEdit->setProperty("FeatureName", name);
|
| | lineEdit->setProperty("FaceName", setUpToFace(uptoface));
|
| | }
|
| | else {
|
| | lineEdit->setProperty("FeatureName", QVariant());
|
| | lineEdit->setProperty("FaceName", QVariant());
|
| | }
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::translateFaceName(QLineEdit* lineEdit)
|
| | {
|
| | handleLineFaceNameNo(lineEdit);
|
| | QVariant featureName = lineEdit->property("FeatureName");
|
| | if (featureName.isValid()) {
|
| | QStringList parts = lineEdit->text().split(QChar::fromLatin1(':'));
|
| | QByteArray upToFace = lineEdit->property("FaceName").toByteArray();
|
| | int faceId = -1;
|
| | bool ok = false;
|
| | if (upToFace.indexOf("Face") == 0) {
|
| | faceId = upToFace.remove(0, 4).toInt(&ok);
|
| | }
|
| |
|
| | if (ok) {
|
| | lineEdit->setText(QStringLiteral("%1:%2%3").arg(parts[0], tr("Face")).arg(faceId));
|
| | }
|
| | else {
|
| | lineEdit->setText(parts[0]);
|
| | }
|
| | }
|
| | }
|
| |
|
| | double TaskExtrudeParameters::getOffset() const
|
| | {
|
| | return ui->offsetEdit->value().getValue();
|
| | }
|
| |
|
| | double TaskExtrudeParameters::getOffset2() const
|
| | {
|
| | return ui->offsetEdit2->value().getValue();
|
| | }
|
| |
|
| | bool TaskExtrudeParameters::getAlongSketchNormal() const
|
| | {
|
| | return ui->checkBoxAlongDirection->isChecked();
|
| | }
|
| |
|
| | bool TaskExtrudeParameters::getCustom() const
|
| | {
|
| | return (ui->directionCB->currentIndex() == DirectionModes::Custom);
|
| | }
|
| |
|
| | std::string TaskExtrudeParameters::getReferenceAxis() const
|
| | {
|
| | std::vector<std::string> sub;
|
| | App::DocumentObject* obj;
|
| | getReferenceAxis(obj, sub);
|
| | return buildLinkSingleSubPythonStr(obj, sub);
|
| | }
|
| |
|
| | double TaskExtrudeParameters::getXDirection() const
|
| | {
|
| | return ui->XDirectionEdit->value();
|
| | }
|
| |
|
| | double TaskExtrudeParameters::getYDirection() const
|
| | {
|
| | return ui->YDirectionEdit->value();
|
| | }
|
| |
|
| | double TaskExtrudeParameters::getZDirection() const
|
| | {
|
| | return ui->ZDirectionEdit->value();
|
| | }
|
| |
|
| | bool TaskExtrudeParameters::getReversed() const
|
| | {
|
| | return ui->checkBoxReversed->isChecked();
|
| | }
|
| |
|
| | int TaskExtrudeParameters::getMode() const
|
| | {
|
| | return ui->changeMode->currentIndex();
|
| | }
|
| |
|
| | int TaskExtrudeParameters::getMode2() const
|
| | {
|
| | return ui->changeMode2->currentIndex();
|
| | }
|
| |
|
| | int TaskExtrudeParameters::getSidesMode() const
|
| | {
|
| | return ui->sidesMode->currentIndex();
|
| | }
|
| |
|
| | QString TaskExtrudeParameters::getFaceName(QLineEdit* lineEdit) const
|
| | {
|
| | QVariant featureName = lineEdit->property("FeatureName");
|
| | if (featureName.isValid()) {
|
| | QString faceName = lineEdit->property("FaceName").toString();
|
| | return getFaceReference(featureName.toString(), faceName);
|
| | }
|
| |
|
| | return QStringLiteral("None");
|
| | }
|
| |
|
| | void TaskExtrudeParameters::changeEvent(QEvent* e)
|
| | {
|
| | TaskBox::changeEvent(e);
|
| | if (e->type() == QEvent::LanguageChange) {
|
| | QSignalBlocker length(ui->lengthEdit);
|
| | QSignalBlocker length2(ui->lengthEdit2);
|
| | QSignalBlocker offset(ui->offsetEdit);
|
| | QSignalBlocker offset2(ui->offsetEdit2);
|
| | QSignalBlocker taper(ui->taperEdit);
|
| | QSignalBlocker taper2(ui->taperEdit2);
|
| | QSignalBlocker xdir(ui->XDirectionEdit);
|
| | QSignalBlocker ydir(ui->YDirectionEdit);
|
| | QSignalBlocker zdir(ui->ZDirectionEdit);
|
| | QSignalBlocker dir(ui->directionCB);
|
| | QSignalBlocker face(ui->lineFaceName);
|
| | QSignalBlocker face2(ui->lineFaceName2);
|
| | QSignalBlocker mode(ui->changeMode);
|
| | QSignalBlocker mode2(ui->changeMode2);
|
| | QSignalBlocker sidesMode(ui->sidesMode);
|
| |
|
| |
|
| | QStringList items;
|
| | for (int i = 0; i < ui->directionCB->count(); i++) {
|
| | items << ui->directionCB->itemText(i);
|
| | }
|
| |
|
| |
|
| | int index = ui->directionCB->currentIndex();
|
| | ui->retranslateUi(proxy);
|
| |
|
| |
|
| | for (int i = 0; i < ui->directionCB->count(); i++) {
|
| | items.pop_front();
|
| | }
|
| | ui->directionCB->addItems(items);
|
| | ui->directionCB->setCurrentIndex(index);
|
| |
|
| |
|
| | translateModeList(ui->changeMode, ui->changeMode->currentIndex());
|
| | translateModeList(ui->changeMode2, ui->changeMode2->currentIndex());
|
| | translateSidesList(ui->sidesMode->currentIndex());
|
| |
|
| | translateFaceName(ui->lineFaceName);
|
| | translateFaceName(ui->lineFaceName2);
|
| | }
|
| | }
|
| |
|
| | void TaskExtrudeParameters::saveHistory()
|
| | {
|
| |
|
| | ui->lengthEdit->pushToHistory();
|
| | ui->lengthEdit2->pushToHistory();
|
| | ui->offsetEdit->pushToHistory();
|
| | ui->offsetEdit2->pushToHistory();
|
| | ui->taperEdit->pushToHistory();
|
| | ui->taperEdit2->pushToHistory();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::applyParameters()
|
| | {
|
| | auto obj = getObject();
|
| |
|
| | QString facename = QStringLiteral("None");
|
| | QString facename2 = QStringLiteral("None");
|
| | if (static_cast<Mode>(getMode()) == Mode::ToFace) {
|
| | facename = getFaceName(ui->lineFaceName);
|
| | }
|
| | if (static_cast<Mode>(getMode2()) == Mode::ToFace) {
|
| | facename2 = getFaceName(ui->lineFaceName2);
|
| | }
|
| |
|
| |
|
| | int type1 = getMode();
|
| | if (static_cast<Mode>(type1) == Mode::ToShape) {
|
| | type1++;
|
| | }
|
| | int type2 = getMode2();
|
| | if (static_cast<Mode>(type2) == Mode::ToShape) {
|
| | type2++;
|
| | }
|
| |
|
| | ui->lengthEdit->apply();
|
| | ui->lengthEdit2->apply();
|
| | ui->taperEdit->apply();
|
| | ui->taperEdit2->apply();
|
| | FCMD_OBJ_CMD(obj, "UseCustomVector = " << (getCustom() ? 1 : 0));
|
| | FCMD_OBJ_CMD(
|
| | obj,
|
| | "Direction = (" << getXDirection() << ", " << getYDirection() << ", " << getZDirection() << ")"
|
| | );
|
| | FCMD_OBJ_CMD(obj, "ReferenceAxis = " << getReferenceAxis());
|
| | FCMD_OBJ_CMD(obj, "AlongSketchNormal = " << (getAlongSketchNormal() ? 1 : 0));
|
| | FCMD_OBJ_CMD(obj, "SideType = " << getSidesMode());
|
| | FCMD_OBJ_CMD(obj, "Type = " << type1);
|
| | FCMD_OBJ_CMD(obj, "Type2 = " << type2);
|
| | FCMD_OBJ_CMD(obj, "UpToFace = " << facename.toUtf8().data());
|
| | FCMD_OBJ_CMD(obj, "UpToFace2 = " << facename2.toUtf8().data());
|
| | FCMD_OBJ_CMD(obj, "Reversed = " << (getReversed() ? 1 : 0));
|
| | FCMD_OBJ_CMD(obj, "Offset = " << getOffset());
|
| | FCMD_OBJ_CMD(obj, "Offset2 = " << getOffset2());
|
| | }
|
| |
|
| | void TaskExtrudeParameters::onSidesModeChanged(int index)
|
| | {
|
| | auto extrude = getObject<PartDesign::FeatureExtrude>();
|
| | switch (static_cast<SidesMode>(index)) {
|
| | case SidesMode::OneSide:
|
| | extrude->SideType.setValue("One side");
|
| | updateUI(Side::First);
|
| | break;
|
| | case SidesMode::TwoSides:
|
| | extrude->SideType.setValue("Two sides");
|
| | updateUI(Side::Second);
|
| | break;
|
| | case SidesMode::Symmetric:
|
| | extrude->SideType.setValue("Symmetric");
|
| | updateUI(Side::First);
|
| | break;
|
| | }
|
| |
|
| | recomputeFeature();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::updateUI(Side)
|
| | {
|
| |
|
| | }
|
| |
|
| | void TaskExtrudeParameters::translateModeList(QComboBox*, int)
|
| | {
|
| |
|
| | }
|
| |
|
| | void TaskExtrudeParameters::translateSidesList(int index)
|
| | {
|
| | ui->sidesMode->clear();
|
| | ui->sidesMode->addItem(tr("One sided"));
|
| | ui->sidesMode->addItem(tr("Two sided"));
|
| | ui->sidesMode->addItem(tr("Symmetric"));
|
| | ui->sidesMode->setCurrentIndex(index);
|
| | }
|
| |
|
| | void TaskExtrudeParameters::handleLineFaceNameClick(QLineEdit* lineEdit)
|
| | {
|
| | lineEdit->setPlaceholderText(tr("Click on a face in the model"));
|
| | }
|
| |
|
| | void TaskExtrudeParameters::handleLineFaceNameNo(QLineEdit* lineEdit)
|
| | {
|
| | lineEdit->setPlaceholderText(tr("No face selected"));
|
| | }
|
| |
|
| | void TaskExtrudeParameters::setupGizmos()
|
| | {
|
| | if (GizmoContainer::isEnabled() == false) {
|
| | return;
|
| | }
|
| |
|
| | lengthGizmo1 = new Gui::LinearGizmo(ui->lengthEdit);
|
| | lengthGizmo2 = new Gui::LinearGizmo(ui->lengthEdit2);
|
| | taperAngleGizmo1 = new Gui::RotationGizmo(ui->taperEdit);
|
| | taperAngleGizmo2 = new Gui::RotationGizmo(ui->taperEdit2);
|
| |
|
| | connect(ui->sidesMode, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) {
|
| | setGizmoPositions();
|
| | });
|
| |
|
| | gizmoContainer = GizmoContainer::create(
|
| | {lengthGizmo1, lengthGizmo2, taperAngleGizmo1, taperAngleGizmo2},
|
| | vp
|
| | );
|
| |
|
| | setGizmoPositions();
|
| | }
|
| |
|
| | void TaskExtrudeParameters::setGizmoPositions()
|
| | {
|
| | if (!gizmoContainer) {
|
| | return;
|
| | }
|
| |
|
| | auto extrude = getObject<PartDesign::FeatureExtrude>();
|
| | if (!extrude || extrude->isError()) {
|
| | gizmoContainer->visible = false;
|
| | return;
|
| | }
|
| | gizmoContainer->visible = true;
|
| |
|
| | PartDesign::TopoShape shape = extrude->getProfileShape();
|
| | Base::Vector3d center = getMidPointFromProfile(shape);
|
| | std::string sideType = std::string(extrude->SideType.getValueAsString());
|
| | std::string extrudeType = std::string(extrude->Type.getValueAsString());
|
| | std::string extrudeType2 = std::string(extrude->Type2.getValueAsString());
|
| | double dir = extrude->Reversed.getValue() ? -1 : 1;
|
| |
|
| | lengthGizmo1->Gizmo::setDraggerPlacement(center, extrude->Direction.getValue() * dir);
|
| | lengthGizmo1->setVisibility(extrudeType == "Length");
|
| | taperAngleGizmo1->placeOverLinearGizmo(lengthGizmo1);
|
| | taperAngleGizmo1->setVisibility(extrudeType == "Length");
|
| | lengthGizmo2->Gizmo::setDraggerPlacement(center, -extrude->Direction.getValue() * dir);
|
| | lengthGizmo2->setVisibility(sideType == "Two sides" && extrudeType2 == "Length");
|
| | taperAngleGizmo2->placeOverLinearGizmo(lengthGizmo2);
|
| | taperAngleGizmo2->setVisibility(sideType == "Two sides" && extrudeType2 == "Length");
|
| |
|
| | Base::Vector3d padDir = extrude->Direction.getValue().Normalized();
|
| | Base::Vector3d sketchDir = extrude->getProfileNormal().Normalized();
|
| |
|
| | double lengthFactor = padDir.Dot(sketchDir);
|
| | double multFactor = (sideType == "Symmetric") ? 0.5 : 1.0;
|
| |
|
| |
|
| |
|
| |
|
| | if (extrude->AlongSketchNormal.getValue()) {
|
| | lengthGizmo1->setMultFactor(multFactor / lengthFactor);
|
| | lengthGizmo2->setMultFactor(multFactor / lengthFactor);
|
| | }
|
| | else {
|
| | lengthGizmo1->setMultFactor(multFactor);
|
| | lengthGizmo2->setMultFactor(multFactor);
|
| | }
|
| |
|
| | gizmoContainer->calculateScaleAndOrientation();
|
| | }
|
| |
|
| | TaskDlgExtrudeParameters::TaskDlgExtrudeParameters(PartDesignGui::ViewProviderExtrude* vp)
|
| | : TaskDlgSketchBasedParameters(vp)
|
| | {}
|
| |
|
| | bool TaskDlgExtrudeParameters::accept()
|
| | {
|
| | getTaskParameters()->setSelectionMode(TaskExtrudeParameters::None);
|
| |
|
| | return TaskDlgSketchBasedParameters::accept();
|
| | }
|
| |
|
| | bool TaskDlgExtrudeParameters::reject()
|
| | {
|
| | getTaskParameters()->setSelectionMode(TaskExtrudeParameters::None);
|
| |
|
| | return TaskDlgSketchBasedParameters::reject();
|
| | }
|
| |
|
| | #include "moc_TaskExtrudeParameters.cpp"
|
| |
|