Skip to content

Commit

Permalink
Sketcher: support external reference without subname
Browse files Browse the repository at this point in the history
Reference without subname deliberately disables geometry topo name
tracking to handling some special cases, such as configuration table
with explicit geometry reference. Whole object selection is only enabled
by holding `Alt` key.

Related #1028
  • Loading branch information
realthunder committed Aug 25, 2024
1 parent 12f9135 commit 8b9ad46
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 24 deletions.
44 changes: 36 additions & 8 deletions src/Mod/Sketcher/App/SketchObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7616,15 +7616,24 @@ int SketchObject::addExternal(App::DocumentObject *Obj, const char* SubName, boo
if (!isExternalAllowed(Obj->getDocument(), Obj))
return -1;

auto wholeShape = Part::Feature::getTopoShape(Obj);
auto shape = wholeShape.getSubTopoShape(SubName, /*silent*/true);
Part::TopoShape wholeShape = Part::Feature::getTopoShape(Obj);
Part::TopoShape shape;
TopAbs_ShapeEnum shapeType = TopAbs_SHAPE;
if (shape.shapeType(/*silent*/true) != TopAbs_FACE) {
if (shape.hasSubShape(TopAbs_FACE))
shapeType = TopAbs_FACE;
else if (shape.shapeType(/*silent*/true) != TopAbs_EDGE
&& shape.hasSubShape(TopAbs_EDGE))
shapeType = TopAbs_EDGE;
if (!SubName && !SubName[0]) {
shape = wholeShape.getSubTopoShape(SubName, /*silent*/true);
if (shape.shapeType(/*silent*/true) != TopAbs_FACE
&& shape.shapeType(/*silent*/true) != TopAbs_WIRE) {
if (shape.hasSubShape(TopAbs_FACE)) {
shapeType = TopAbs_FACE;
}
else if (shape.hasSubShape(TopAbs_WIRE)) {
shapeType = TopAbs_WIRE;
}
else if (shape.shapeType(/*silent*/true) != TopAbs_EDGE
&& shape.hasSubShape(TopAbs_EDGE)) {
shapeType = TopAbs_EDGE;
}
}
}

if (shapeType != TopAbs_SHAPE) {
Expand Down Expand Up @@ -8543,6 +8552,21 @@ void SketchObject::rebuildExternalGeometry(bool defining, bool addIntersection)
FC_WARN("Null shape from geometry reference in " << getFullName() << ": " << key);
continue;
}
if (refSubShape.ShapeType() != TopAbs_FACE
&& refSubShape.ShapeType() != TopAbs_EDGE
&& refSubShape.ShapeType() != TopAbs_VERTEX
&& refSubShape.ShapeType() != TopAbs_WIRE)
{
const std::array<TopAbs_ShapeEnum, 4> types = {
TopAbs_FACE, TopAbs_WIRE, TopAbs_EDGE, TopAbs_VERTEX};
Part::TopoShape shape(refSubShape);
for (auto type : types) {
if (shape.hasSubShape(type)) {
refSubShape = shape.getSubShape(type, 1);
break;
}
}
}

auto importFace = [&](const TopoDS_Shape &refSubShape) {
gp_Pln plane;
Expand Down Expand Up @@ -9116,6 +9140,10 @@ void SketchObject::rebuildExternalGeometry(bool defining, bool addIntersection)
if (!intersection)
importFace(refSubShape);
break;
case TopAbs_WIRE:
for (const auto &s : Part::TopoShape(refSubShape).getSubShapes(TopAbs_EDGE))
importEdge(s);
break;
case TopAbs_EDGE:
importEdge(refSubShape);
break;
Expand Down
64 changes: 48 additions & 16 deletions src/Mod/Sketcher/Gui/DrawSketchHandlerExternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,7 @@
#ifndef SKETCHERGUI_DrawSketchHandlerExternal_H
#define SKETCHERGUI_DrawSketchHandlerExternal_H

#include <App/OriginFeature.h>
#include <Mod/Part/App/DatumFeature.h>

#include <Gui/Notifications.h>
#include <Gui/SelectionFilter.h>
#include <Gui/Command.h>
#include <Gui/CommandT.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <Gui/MDIView.h>

#include <Mod/Sketcher/App/SketchObject.h>

#include "DrawSketchHandler.h"
#include <array>
#include "GeometryCreationMode.h"
#include "Utils.h"
#include "ViewProviderSketch.h"
Expand All @@ -59,13 +46,52 @@ class ExternalSelection : public SketcherSelectionFilterGate
bool allow(App::Document* pDoc, App::DocumentObject* pObj, const char* sSubName) override
{
Sketcher::SketchObject* sketch = static_cast<Sketcher::SketchObject*>(object);
static const std::array<const char *, 4> allowedTypes = {"Face", "Wire", "Edge", "Vertex"};

this->notAllowedReason = "";

if (!sSubName || sSubName[0] == '\0') {
this->notAllowedReason = QT_TR_NOOP("No element. ");
bool checkShape = true;
if (sSubName && sSubName[0]) {
for (auto type : allowedTypes) {
if (boost::starts_with(sSubName, type)) {
checkShape = false;
break;
}
}
}
else if (!(QApplication::queryKeyboardModifiers() & Qt::AltModifier)) {
this->notAllowedReason = QT_TR_NOOP("Hold Alt key to enable whole object selection.");
return false;
}

if (checkShape) {
auto shape = Part::TopoShape(Part::Feature::getShape(pObj));
if (shape.isNull()) {
this->notAllowedReason = QT_TR_NOOP("No shape. ");
return false;
}
sSubName = nullptr;
for (auto type : allowedTypes) {
auto shapeType = Part::TopoShape::shapeType(type);
if (shape.shapeType() == shapeType) {
sSubName = type;
break;
}
int count = shape.countSubShapes(shapeType);
if (count == 1) {
sSubName = type;
break;
}
if (count > 1) {
this->notAllowedReason = QT_TR_NOOP("Multiple elements. ");
return false;
}
}
if (!sSubName) {
this->notAllowedReason = QT_TR_NOOP("Unknown element. ");
return false;
}
}

if (!ViewProviderSketch::allowFaceExternalPick() && boost::starts_with(sSubName, "Face")) {
this->notAllowedReason = QT_TR_NOOP("Face picking disabled in the task panel. ");
Expand Down Expand Up @@ -272,10 +298,16 @@ class DrawSketchHandlerExternal: public DrawSketchHandler
throw Base::ValueError("Sketcher: External geometry: Invalid object in selection");
}

if (msg.Object.getOldElementName().empty()
&& !(QApplication::queryKeyboardModifiers() & Qt::AltModifier)) {
return false;
}

auto indexedName = Data::IndexedName(msg.Object.getOldElementName().c_str());
if (intersection ||
obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId()) ||
obj->getTypeId().isDerivedFrom(Part::Datum::getClassTypeId()) ||
msg.Object.getOldElementName().empty() ||
boost::iends_with(indexedName.getType(), "edge") ||
boost::iends_with(indexedName.getType(), "vertex") ||
boost::iends_with(indexedName.getType(), "face") ||
Expand Down

0 comments on commit 8b9ad46

Please sign in to comment.