void CmdPartDesignDuplicateSelection::activated(int iMsg) { Q_UNUSED(iMsg); PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false); std::vector<App::DocumentObject*> beforeFeatures = getDocument()->getObjects(); openCommand("Duplicate a PartDesign object"); doCommand(Doc,"FreeCADGui.runCommand('Std_DuplicateSelection')"); if (pcActiveBody) { // Find the features that were added std::vector<App::DocumentObject*> afterFeatures = getDocument()->getObjects(); std::vector<App::DocumentObject*> newFeatures; std::sort(beforeFeatures.begin(), beforeFeatures.end()); std::sort(afterFeatures.begin(), afterFeatures.end()); std::set_difference(afterFeatures.begin(), afterFeatures.end(), beforeFeatures.begin(), beforeFeatures.end(), std::back_inserter(newFeatures)); for (auto feature : newFeatures) { if (PartDesign::Body::isAllowed(feature)) { doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)", pcActiveBody->getNameInDocument(), feature->getNameInDocument()); doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", feature->getNameInDocument()); } } // Adjust visibility of features doCommand(Gui,"Gui.activeDocument().show(\"%s\")", newFeatures.back()->getNameInDocument()); } updateActive(); }
void TaskTransformedParameters::fillPlanesCombo(ComboLinks &combolinks, Part::Part2DObject* sketch) { combolinks.clear(); //add sketch axes if (sketch){ combolinks.addLink(sketch,"V_Axis",QObject::tr("Vertical sketch axis")); combolinks.addLink(sketch,"H_Axis",QObject::tr("Horizontal sketch axis")); for (int i=0; i < sketch->getAxisCount(); i++) { QString itemText = tr("Construction line %1").arg(i+1); std::stringstream sub; sub << "Axis" << i; combolinks.addLink(sketch,sub.str(),itemText); } } //add part baseplanes App::DocumentObject* obj = getObject(); PartDesign::Body * body = PartDesign::Body::findBodyOf ( obj ); if (body) { try { App::Origin* orig = body->getOrigin(); combolinks.addLink(orig->getXY(),"",tr("Base XY plane")); combolinks.addLink(orig->getYZ(),"",tr("Base YZ plane")); combolinks.addLink(orig->getXZ(),"",tr("Base XZ plane")); } catch (const Base::Exception &ex) { Base::Console().Error ("%s\n", ex.what() ); } } //add "Select reference" combolinks.addLink(0,std::string(),tr("Select reference...")); }
SbBox3f ViewProviderDatum::getRelevantBoundBox () const { std::vector<App::DocumentObject *> objs; // Probe body first PartDesign::Body* body = PartDesign::Body::findBodyOf ( this->getObject() ); if (body) { objs = body->getFullModel (); } else { // Probe if we belongs to some group App::DocumentObjectGroup* group = App::DocumentObjectGroup::getGroupOfObject ( this->getObject () ); if(group) { objs = group->getObjects (); } else { // Fallback to whole document objs = this->getObject ()->getDocument ()->getObjects (); } } Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(this->getActiveView())->getViewer(); SoGetBoundingBoxAction bboxAction(viewer->getSoRenderManager()->getViewportRegion()); SbBox3f bbox = getRelevantBoundBox (bboxAction, objs); if ( bbox.getVolume () < Precision::Confusion() ) { bbox.extendBy ( defaultBoundBox () ); } return bbox; }
void getReferencedSelection(const App::DocumentObject* thisObj, const Gui::SelectionChanges& msg, App::DocumentObject*& selObj, std::vector<std::string>& selSub) { if (!thisObj) return; if (strcmp(thisObj->getDocument()->getName(), msg.pDocName) != 0) return; selObj = thisObj->getDocument()->getObject(msg.pObjectName); if (selObj == thisObj) return; std::string subname = msg.pSubName; //check if the selection is an external reference and ask the user what to do //of course only if thisObj is in a body, as otherwise the old workflow would not //be supportet PartDesign::Body* body = PartDesignGui::getBodyFor(thisObj, false); bool originfeature = selObj->isDerivedFrom(App::OriginFeature::getClassTypeId()); if(!originfeature && body) { PartDesign::Body* selBody = PartDesignGui::getBodyFor(selObj, false); if(!selBody || body != selBody) { auto* pcActivePart = PartDesignGui::getPartFor(body, false); QDialog* dia = new QDialog; Ui_Dialog dlg; dlg.setupUi(dia); dia->setModal(true); int result = dia->exec(); if(result == QDialog::DialogCode::Rejected) { selObj = NULL; return; } else if(!dlg.radioXRef->isChecked()) { auto copy = PartDesignGui::TaskFeaturePick::makeCopy(selObj, subname, dlg.radioIndependent->isChecked()); if(selBody) body->addObject(copy); else pcActivePart->addObject(copy); selObj = copy; subname.erase(std::remove_if(subname.begin(), subname.end(), &isdigit), subname.end()); subname.append("1"); } } } // Remove subname for planes and datum features if (PartDesign::Feature::isDatum(selObj)) { subname = ""; } selSub = std::vector<std::string>(1,subname); }
void ViewProviderBody::slotChangedObjectApp ( const App::DocumentObject& obj, const App::Property& prop ) { if (!obj.isDerivedFrom ( Part::Feature::getClassTypeId () ) || obj.isDerivedFrom ( Part::BodyBase::getClassTypeId () ) ) { // we are intrested only in Part::Features and not in bodies return; } const Part::Feature *feat = static_cast <const Part::Feature *>(&obj); if ( &feat->Shape != &prop && &feat->Placement != &prop) { // react only on changes in shapes and placement return; } PartDesign::Body *body = static_cast<PartDesign::Body*> ( getObject() ); if ( body && body->hasFeature (&obj ) ) { updateOriginDatumSize (); } }
void TaskDatumParameters::resetViewMode() { //end temporary view mode of coordinate system PartDesign::Body * body = PartDesign::Body::findBodyOf(DatumView->getObject()); if (body) { try { App::Origin *origin = body->getOrigin(); ViewProviderOrigin* vpOrigin; vpOrigin = static_cast<ViewProviderOrigin*>(Gui::Application::Instance->getViewProvider(origin)); vpOrigin->resetTemporaryVisibility(); } catch (const Base::Exception &ex) { Base::Console().Error("%s\n", ex.what()); } } DatumView->setPickable(true); }
const QByteArray TaskSketchBasedParameters::onFaceName(const QString& text) { if (text.length() == 0) return QByteArray(); QStringList parts = text.split(QChar::fromLatin1(':')); if (parts.length() < 2) parts.push_back(QString::fromLatin1("")); // Check whether this is the name of an App::Plane or Part::Datum feature App::DocumentObject* obj = vp->getObject()->getDocument()->getObject(parts[0].toLatin1()); if (obj == NULL) return QByteArray(); PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY); if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) { // everything is OK (we assume a Part can only have exactly 3 App::Plane objects located at the base of the feature tree) return QByteArray(); } else if (obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) { if (!activeBody->hasFeature(obj)) return QByteArray(); return QByteArray(); } else { // We must expect that "text" is the translation of "Face" followed by an ID. QString name; QTextStream str(&name); str << "^" << tr("Face") << "(\\d+)$"; QRegExp rx(name); if (text.indexOf(rx) < 0) { return QByteArray(); } int faceId = rx.cap(1).toInt(); std::stringstream ss; ss << "Face" << faceId; std::vector<std::string> upToFaces(1,ss.str()); PartDesign::ProfileBased* pcSketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject()); pcSketchBased->UpToFace.setValue(obj, upToFaces); recomputeFeature(); return QByteArray(ss.str().c_str()); } }
TaskRevolutionParameters::~TaskRevolutionParameters() { //hide the parts coordinate system axis for selection PartDesign::Body * body = PartDesign::Body::findBodyOf ( vp->getObject() ); if ( body ) { try { App::Origin *origin = body->getOrigin(); ViewProviderOrigin* vpOrigin; vpOrigin = static_cast<ViewProviderOrigin*>(Gui::Application::Instance->getViewProvider(origin)); vpOrigin->resetTemporaryVisibility(); } catch (const Base::Exception &ex) { Base::Console().Error ("%s\n", ex.what () ); } } delete ui; for(size_t i = 0 ; i < axesInList.size() ; i++ ){ delete axesInList[i]; } }
void ViewProviderBody::slotChangedObjectGui ( const Gui::ViewProviderDocumentObject& vp, const App::Property& prop ) { if (&vp.Visibility != &prop) { // react only on visability changes return; } if ( !vp.isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) && !vp.isDerivedFrom ( Gui::ViewProviderOriginFeature::getClassTypeId () ) ) { // Ignore origins to avoid infinite recursion (not likely in a well-formed document, // but may happen in documents designed in old versions of assembly branch ) return; } PartDesign::Body *body = static_cast<PartDesign::Body*> ( getObject() ); App::DocumentObject *obj = vp.getObject (); if ( body && obj && body->hasFeature ( obj ) ) { updateOriginDatumSize (); } }
void CmdPartDesignMoveFeature::activated(int iMsg) { Q_UNUSED(iMsg); std::vector<App::DocumentObject*> features = getSelection().getObjectsOfType(Part::Feature::getClassTypeId()); if (features.empty()) return; // Check if all features are valid to move if (std::any_of(std::begin(features), std::end(features), [](App::DocumentObject* obj){return !PartDesignGui::isFeatureMovable(obj); })) { //show messagebox and cancel QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Features cannot be moved"), QObject::tr("Some of the selected features have dependencies in the source body")); return; } // Collect dependenies of the selected features std::vector<App::DocumentObject*> dependencies = PartDesignGui::collectMovableDependencies(features); if (!dependencies.empty()) features.insert(std::end(features), std::begin(dependencies), std::end(dependencies)); // Create a list of all bodies in this part std::vector<App::DocumentObject*> bodies = getDocument()->getObjectsOfType(Part::BodyBase::getClassTypeId()); std::set<App::DocumentObject*> source_bodies; for (auto feat : features) { PartDesign::Body* source = PartDesign::Body::findBodyOf(feat); source_bodies.insert(static_cast<App::DocumentObject*>(source)); } std::vector<App::DocumentObject*> target_bodies; for (auto body : bodies) { if (!source_bodies.count(body)) target_bodies.push_back(body); } if (target_bodies.empty()) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Features cannot be moved"), QObject::tr("There are no other bodies to move to")); return; } // Ask user to select the target body (remove source bodies from list) bool ok; QStringList items; for (auto body : target_bodies) { items.push_back(QString::fromUtf8(body->Label.getValue())); } QString text = QInputDialog::getItem(Gui::getMainWindow(), qApp->translate("PartDesign_MoveFeature", "Select body"), qApp->translate("PartDesign_MoveFeature", "Select a body from the list"), items, 0, false, &ok); if (!ok) return; int index = items.indexOf(text); if (index < 0) return; PartDesign::Body* target = static_cast<PartDesign::Body*>(target_bodies[index]); openCommand("Move an object"); for (auto feat: features) { // Find body of this feature Part::BodyBase* source = PartDesign::Body::findBodyOf(feat); bool featureWasTip = false; if (source == target) continue; // Remove from the source body if the feature belonged to a body if (source) { featureWasTip = (source->Tip.getValue() == feat); doCommand(Doc,"App.activeDocument().%s.removeObject(App.activeDocument().%s)", source->getNameInDocument(), (feat)->getNameInDocument()); } App::DocumentObject* targetOldTip = target->Tip.getValue(); // Add to target body (always at the Tip) doCommand(Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)", target->getNameInDocument(), (feat)->getNameInDocument()); // Recompute to update the shape doCommand(Gui,"App.activeDocument().recompute()"); // Adjust visibility of features // TODO: May be something can be done in view provider (2015-08-05, Fat-Zer) // If we removed the tip of the source body, make the new tip visible if ( featureWasTip ) { App::DocumentObject * sourceNewTip = source->Tip.getValue(); if (sourceNewTip) doCommand(Gui,"Gui.activeDocument().show(\"%s\")", sourceNewTip->getNameInDocument()); } // Hide old tip and show new tip (the moved feature) of the target body App::DocumentObject* targetNewTip = target->Tip.getValue(); if ( targetOldTip != targetNewTip ) { if ( targetOldTip ) { doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", targetOldTip->getNameInDocument()); } if (targetNewTip) { doCommand(Gui,"Gui.activeDocument().show(\"%s\")", targetNewTip->getNameInDocument()); } } // Fix sketch support if (feat->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) { Sketcher::SketchObject *sketch = static_cast<Sketcher::SketchObject*>(feat); try { PartDesignGui::fixSketchSupport(sketch); } catch (Base::Exception &) { QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Sketch plane cannot be migrated"), QObject::tr("Please edit '%1' and redefine it to use a Base or Datum plane as the sketch plane."). arg( QString::fromLatin1( sketch->Label.getValue () ) ) ); } } //relink origin for sketches and datums (coordinates) PartDesignGui::relinkToOrigin(feat, target); } updateActive(); }
TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* RevolutionView, QWidget *parent) : TaskSketchBasedParameters(RevolutionView, parent, "PartDesign_Revolution",tr("Revolution parameters")) { // we need a separate container widget to add all controls to proxy = new QWidget(this); ui = new Ui_TaskRevolutionParameters(); ui->setupUi(proxy); QMetaObject::connectSlotsByName(this); connect(ui->revolveAngle, SIGNAL(valueChanged(double)), this, SLOT(onAngleChanged(double))); connect(ui->axis, SIGNAL(activated(int)), this, SLOT(onAxisChanged(int))); connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), this, SLOT(onMidplane(bool))); connect(ui->checkBoxReversed, SIGNAL(toggled(bool)), this, SLOT(onReversed(bool))); connect(ui->checkBoxUpdateView, SIGNAL(toggled(bool)), this, SLOT(onUpdateView(bool))); this->groupLayout()->addWidget(proxy); // Temporarily prevent unnecessary feature recomputes ui->revolveAngle->blockSignals(true); ui->axis->blockSignals(true); ui->checkBoxMidplane->blockSignals(true); ui->checkBoxReversed->blockSignals(true); //bind property mirrors PartDesign::ProfileBased* pcFeat = static_cast<PartDesign::ProfileBased*>(vp->getObject()); if (pcFeat->isDerivedFrom(PartDesign::Revolution::getClassTypeId())) { PartDesign::Revolution* rev = static_cast<PartDesign::Revolution*>(vp->getObject()); this->propAngle = &(rev->Angle); this->propMidPlane = &(rev->Midplane); this->propReferenceAxis = &(rev->ReferenceAxis); this->propReversed = &(rev->Reversed); } else { assert(pcFeat->isDerivedFrom(PartDesign::Groove::getClassTypeId())); PartDesign::Groove* rev = static_cast<PartDesign::Groove*>(vp->getObject()); this->propAngle = &(rev->Angle); this->propMidPlane = &(rev->Midplane); this->propReferenceAxis = &(rev->ReferenceAxis); this->propReversed = &(rev->Reversed); } double l = propAngle->getValue(); bool mirrored = propMidPlane->getValue(); bool reversed = propReversed->getValue(); ui->revolveAngle->setValue(l); blockUpdate = false; updateUI(); ui->checkBoxMidplane->setChecked(mirrored); ui->checkBoxReversed->setChecked(reversed); PartDesign::ProfileBased* sketchBased = static_cast<PartDesign::ProfileBased*>(vp->getObject()); // TODO This is quite ugly better redo it (2015-11-02, Fat-Zer) if ( sketchBased->isDerivedFrom(PartDesign::Revolution::getClassTypeId() ) ) { ui->revolveAngle->bind(static_cast<PartDesign::Revolution *> ( sketchBased )->Angle); } else if ( sketchBased->isDerivedFrom(PartDesign::Groove::getClassTypeId() ) ) { ui->revolveAngle->bind(static_cast<PartDesign::Groove *> ( sketchBased )->Angle); } ui->revolveAngle->blockSignals(false); ui->axis->blockSignals(false); ui->checkBoxMidplane->blockSignals(false); ui->checkBoxReversed->blockSignals(false); setFocus (); //show the parts coordinate system axis for selection PartDesign::Body * body = PartDesign::Body::findBodyOf ( vp->getObject () ); if(body) { try { App::Origin *origin = body->getOrigin(); ViewProviderOrigin* vpOrigin; vpOrigin = static_cast<ViewProviderOrigin*>(Gui::Application::Instance->getViewProvider(origin)); vpOrigin->setTemporaryVisibility(true, false); } catch (const Base::Exception &ex) { Base::Console().Error ("%s\n", ex.what () ); } } }
TaskDatumParameters::TaskDatumParameters(ViewProviderDatum *DatumView,QWidget *parent) : TaskBox(Gui::BitmapFactory().pixmap((QString::fromLatin1("PartDesign_") + DatumView->datumType).toLatin1()), DatumView->datumType + tr(" parameters"), true, parent), DatumView(DatumView) { // we need a separate container widget to add all controls to proxy = new QWidget(this); ui = new Ui_TaskDatumParameters(); ui->setupUi(proxy); QMetaObject::connectSlotsByName(this); connect(ui->superplacementX, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementXChanged(double))); connect(ui->superplacementY, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementYChanged(double))); connect(ui->superplacementZ, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementZChanged(double))); connect(ui->superplacementYaw, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementYawChanged(double))); connect(ui->superplacementPitch, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementPitchChanged(double))); connect(ui->superplacementRoll, SIGNAL(valueChanged(double)), this, SLOT(onSuperplacementRollChanged(double))); connect(ui->checkBoxFlip, SIGNAL(toggled(bool)), this, SLOT(onCheckFlip(bool))); connect(ui->buttonRef1, SIGNAL(clicked(bool)), this, SLOT(onButtonRef1(bool))); connect(ui->lineRef1, SIGNAL(textEdited(QString)), this, SLOT(onRefName1(QString))); connect(ui->buttonRef2, SIGNAL(clicked(bool)), this, SLOT(onButtonRef2(bool))); connect(ui->lineRef2, SIGNAL(textEdited(QString)), this, SLOT(onRefName2(QString))); connect(ui->buttonRef3, SIGNAL(clicked(bool)), this, SLOT(onButtonRef3(bool))); connect(ui->lineRef3, SIGNAL(textEdited(QString)), this, SLOT(onRefName3(QString))); connect(ui->buttonRef4, SIGNAL(clicked(bool)), this, SLOT(onButtonRef4(bool))); connect(ui->lineRef4, SIGNAL(textEdited(QString)), this, SLOT(onRefName4(QString))); connect(ui->listOfModes,SIGNAL(itemSelectionChanged()), this, SLOT(onModeSelect())); this->groupLayout()->addWidget(proxy); // Temporarily prevent unnecessary feature recomputes ui->checkBoxFlip->blockSignals(true); ui->buttonRef1->blockSignals(true); ui->lineRef1->blockSignals(true); ui->buttonRef2->blockSignals(true); ui->lineRef2->blockSignals(true); ui->buttonRef3->blockSignals(true); ui->lineRef3->blockSignals(true); ui->buttonRef4->blockSignals(true); ui->lineRef4->blockSignals(true); ui->listOfModes->blockSignals(true); // Get the feature data Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject()); //std::vector<App::DocumentObject*> refs = pcDatum->Support.getValues(); std::vector<std::string> refnames = pcDatum->Support.getSubValues(); ui->checkBoxFlip->setChecked(pcDatum->MapReversed.getValue()); std::vector<QString> refstrings; makeRefStrings(refstrings, refnames); ui->lineRef1->setText(refstrings[0]); ui->lineRef1->setProperty("RefName", QByteArray(refnames[0].c_str())); ui->lineRef2->setText(refstrings[1]); ui->lineRef2->setProperty("RefName", QByteArray(refnames[1].c_str())); ui->lineRef3->setText(refstrings[2]); ui->lineRef3->setProperty("RefName", QByteArray(refnames[2].c_str())); ui->lineRef4->setText(refstrings[3]); ui->lineRef4->setProperty("RefName", QByteArray(refnames[3].c_str())); // activate and de-activate dialog elements as appropriate ui->checkBoxFlip->blockSignals(false); ui->buttonRef1->blockSignals(false); ui->lineRef1->blockSignals(false); ui->buttonRef2->blockSignals(false); ui->lineRef2->blockSignals(false); ui->buttonRef3->blockSignals(false); ui->lineRef3->blockSignals(false); ui->buttonRef4->blockSignals(false); ui->lineRef4->blockSignals(false); ui->listOfModes->blockSignals(false); this->iActiveRef = 0; if (pcDatum->Support.getSize() == 0){ autoNext = true; } else { autoNext = false; } ui->superplacementX->bind(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Base.x"))); ui->superplacementY->bind(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Base.y"))); ui->superplacementZ->bind(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Base.z"))); visibilityAutomation(true); updateSuperplacementUI(); updateReferencesUI(); updateListOfModes(eMapMode(pcDatum->MapMode.getValue())); updatePreview(); //temporary show coordinate systems for selection PartDesign::Body * body = PartDesign::Body::findBodyOf(DatumView->getObject()); if (body) { try { App::Origin *origin = body->getOrigin(); ViewProviderOrigin* vpOrigin; vpOrigin = static_cast<ViewProviderOrigin*>(Gui::Application::Instance->getViewProvider(origin)); vpOrigin->setTemporaryVisibility(true, true); } catch (const Base::Exception &ex) { Base::Console().Error ("%s\n", ex.what () ); } } DatumView->setPickable(false); Gui::Selection().addSelectionGate(new NoDependentsSelection(DatumView->getObject(), true, true, true, true)); // connect object deletion with slot auto bnd = boost::bind(&TaskDatumParameters::objectDeleted, this, _1); Gui::Document* document = Gui::Application::Instance->getDocument(DatumView->getObject()->getDocument()); connectDelObject = document->signalDeletedObject.connect(bnd); }
void ViewProviderBody::updateOriginDatumSize () { PartDesign::Body *body = static_cast<PartDesign::Body *> ( getObject() ); // Use different bounding boxes for datums and for origins: Gui::Document* gdoc = Gui::Application::Instance->getDocument(getObject()->getDocument()); if(!gdoc) return; Gui::MDIView* view = gdoc->getViewOfViewProvider(this); if(!view) return; Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer(); SoGetBoundingBoxAction bboxAction(viewer->getSoRenderManager()->getViewportRegion()); const auto & model = body->getFullModel (); // BBox for Datums is calculated from all visible objects but treating datums as their basepoints only SbBox3f bboxDatums = ViewProviderDatum::getRelevantBoundBox ( bboxAction, model ); // BBox for origin should take into account datums size also SbBox3f bboxOrigins = bboxDatums; for(App::DocumentObject* obj : model) { if ( obj->isDerivedFrom ( Part::Datum::getClassTypeId () ) ) { ViewProvider *vp = Gui::Application::Instance->getViewProvider(obj); if (!vp) { continue; } ViewProviderDatum *vpDatum = static_cast <ViewProviderDatum *> (vp) ; vpDatum->setExtents ( bboxDatums ); bboxAction.apply ( vp->getRoot () ); bboxOrigins.extendBy ( bboxAction.getBoundingBox () ); } } // get the bounding box values SbVec3f max = bboxOrigins.getMax(); SbVec3f min = bboxOrigins.getMin(); // obtain an Origin and it's ViewProvider App::Origin* origin = 0; Gui::ViewProviderOrigin* vpOrigin = 0; try { origin = body->getOrigin (); assert (origin); Gui::ViewProvider *vp = Gui::Application::Instance->getViewProvider(origin); if (!vp) { throw Base::Exception ("No view provider linked to the Origin"); } assert ( vp->isDerivedFrom ( Gui::ViewProviderOrigin::getClassTypeId () ) ); vpOrigin = static_cast <Gui::ViewProviderOrigin *> ( vp ); } catch (const Base::Exception &ex) { Base::Console().Error ("%s\n", ex.what() ); return; } // calculate the desired origin size Base::Vector3d size; for (uint_fast8_t i=0; i<3; i++) { size[i] = std::max ( fabs ( max[i] ), fabs ( min[i] ) ); if (size[i] < Precision::Confusion() ) { size[i] = Gui::ViewProviderOrigin::defaultSize(); } } vpOrigin->Size.setValue ( size*1.2 ); }
void Workbench::setupContextMenu(const char* recipient, Gui::MenuItem* item) const { auto selection = Gui::Selection().getSelection(); // Add move Tip Command if ( selection.size () >= 1 ) { App::DocumentObject *feature = selection.front().pObject; PartDesign::Body *body = PartDesignGui::getBodyFor ( feature, false ); // lote of assertion so feature sould be marked as a tip if ( selection.size () == 1 && feature && ( feature->isDerivedFrom ( PartDesign::Body::getClassTypeId () ) || ( feature->isDerivedFrom ( PartDesign::Feature::getClassTypeId () ) && body ) || ( feature->isDerivedFrom ( Part::Feature::getClassTypeId () ) && body && body->BaseFeature.getValue() == feature ) ) ) { *item << "PartDesign_MoveTip"; } if (strcmp(recipient, "Tree") == 0) { Gui::MDIView *activeView = Gui::Application::Instance->activeView(); if ( selection.size () > 0 && activeView ) { bool docHaveBodies = activeView->getAppDocument()->countObjectsOfType ( PartDesign::Body::getClassTypeId () ) > 0; if ( docHaveBodies ) { bool addMoveFeature = true; bool addMoveFeatureInTree = (body != nullptr); for (auto sel: selection) { // if at least one selected feature cannot be moved to a body // disable the entry if ( addMoveFeature && !PartDesign::Body::isAllowed ( sel.pObject ) ) { addMoveFeature = false; } // if all at lest one selected feature doesn't belongs to the same body // disable the menu entry if ( addMoveFeatureInTree && !body->hasFeature ( sel.pObject ) ) { addMoveFeatureInTree = false; } if ( !addMoveFeatureInTree && !addMoveFeature ) { break; } } if (addMoveFeature) { *item << "PartDesign_MoveFeature"; } if (addMoveFeatureInTree) { *item << "PartDesign_MoveFeatureInTree"; } } } if (Gui::Selection().countObjectsOfType(PartDesign::Transformed::getClassTypeId()) - Gui::Selection().countObjectsOfType(PartDesign::MultiTransform::getClassTypeId()) == 1 ) *item << "PartDesign_MultiTransform"; } } }
void CmdPartDesignMoveFeatureInTree::activated(int iMsg) { Q_UNUSED(iMsg); std::vector<App::DocumentObject*> features = getSelection().getObjectsOfType(Part::Feature::getClassTypeId()); if (features.empty()) return; PartDesign::Body *body = PartDesignGui::getBodyFor ( features.front(), false ); App::DocumentObject * bodyBase = nullptr; // sanity check bool allFeaturesFromSameBody = true; if ( body ) { bodyBase= body->BaseFeature.getValue(); for ( auto feat: features ) { if ( !body->hasObject ( feat ) ) { allFeaturesFromSameBody = false; break; } if ( bodyBase== feat) { QMessageBox::warning (0, QObject::tr( "Selection error" ), QObject::tr( "Impossible to move the base feature of a body." ) ); return; } } } if (!body || ! allFeaturesFromSameBody) { QMessageBox::warning (0, QObject::tr( "Selection error" ), QObject::tr( "Select one or more features from the same body." ) ); return; } // Create a list of all features in this body const std::vector<App::DocumentObject*> & model = body->Group.getValues(); // Ask user to select the target feature bool ok; QStringList items; if ( bodyBase ) { items.push_back( QString::fromUtf8 ( bodyBase->Label.getValue () ) ); } else { items.push_back( QObject::tr( "Beginning of the body" ) ); } for ( auto feat: model ) { items.push_back( QString::fromUtf8 ( feat->Label.getValue() ) ); } QString text = QInputDialog::getItem(Gui::getMainWindow(), qApp->translate("PartDesign_MoveFeatureInTree", "Select feature"), qApp->translate("PartDesign_MoveFeatureInTree", "Select a feature from the list"), items, 0, false, &ok); if (!ok) return; int index = items.indexOf(text); // first object is the beginning of the body App::DocumentObject* target = index != 0 ? model[index-1] : nullptr; openCommand("Move an object inside tree"); for ( auto feat: features ) { if ( feat == target ) continue; std::string targetStr; if (target) { targetStr.append("App.activeDocument().").append(target->getNameInDocument()); } else { targetStr = "None"; } // Remove and re-insert the feature to/from the Body // TODO if tip was moved the new position of tip is quite undetermined (2015-08-07, Fat-Zer) // TODO warn the user if we are moving an object to some place before the object's link (2015-08-07, Fat-Zer) doCommand ( Doc,"App.activeDocument().%s.removeObject(App.activeDocument().%s)", body->getNameInDocument(), feat->getNameInDocument() ); doCommand ( Doc, "App.activeDocument().%s.insertObject(App.activeDocument().%s, %s, True)", body->getNameInDocument(), feat->getNameInDocument(), targetStr.c_str () ); } updateActive(); }
bool ReferenceSelection::allow(App::Document* pDoc, App::DocumentObject* pObj, const char* sSubName) { // TODO review this function (2015-09-04, Fat-Zer) PartDesign::Body *body; App::GeoFeatureGroup *geoGroup; if ( support ) { body = PartDesign::Body::findBodyOf (support); } else { body = PartDesignGui::getBody (false); } if ( body ) { // Search for Part of the body geoGroup = App::GeoFeatureGroup::getGroupOfObject ( body ) ; } else if ( support ) { // if no body search part for support geoGroup = App::GeoFeatureGroup::getGroupOfObject ( support ) ; } else { // fallback to active part geoGroup = PartDesignGui::getActivePart ( ); } // Don't allow selection in other document if ( support && pDoc != support->getDocument() ) { return false; } // Enable selection from origin of current part/ if ( pObj->getTypeId().isDerivedFrom(App::OriginFeature::getClassTypeId()) ) { bool fits = false; if ( plane && pObj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ) { fits = true; } else if ( edge && pObj->getTypeId().isDerivedFrom(App::Line::getClassTypeId()) ) { fits = true; } if (fits) { // check that it is actually belongs to the choosen body or part try { // here are some throwers if (body) { if (body->getOrigin ()->hasObject (pObj) ) { return true; } } else if (geoGroup && geoGroup->isDerivedFrom ( App::OriginGroup::getClassTypeId () ) ) { if ( static_cast<App::OriginGroup *>(geoGroup)->getOrigin ()->hasObject (pObj) ) { return true; } } } catch (const Base::Exception) { } } return false; // The Plane/Axis doesn't fits our needs } if (pObj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId())) { if (!body) { // Allow selecting Part::Datum features from the active Body return false; } else if (!allowOtherBody && !body->hasFeature(pObj)) { return false; } if (plane && (pObj->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId()))) return true; if (edge && (pObj->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId()))) return true; if (point && (pObj->getTypeId().isDerivedFrom(PartDesign::Point::getClassTypeId()))) return true; return false; } // Handle selection of geometry elements if (!sSubName || sSubName[0] == '\0') return false; if (!allowOtherBody) { if (support == NULL) return false; if (pObj != support) return false; } std::string subName(sSubName); if (edge && subName.size() > 4 && subName.substr(0,4) == "Edge") { const Part::TopoShape &shape = static_cast<const Part::Feature*>(pObj)->Shape.getValue(); TopoDS_Shape sh = shape.getSubShape(subName.c_str()); const TopoDS_Edge& edge = TopoDS::Edge(sh); if (!edge.IsNull()) { if (planar) { BRepAdaptor_Curve adapt(edge); if (adapt.GetType() == GeomAbs_Line) return true; } else { return true; } } } if (plane && subName.size() > 4 && subName.substr(0,4) == "Face") { const Part::TopoShape &shape = static_cast<const Part::Feature*>(pObj)->Shape.getValue(); TopoDS_Shape sh = shape.getSubShape(subName.c_str()); const TopoDS_Face& face = TopoDS::Face(sh); if (!face.IsNull()) { if (planar) { BRepAdaptor_Surface adapt(face); if (adapt.GetType() == GeomAbs_Plane) return true; } else { return true; } } } if (point && subName.size() > 6 && subName.substr(0,6) == "Vertex") { return true; } return false; }
void TaskRevolutionParameters::fillAxisCombo(bool forceRefill) { // TODO share the code with TaskTransformedParameters (2015-08-31, Fat-Zer) bool oldVal_blockUpdate = blockUpdate; blockUpdate = true; if(axesInList.size() == 0) forceRefill = true;//not filled yet, full refill if (forceRefill){ ui->axis->clear(); for(size_t i = 0 ; i < axesInList.size() ; i++ ){ delete axesInList[i]; } this->axesInList.clear(); //add sketch axes PartDesign::ProfileBased* pcFeat = static_cast<PartDesign::Revolution*>(vp->getObject()); Part::Part2DObject* pcSketch = static_cast<Part::Part2DObject*>(pcFeat->Profile.getValue()); if (pcSketch){ addAxisToCombo(pcSketch,"V_Axis",QObject::tr("Vertical sketch axis")); addAxisToCombo(pcSketch,"H_Axis",QObject::tr("Horizontal sketch axis")); for (int i=0; i < pcSketch->getAxisCount(); i++) { QString itemText = QObject::tr("Construction line %1").arg(i+1); std::stringstream sub; sub << "Axis" << i; addAxisToCombo(pcSketch,sub.str(),itemText); } } //add part axes App::DocumentObject* obj = vp->getObject(); PartDesign::Body * body = PartDesign::Body::findBodyOf ( obj ); if (body) { try { App::Origin* orig = body->getOrigin(); addAxisToCombo(orig->getX(),"",tr("Base X axis")); addAxisToCombo(orig->getY(),"",tr("Base Y axis")); addAxisToCombo(orig->getZ(),"",tr("Base Z axis")); } catch (const Base::Exception &ex) { Base::Console().Error ("%s\n", ex.what() ); } } //add "Select reference" addAxisToCombo(0,std::string(),tr("Select reference...")); }//endif forceRefill //add current link, if not in list //first, figure out the item number for current axis 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; } if ( indexOfCurrent == -1 && ax ){ assert(subList.size() <= 1); std::string sub; if (subList.size()>0) sub = subList[0]; addAxisToCombo(ax, sub, getRefStr(ax, subList)); indexOfCurrent = axesInList.size()-1; } //highlight current. if (indexOfCurrent != -1) ui->axis->setCurrentIndex(indexOfCurrent); blockUpdate = oldVal_blockUpdate; }