PartDesign: Enable selecting a sketch as base plane of another sketch (#23428)
* PartDesign: Enable selecting a sketch as base plane of another sketch * to squash * Part: Attacher: enable attaching to empty objects such as empty Sketch or Body. * Update SketchWorkflow.cpp
This commit is contained in:
@@ -842,9 +842,19 @@ void AttachEngine::readLinks(const std::vector<App::DocumentObject*>& objs,
|
||||
|
||||
auto shape = extractSubShape(objs[i], subs[i]);
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: null subshape " << objs[i]->getNameInDocument() << '.'
|
||||
<< subs[i]);
|
||||
if (subs[i].length() == 0) {
|
||||
storage.emplace_back(TopoShape());
|
||||
shapes[i] = &storage.back();
|
||||
types[i] = eRefType(rtPart | rtFlagHasPlacement);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// This case should now be unreachable because extractSubShape would have thrown
|
||||
// for a missing subname. But it's good defensive programming.
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: null subshape " << objs[i]->getNameInDocument() << '.'
|
||||
<< subs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
storage.emplace_back(shape);
|
||||
@@ -889,9 +899,22 @@ TopoShape AttachEngine::extractSubShape(App::DocumentObject* obj, const std::str
|
||||
|
||||
for (;;) {
|
||||
if (shape.isNull()) {
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: subshape not found " << obj->getNameInDocument() << '.'
|
||||
<< subname);
|
||||
// Shape is null. Let's see if this is an acceptable null.
|
||||
// (i.e., an empty object was selected, not a broken link to a sub-element).
|
||||
if (subname.empty()) {
|
||||
// The user selected the whole object, and it has no shape.
|
||||
// This is the empty sketch or empty body case.
|
||||
// Instead of throwing an error, we return a null TopoShape.
|
||||
// The caller (readLinks) will then handle this null shape.
|
||||
return TopoShape(); // Return a default-constructed (null) shape
|
||||
}
|
||||
else {
|
||||
// The user specified a subname (e.g., "Edge1"), but it couldn't be found.
|
||||
// This is a genuine error.
|
||||
FC_THROWM(AttachEngineException,
|
||||
"AttachEngine3D: subshape not found " << obj->getNameInDocument()
|
||||
<< '.' << subname);
|
||||
}
|
||||
}
|
||||
|
||||
if (shape.shapeType() != TopAbs_COMPOUND || shape.countSubShapes(TopAbs_SHAPE) != 1) {
|
||||
|
||||
@@ -197,17 +197,18 @@ class SketchPreselection
|
||||
{
|
||||
public:
|
||||
SketchPreselection(Gui::Document* guidocument, PartDesign::Body* activeBody,
|
||||
std::tuple<Gui::SelectionFilter, Gui::SelectionFilter> filter)
|
||||
std::tuple<Gui::SelectionFilter, Gui::SelectionFilter, Gui::SelectionFilter> filter)
|
||||
: guidocument(guidocument)
|
||||
, activeBody(activeBody)
|
||||
, faceFilter(std::get<0>(filter))
|
||||
, planeFilter(std::get<1>(filter))
|
||||
, sketchFilter(std::get<2>(filter))
|
||||
{
|
||||
}
|
||||
|
||||
bool matches()
|
||||
{
|
||||
return faceFilter.match() || planeFilter.match();
|
||||
return faceFilter.match() || planeFilter.match() || sketchFilter.match();
|
||||
}
|
||||
|
||||
std::string getSupport() const
|
||||
@@ -231,11 +232,17 @@ public:
|
||||
selectedObject = validator.getObject();
|
||||
supportString = validator.getSupport();
|
||||
}
|
||||
else {
|
||||
else if (planeFilter.match()) {
|
||||
SupportPlaneValidator validator(planeFilter.Result[0][0]);
|
||||
selectedObject = validator.getObject();
|
||||
supportString = validator.getSupport();
|
||||
}
|
||||
else {
|
||||
// For a sketch, the support is the object itself with no sub-element.
|
||||
Gui::SelectionObject sketchSelObject = sketchFilter.Result[0][0];
|
||||
selectedObject = sketchSelObject.getObject();
|
||||
supportString = sketchSelObject.getAsPropertyLinkSubString();
|
||||
}
|
||||
|
||||
handleIfSupportOutOfBody(selectedObject);
|
||||
}
|
||||
@@ -250,7 +257,16 @@ public:
|
||||
FCMD_OBJ_CMD(activeBody, "newObject('Sketcher::SketchObject','" << FeatName << "')");
|
||||
auto Feat = activeBody->getDocument()->getObject(FeatName.c_str());
|
||||
FCMD_OBJ_CMD(Feat, "AttachmentSupport = " << supportString);
|
||||
FCMD_OBJ_CMD(Feat, "MapMode = '" << Attacher::AttachEngine::getModeName(Attacher::mmFlatFace)<<"'");
|
||||
if (sketchFilter.match()) {
|
||||
FCMD_OBJ_CMD(Feat,
|
||||
"MapMode = '" << Attacher::AttachEngine::getModeName(Attacher::mmObjectXY)
|
||||
<< "'");
|
||||
}
|
||||
else { // For Face or Plane
|
||||
FCMD_OBJ_CMD(Feat,
|
||||
"MapMode = '" << Attacher::AttachEngine::getModeName(Attacher::mmFlatFace)
|
||||
<< "'");
|
||||
}
|
||||
Gui::Command::updateActive();
|
||||
PartDesignGui::setEdit(Feat, activeBody);
|
||||
}
|
||||
@@ -346,6 +362,7 @@ private:
|
||||
PartDesign::Body* activeBody;
|
||||
Gui::SelectionFilter faceFilter;
|
||||
Gui::SelectionFilter planeFilter;
|
||||
Gui::SelectionFilter sketchFilter;
|
||||
std::string supportString;
|
||||
};
|
||||
|
||||
@@ -757,8 +774,8 @@ void SketchWorkflow::tryCreateSketch()
|
||||
return;
|
||||
}
|
||||
|
||||
auto faceOrPlaneFilter = getFaceAndPlaneFilter();
|
||||
SketchPreselection sketchOnFace{ guidocument, activeBody, faceOrPlaneFilter };
|
||||
auto filters = getFilters();
|
||||
SketchPreselection sketchOnFace {guidocument, activeBody, filters};
|
||||
|
||||
if (sketchOnFace.matches()) {
|
||||
// create Sketch on Face or Plane
|
||||
@@ -804,7 +821,7 @@ bool SketchWorkflow::shouldAbort(bool shouldMakeBody) const
|
||||
return !shouldMakeBody && !activeBody;
|
||||
}
|
||||
|
||||
std::tuple<Gui::SelectionFilter, Gui::SelectionFilter> SketchWorkflow::getFaceAndPlaneFilter() const
|
||||
std::tuple<Gui::SelectionFilter, Gui::SelectionFilter, Gui::SelectionFilter> SketchWorkflow::getFilters() const
|
||||
{
|
||||
// Hint:
|
||||
// The behaviour of this command has changed with respect to a selected sketch:
|
||||
@@ -815,9 +832,11 @@ std::tuple<Gui::SelectionFilter, Gui::SelectionFilter> SketchWorkflow::getFaceAn
|
||||
Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1");
|
||||
Gui::SelectionFilter PlaneFilter ("SELECT App::Plane COUNT 1", activeBody);
|
||||
Gui::SelectionFilter PlaneFilter2("SELECT PartDesign::Plane COUNT 1", activeBody);
|
||||
Gui::SelectionFilter SketchFilter("SELECT Part::2DObject COUNT 1", activeBody);
|
||||
|
||||
if (PlaneFilter2.match()) {
|
||||
PlaneFilter = PlaneFilter2;
|
||||
}
|
||||
return std::make_tuple(FaceFilter, PlaneFilter);
|
||||
|
||||
return std::make_tuple(FaceFilter, PlaneFilter, SketchFilter);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ private:
|
||||
void tryCreateSketch();
|
||||
std::tuple<bool, PartDesign::Body*> shouldCreateBody();
|
||||
bool shouldAbort(bool) const;
|
||||
std::tuple<Gui::SelectionFilter, Gui::SelectionFilter> getFaceAndPlaneFilter() const;
|
||||
std::tuple<Gui::SelectionFilter, Gui::SelectionFilter, Gui::SelectionFilter> getFilters() const;
|
||||
|
||||
private:
|
||||
Gui::Document* guidocument;
|
||||
|
||||
Reference in New Issue
Block a user