From 16e4ce20f0333b7a84f62d73014b0124b6f00f8a Mon Sep 17 00:00:00 2001 From: DeepSOIC Date: Mon, 20 Jul 2015 17:43:48 +0300 Subject: [PATCH] PartDesign workflow without part/body PartDesign: make datum features work outside of body/part PartDesign old workflow: remove a few messageboxes about no part PartDesign: old workflow: multitransform without body Still has visibility issues, but generally works. --- src/Mod/PartDesign/App/FeaturePad.cpp | 23 -------- src/Mod/PartDesign/Gui/Command.cpp | 55 ++++++++++--------- .../Gui/TaskSketchBasedParameters.cpp | 37 +++++++++---- .../Gui/TaskTransformedParameters.cpp | 2 +- src/Mod/PartDesign/Gui/ViewProviderDatum.cpp | 37 +++++++++++++ src/Mod/PartDesign/Gui/ViewProviderDatum.h | 14 +++++ .../PartDesign/Gui/ViewProviderDatumLine.cpp | 8 +-- .../PartDesign/Gui/ViewProviderDatumPlane.cpp | 6 +- 8 files changed, 112 insertions(+), 70 deletions(-) diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index 74fde500d..4a2d4adb2 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -110,29 +110,6 @@ App::DocumentObjectExecReturn *Pad::execute(void) base = TopoDS_Shape(); } -/* - // Find Body feature which owns this Pad and get the shape of the feature preceding this one for fusing - // This method was rejected in favour of the BaseFeature property because that makes the feature atomic (independent of the - // Body object). See - // https://sourceforge.net/apps/phpbb/free-cad/viewtopic.php?f=19&t=3831 - // https://sourceforge.net/apps/phpbb/free-cad/viewtopic.php?f=19&t=3855 - PartDesign::Body* body = getBody(); - if (body == NULL) { - return new App::DocumentObjectExecReturn( - "In order to use PartDesign you need an active Body object in the document. " - "Please make one active or create one. If you have a legacy document " - "with PartDesign objects without Body, use the transfer function in " - "PartDesign to put them into a Body." - ); - } - const Part::TopoShape& prevShape = body->getPreviousSolid(this); - TopoDS_Shape support; - if (prevShape.isNull()) - // ignore, because support isn't mandatory - support = TopoDS_Shape(); - else - support = prevShape._Shape; -*/ // get the Sketch plane Base::Placement SketchPos = sketch->Placement.getValue(); diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 4bf41fb8f..417bf80bc 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -522,9 +522,7 @@ void UnifiedDatumCommand(Gui::Command &cmd, Base::Type type, std::string name) cmd.openCommand(tmp.c_str()); cmd.doCommand(Gui::Command::Gui,"Gui.activeDocument().setEdit('%s')",support.getValue()->getNameInDocument()); } else { - PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true); - if (pcActiveBody == 0) - return; + PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false); std::string FeatName = cmd.getUniqueObjectName(name.c_str()); @@ -547,8 +545,10 @@ void UnifiedDatumCommand(Gui::Command &cmd, Base::Type type, std::string name) QMessageBox::information(Gui::getMainWindow(),QObject::tr("Invalid selection"), QObject::tr("There are no attachment modes that fit seleted objects. Select something else.")); } } - cmd.doCommand(Gui::Command::Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", - pcActiveBody->getNameInDocument(), FeatName.c_str()); + if (pcActiveBody) { + cmd.doCommand(Gui::Command::Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", + pcActiveBody->getNameInDocument(), FeatName.c_str()); + } cmd.doCommand(Gui::Command::Doc,"App.activeDocument().recompute()"); // recompute the feature based on its references cmd.doCommand(Gui::Command::Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); } @@ -667,7 +667,11 @@ void CmdPartDesignNewSketch::activated(int iMsg) PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true); // No PartDesign feature without Body past FreeCAD 0.13 - if(!pcActiveBody) return; + if(!pcActiveBody) { + Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + rcCmdMgr.runCommandByName("Sketcher_NewSketch"); + return; + } Gui::SelectionFilter SketchFilter("SELECT Sketcher::SketchObject COUNT 1"); Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1"); @@ -893,10 +897,9 @@ bool CmdPartDesignNewSketch::isActive(void) void finishFeature(const Gui::Command* cmd, const std::string& FeatName, const bool hidePrevSolid = true) { PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false); - if (pcActiveBody == 0) - throw Base::Exception("No active body!"); - cmd->doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", + if (pcActiveBody) + cmd->doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", pcActiveBody->getNameInDocument(), FeatName.c_str()); if (pcActiveBody != NULL) { @@ -939,8 +942,8 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName, const b for (std::vector::iterator s = sketches.begin(); s != sketches.end(); s++) { // Check whether this plane belongs to the active body - if (!pcActiveBody->hasFeature(*s)) { - if(pcActivePart->hasObject(*s, true)) + if (pcActiveBody && !pcActiveBody->hasFeature(*s)) { + if(pcActivePart && pcActivePart->hasObject(*s, true)) status.push_back(PartDesignGui::TaskFeaturePick::otherBody); else status.push_back(PartDesignGui::TaskFeaturePick::otherPart); @@ -968,7 +971,7 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName, const b continue; } - if (pcActiveBody->isAfterTip(*s)){ + if (pcActiveBody && pcActiveBody->isAfterTip(*s)){ status.push_back(PartDesignGui::TaskFeaturePick::afterTip); continue; } @@ -1005,9 +1008,6 @@ void finishFeature(const Gui::Command* cmd, const std::string& FeatName, const b void prepareSketchBased(Gui::Command* cmd, const std::string& which, boost::function func) { - PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true); - if (!pcActiveBody) return; - bool bNoSketchWasSelected = false; // Get a valid sketch from the user // First check selections @@ -1050,8 +1050,6 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which, which.c_str(), FeatName.c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s", FeatName.c_str(), sketch->getNameInDocument()); - //Gui::Command::doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", - // pcActiveBody->getNameInDocument(), FeatName.c_str()); func(sketch, FeatName); }; @@ -2061,8 +2059,8 @@ CmdPartDesignMultiTransform::CmdPartDesignMultiTransform() void CmdPartDesignMultiTransform::activated(int iMsg) { - PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */true); - if (!pcActiveBody) return; + PartDesign::Body *pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false); + //if (!pcActiveBody) return; std::vector features; @@ -2082,8 +2080,12 @@ void CmdPartDesignMultiTransform::activated(int iMsg) PartDesign::Transformed* trFeat = static_cast(features.front()); // Move the insert point back one feature - App::DocumentObject* oldTip = pcActiveBody->Tip.getValue(); - App::DocumentObject* prevFeature = pcActiveBody->getPrevFeature(trFeat); + App::DocumentObject* oldTip = 0; + App::DocumentObject* prevFeature = 0; + if (pcActiveBody){ + oldTip = pcActiveBody->Tip.getValue(); + prevFeature = pcActiveBody->getPrevFeature(trFeat); + } Gui::Selection().clearSelection(); if (prevFeature != NULL) Gui::Selection().addSelection(prevFeature->getDocument()->getName(), prevFeature->getNameInDocument()); @@ -2091,8 +2093,9 @@ void CmdPartDesignMultiTransform::activated(int iMsg) doCommand(Gui, "FreeCADGui.runCommand('PartDesign_MoveTip')"); // Remove the Transformed feature from the Body - doCommand(Doc, "App.activeDocument().%s.removeFeature(App.activeDocument().%s)", - pcActiveBody->getNameInDocument(), trFeat->getNameInDocument()); + if(pcActiveBody) + doCommand(Doc, "App.activeDocument().%s.removeFeature(App.activeDocument().%s)", + pcActiveBody->getNameInDocument(), trFeat->getNameInDocument()); // Create a MultiTransform feature and move the Transformed feature inside it std::string FeatName = getUniqueObjectName("MultiTransform"); @@ -2105,7 +2108,7 @@ void CmdPartDesignMultiTransform::activated(int iMsg) finishFeature(this, FeatName); // Restore the insert point - if (oldTip != trFeat) { + if (pcActiveBody && oldTip != trFeat) { Gui::Selection().clearSelection(); Gui::Selection().addSelection(oldTip->getDocument()->getName(), oldTip->getNameInDocument()); Gui::Command::doCommand(Gui::Command::Gui,"FreeCADGui.runCommand('PartDesign_MoveTip')"); @@ -2120,7 +2123,9 @@ void CmdPartDesignMultiTransform::activated(int iMsg) return; // Make sure the user isn't presented with an empty screen because no transformations are defined yet... - App::DocumentObject* prevSolid = pcActiveBody->getPrevSolidFeature(NULL, true); + App::DocumentObject* prevSolid = 0; + if (pcActiveBody) + pcActiveBody->getPrevSolidFeature(NULL, true); if (prevSolid != NULL) { Part::Feature* feat = static_cast(prevSolid); doCommand(Doc,"App.activeDocument().%s.Shape = App.activeDocument().%s.Shape", diff --git a/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp b/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp index e50fa095c..5bd8e81cf 100644 --- a/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp @@ -94,15 +94,28 @@ const QString TaskSketchBasedParameters::onAddSelection(const Gui::SelectionChan void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool edge, const bool face, const bool planar) { // Note: Even if there is no solid, App::Plane and Part::Datum can still be selected - PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject(PDBODYKEY); - App::DocumentObject* prevSolid = activeBody->getPrevSolidFeature(vp->getObject(), false); - App::DocumentObject* curSolid = activeBody->getPrevSolidFeature(); + + PartDesign::SketchBased* pcSketchBased = static_cast(vp->getObject()); + PartDesign::Body* activeBody = Gui::Application::Instance->activeView()->getActiveObject(PDBODYKEY); + + App::DocumentObject* curSolid = 0;//the last solid of the body, the one that is likely visible, but can't be used for up-to-face + if (activeBody) + curSolid = activeBody->getPrevSolidFeature(); + else + curSolid = pcSketchBased; + + App::DocumentObject* prevSolid = 0;//the solid this feature will be fused to + try { + prevSolid = pcSketchBased->getBaseObject(); + } catch (Base::Exception) { + //this feature is a starting feature + } if (pressed) { Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (doc) { if (curSolid) - doc->setHide(curSolid->getNameInDocument()); + doc->setHide(curSolid->getNameInDocument()); if (prevSolid) doc->setShow(prevSolid->getNameInDocument()); } @@ -114,7 +127,7 @@ void TaskSketchBasedParameters::onSelectReference(const bool pressed, const bool Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (doc) { if (curSolid) - doc->setShow(curSolid->getNameInDocument()); + doc->setShow(curSolid->getNameInDocument()); if (prevSolid) doc->setHide(prevSolid->getNameInDocument()); } @@ -200,7 +213,7 @@ App::DocumentObject* TaskSketchBasedParameters::getPartPlanes(const char* str) c //TODO: Adjust to GRAPH handling when available App::DocumentObject* obj = vp->getObject(); - App::Part* part = getPartFor(obj, true); + App::Part* part = getPartFor(obj, false); if(!part) return nullptr; @@ -224,11 +237,15 @@ App::DocumentObject* TaskSketchBasedParameters::getPartLines(const char* str) co //TODO: Adjust to GRAPH handling when available App::DocumentObject* obj = vp->getObject(); - App::Part* part = getPartFor(obj, true); - if(!part) - return nullptr; + App::Part* part = getPartFor(obj, false); - std::vector origs = part->getObjectsOfType(App::Origin::getClassTypeId()); + + std::vector origs; + if(part) + origs = part->getObjectsOfType(App::Origin::getClassTypeId()); + else + origs = vp->getObject()->getDocument()->getObjectsOfType(App::Origin::getClassTypeId()); + if(origs.size()<1) return nullptr; diff --git a/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp b/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp index e6fc7851e..6045e5868 100644 --- a/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp @@ -182,7 +182,7 @@ App::DocumentObject* TaskTransformedParameters::getPartPlanes(const char* str) c //TODO: Adjust to GRAPH handling when available App::DocumentObject* obj = getObject(); - App::Part* part = getPartFor(obj, true); + App::Part* part = getPartFor(obj, false); if (part) { std::vector origs = part->getObjectsOfType(App::Origin::getClassTypeId()); diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp b/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp index 7648e031b..b7497a4e7 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp @@ -54,6 +54,7 @@ #include "ViewProviderDatum.h" #include "TaskDatumParameters.h" #include "Workbench.h" +#include #include #include #include @@ -314,3 +315,39 @@ void ViewProviderDatum::unsetEdit(int ModNum) } } +Base::BoundBox3d ViewProviderDatum::getRelevantExtents() +{ + Base::BoundBox3d bbox; + PartDesign::Body* body = static_cast(Part::BodyBase::findBodyOf(this->getObject())); + if (body != NULL) + bbox = body->getBoundBox(); + else { + App::Part* part = getPartFor(this->getObject(),false); + std::vector objs; + + if(part) + objs = part->getObjectsOfType(Part::Feature::getClassTypeId()); + else + objs = this->getObject()->getDocument()->getObjectsOfType(Part::Feature::getClassTypeId()); + + for(App::DocumentObject* obj: objs){ + Part::Feature* feat = static_cast(obj); + Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(feat); + if (vp->isVisible()){ + Base::BoundBox3d bbf = feat->Shape.getBoundingBox(); + if (bbf.CalcDiagonalLength() < Precision::Infinite()) + bbox.Add(bbf); + } + + } + if (bbox.CalcDiagonalLength() < Precision::Confusion()){ + bbox.Add(Base::Vector3d(-10.0,-10.0,-10.0)); + bbox.Add(Base::Vector3d(10.0,10.0,10.0)); + } + + } + bbox.Enlarge(0.1 * bbox.CalcDiagonalLength()); + return bbox; + +} + diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatum.h b/src/Mod/PartDesign/Gui/ViewProviderDatum.h index db4c48c9c..7b9c2fb15 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatum.h +++ b/src/Mod/PartDesign/Gui/ViewProviderDatum.h @@ -25,6 +25,7 @@ #define PARTGUI_ViewProviderDatum_H #include "Gui/ViewProviderGeometryObject.h" +#include namespace PartDesignGui { @@ -64,6 +65,19 @@ protected: virtual bool setEdit(int ModNum); virtual void unsetEdit(int ModNum); + + // + /** + * @brief getRelevantExtents computes the bounding box of the objects + * relevant to the datum feature, which is intended to be used for + * determinimg the size of the rendered piece of the datum. + * @return Bounding box of body, if the datum is in a body. Bounding box of + * all visible shapes of a part, if in a part but not in a body. Bounding + * box of all visible Part::Feature-derived objects if just in a document. + * This behavior is subject to change. + */ + virtual Base::BoundBox3d getRelevantExtents(); + protected: SoSeparator* pShapeSep; std::string oldWb; diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatumLine.cpp b/src/Mod/PartDesign/Gui/ViewProviderDatumLine.cpp index 9a4a5d9da..b7e3d4e55 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatumLine.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDatumLine.cpp @@ -47,7 +47,6 @@ #include #include #include -#include using namespace PartDesignGui; @@ -80,12 +79,9 @@ void ViewProviderDatumLine::updateData(const App::Property* prop) Base::Vector3d dir(0,0,1); // Get limits of the line from bounding box of the body - PartDesign::Body* body = static_cast(Part::BodyBase::findBodyOf(this->getObject())); - if (body == NULL) - return; - Base::BoundBox3d bbox = body->getBoundBox(); + Base::BoundBox3d bbox = this->getRelevantExtents(); + bbox = bbox.Transformed(plm.toMatrix()); - bbox.Enlarge(0.1 * bbox.CalcDiagonalLength()); Base::Vector3d p1, p2; if (bbox.IsInBox(base)) { bbox.IntersectionPoint(base, dir, p1, Precision::Confusion()); diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatumPlane.cpp b/src/Mod/PartDesign/Gui/ViewProviderDatumPlane.cpp index d64655640..349eee753 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatumPlane.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDatumPlane.cpp @@ -48,7 +48,6 @@ #include #include #include -#include using namespace PartDesignGui; @@ -81,10 +80,7 @@ void ViewProviderDatumPlane::updateData(const App::Property* prop) Base::Vector3d normal(0,0,1); // Get limits of the plane from bounding box of the body - PartDesign::Body* body = static_cast(Part::BodyBase::findBodyOf(this->getObject())); - if (body == NULL) - return; - Base::BoundBox3d bbox = body->getBoundBox(); + Base::BoundBox3d bbox = this->getRelevantExtents(); bbox = bbox.Transformed(plm.toMatrix()); double dlength = bbox.CalcDiagonalLength(); if (dlength < Precision::Confusion())