diff --git a/src/Mod/BIM/Arch.py b/src/Mod/BIM/Arch.py index 577ce7ef2b..bc9b98358d 100644 --- a/src/Mod/BIM/Arch.py +++ b/src/Mod/BIM/Arch.py @@ -1703,6 +1703,7 @@ def makeWindow(baseobj=None, width=None, height=None, parts=None, name=None): 1. If baseobj is not a closed shape, the tool may not create a proper solid figure. """ import Draft + import DraftGeomUtils from draftutils import todo if baseobj and Draft.getType(baseobj) == "Window" and FreeCAD.ActiveDocument: @@ -1730,8 +1731,12 @@ def makeWindow(baseobj=None, width=None, height=None, parts=None, name=None): window.WindowParts = parts else: if baseobj: - if baseobj.getLinkedObject().isDerivedFrom("Part::Part2DObject"): - # Base object is a 2D object (sketch or wire) + linked_obj = baseobj.getLinkedObject(True) + if (linked_obj.isDerivedFrom("Part::Part2DObject") + or Draft.getType(linked_obj) in ["BezCurve", "BSpline", "Wire"]) \ + and DraftGeomUtils.isPlanar(baseobj.Shape): + # "BezCurve", "BSpline" and "Wire" objects created with < v1.1 are "Part::Part2DObject" objects. + # In all versions these objects need not be planar. if baseobj.Shape.Wires: part_type = "Frame" if len(baseobj.Shape.Wires) == 1: diff --git a/src/Mod/BIM/ArchCommands.py b/src/Mod/BIM/ArchCommands.py index a446f7b722..8db79ecd2b 100644 --- a/src/Mod/BIM/ArchCommands.py +++ b/src/Mod/BIM/ArchCommands.py @@ -768,11 +768,14 @@ def pruneIncluded(objectslist,strict=False,silent=False): for parent in obj.InList: if not parent.isDerivedFrom("Part::Feature"): pass - elif Draft.getType(parent) in ["Space","Facebinder","Window","Roof","Clone","Site","Project"]: - pass elif parent.isDerivedFrom("Part::Part2DObject"): # don't consider 2D objects based on arch elements pass + elif Draft.getType(parent) in [ + "BezCurve", "BSpline", "Clone", "Facebinder", "Wire", + "Project", "Roof", "Site", "Space", "Window" + ]: + pass elif parent.isDerivedFrom("PartDesign::FeatureBase"): # don't consider a PartDesign_Clone that references obj pass diff --git a/src/Mod/BIM/ArchSectionPlane.py b/src/Mod/BIM/ArchSectionPlane.py index 8d77f04bbd..bc2526d8ab 100644 --- a/src/Mod/BIM/ArchSectionPlane.py +++ b/src/Mod/BIM/ArchSectionPlane.py @@ -577,7 +577,16 @@ def getDXF(obj): return result if not allOn: objs = Draft.removeHidden(objs) - objs = [o for o in objs if ((not(Draft.getType(o) in ["Space","Dimension","Annotation"])) and (not (o.isDerivedFrom("Part::Part2DObject"))))] + objs = [ + obj + for obj in objs + if ( + not obj.isDerivedFrom("Part::Part2DObject") + and Draft.getType(obj) not in [ + "BezCurve", "BSpline", "Wire", "Annotation", "Dimension", "Space" + ] + ) + ] vshapes,hshapes,sshapes,cutface,cutvolume,invcutvolume = getCutShapes(objs,cutplane,onlySolids,clip,False,showHidden) if vshapes: result.append(TechDraw.projectToDXF(Part.makeCompound(vshapes),direction)) diff --git a/src/Mod/BIM/bimcommands/BimPreflight.py b/src/Mod/BIM/bimcommands/BimPreflight.py index 734d6a80aa..5f29d28b3a 100644 --- a/src/Mod/BIM/bimcommands/BimPreflight.py +++ b/src/Mod/BIM/bimcommands/BimPreflight.py @@ -256,28 +256,20 @@ class BIM_Preflight_TaskPanel: objs = FreeCADGui.Selection.getSelection() # clean objects list of unwanted types objs = Draft.get_group_contents(objs, walls=True, addgroups=True) - objs = [obj for obj in objs if not obj.isDerivedFrom("Part::Part2DObject")] - objs = [obj for obj in objs if not obj.isDerivedFrom("App::Annotation")] objs = [ obj for obj in objs if ( - hasattr(obj, "Shape") + not obj.isDerivedFrom("App::DocumentObjectGroup") + and not obj.isDerivedFrom("App::Annotation") + and not obj.isDerivedFrom("Part::Part2DObject") + and Draft.getType(obj) not in ["BezCurve", "BSpline", "Wire", "WorkingPlaneProxy"] + and hasattr(obj, "Shape") and obj.Shape and not (obj.Shape.Edges and (not obj.Shape.Faces)) ) ] - objs = Arch.pruneIncluded(objs) - objs = [ - obj for obj in objs if not obj.isDerivedFrom("App::DocumentObjectGroup") - ] - objs = [ - obj - for obj in objs - if Draft.getType(obj) - not in ["DraftText", "Material", "MaterialContainer", "WorkingPlaneProxy"] - ] - return objs + return Arch.pruneIncluded(objs) def getToolTip(self, test): "gets the toolTip text from the ui file" diff --git a/src/Mod/BIM/importers/exportIFC.py b/src/Mod/BIM/importers/exportIFC.py index a12fbda457..43740f8805 100644 --- a/src/Mod/BIM/importers/exportIFC.py +++ b/src/Mod/BIM/importers/exportIFC.py @@ -282,9 +282,12 @@ def export(exportList, filename, colors=None, preferences=None): annotations = [] specials = [] for obj in objectslist: - if obj.isDerivedFrom("Part::Part2DObject"): - annotations.append(obj) - elif obj.isDerivedFrom("App::Annotation") or (Draft.getType(obj) in ["DraftText","Text","Dimension","LinearDimension","AngularDimension"]): + if obj.isDerivedFrom("Part::Part2DObject") \ + or obj.isDerivedFrom("App::Annotation") \ + or Draft.getType(obj) in [ + "BezCurve", "BSpline", "Wire", + "DraftText", "Text", "Dimension", "LinearDimension", "AngularDimension" + ]: annotations.append(obj) elif hasattr(obj, "Proxy") and hasattr(obj.Proxy, "export_ifc"): specials.append(obj) diff --git a/src/Mod/BIM/nativeifc/ifc_export.py b/src/Mod/BIM/nativeifc/ifc_export.py index 211f56ff79..ec9288de75 100644 --- a/src/Mod/BIM/nativeifc/ifc_export.py +++ b/src/Mod/BIM/nativeifc/ifc_export.py @@ -215,7 +215,10 @@ def is_annotation(obj): return True elif obj.isDerivedFrom("App::Annotation"): return True - elif Draft.getType(obj) in ["DraftText", + elif Draft.getType(obj) in ["BezCurve", + "BSpline", + "Wire", + "DraftText", "Text", "Dimension", "LinearDimension", diff --git a/src/Mod/Draft/draftfunctions/fuse.py b/src/Mod/Draft/draftfunctions/fuse.py index 899aa3880d..152baaf6b8 100644 --- a/src/Mod/Draft/draftfunctions/fuse.py +++ b/src/Mod/Draft/draftfunctions/fuse.py @@ -57,7 +57,7 @@ def fuse(object1, object2): if len(f.Wires) > 1: holes = True if DraftGeomUtils.isCoplanar(object1.Shape.fuse(object2.Shape).Faces) and not holes: - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython","Fusion") + obj = App.ActiveDocument.addObject("Part::FeaturePython", "Fusion") Wire(obj) if App.GuiUp: ViewProviderWire(obj.ViewObject) @@ -65,10 +65,10 @@ def fuse(object1, object2): obj.Tool = object2 elif holes: # temporary hack, since Part::Fuse objects don't remove splitters - obj = App.ActiveDocument.addObject("Part::Feature","Fusion") + obj = App.ActiveDocument.addObject("Part::Feature", "Fusion") obj.Shape = fshape else: - obj = App.ActiveDocument.addObject("Part::Fuse","Fusion") + obj = App.ActiveDocument.addObject("Part::Fuse", "Fusion") obj.Base = object1 obj.Tool = object2 if App.GuiUp: diff --git a/src/Mod/Draft/draftfunctions/upgrade.py b/src/Mod/Draft/draftfunctions/upgrade.py index 3c9ce544a8..132af193f8 100644 --- a/src/Mod/Draft/draftfunctions/upgrade.py +++ b/src/Mod/Draft/draftfunctions/upgrade.py @@ -563,7 +563,9 @@ def upgrade(objects, delete=False, force=None): _msg(translate("draft", "Found object with several coplanar faces: refining them")) # only one object: if not parametric, we "draftify" it - elif len(objects) == 1 and not objects[0].isDerivedFrom("Part::Part2DObjectPython"): + elif len(objects) == 1 \ + and not objects[0].isDerivedFrom("Part::Part2DObjectPython") \ + and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"]: result = _draftify(objects[0]) if result: _msg(translate("draft", "Found 1 non-parametric object: draftifying it")) @@ -603,7 +605,8 @@ def upgrade(objects, delete=False, force=None): # only one object: if not parametric, we "draftify" it elif len(objects) == 1 \ and len(edges) == 1 \ - and not objects[0].isDerivedFrom("Part::Part2DObjectPython"): + and not objects[0].isDerivedFrom("Part::Part2DObjectPython") \ + and not utils.get_type(objects[0]) in ["BezCurve", "BSpline", "Wire"]: edge_type = DraftGeomUtils.geomType(objects[0].Shape.Edges[0]) # currently only support Line and Circle if edge_type in ("Line", "Circle"): diff --git a/src/Mod/Draft/draftguitools/gui_subelements.py b/src/Mod/Draft/draftguitools/gui_subelements.py index b84020637e..a3b933c23d 100644 --- a/src/Mod/Draft/draftguitools/gui_subelements.py +++ b/src/Mod/Draft/draftguitools/gui_subelements.py @@ -39,6 +39,7 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCADGui as Gui from draftguitools import gui_base_original from draftguitools import gui_tool_utils +from draftutils import utils from draftutils import gui_utils from draftutils.messages import _msg from draftutils.translate import translate @@ -115,10 +116,12 @@ class SubelementHighlight(gui_base_original.Modifier): def get_editable_objects_from_selection(self): """Get editable Draft objects for the selection.""" for obj in Gui.Selection.getSelection(): - if obj.isDerivedFrom("Part::Part2DObject"): + if (obj.isDerivedFrom("Part::Part2DObject") + or utils.get_type(obj) in ["BezCurve", "BSpline", "Wire"]): self.editable_objects.append(obj) elif (hasattr(obj, "Base") - and obj.Base.isDerivedFrom("Part::Part2DObject")): + and (obj.Base.isDerivedFrom("Part::Part2DObject") + or utils.get_type(obj.Base) in ["BezCurve", "BSpline", "Wire"])): self.editable_objects.append(obj.Base) def highlight_editable_objects(self): diff --git a/src/Mod/Draft/draftmake/make_bezcurve.py b/src/Mod/Draft/draftmake/make_bezcurve.py index b6cb58200b..9337104932 100644 --- a/src/Mod/Draft/draftmake/make_bezcurve.py +++ b/src/Mod/Draft/draftmake/make_bezcurve.py @@ -81,7 +81,8 @@ def make_bezcurve(pointslist, utils.type_check([(placement,App.Placement)], "make_bezcurve") if len(pointslist) == 2: fname = "Line" else: fname = "BezCurve" - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython",fname) + obj = App.ActiveDocument.addObject("Part::FeaturePython", fname) + obj.addExtension("Part::AttachExtensionPython") BezCurve(obj) obj.Points = pointslist if degree: diff --git a/src/Mod/Draft/draftmake/make_block.py b/src/Mod/Draft/draftmake/make_block.py index 2ca91d1dd1..3d2e563a7a 100644 --- a/src/Mod/Draft/draftmake/make_block.py +++ b/src/Mod/Draft/draftmake/make_block.py @@ -50,7 +50,8 @@ def make_block(objectslist): if not App.ActiveDocument: App.Console.PrintError("No active document. Aborting\n") return - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython","Block") + obj = App.ActiveDocument.addObject("Part::FeaturePython", "Block") + obj.addExtension("Part::AttachExtensionPython") Block(obj) obj.Components = objectslist if App.GuiUp: diff --git a/src/Mod/Draft/draftmake/make_bspline.py b/src/Mod/Draft/draftmake/make_bspline.py index d5c6b4e4fa..fba96813d2 100644 --- a/src/Mod/Draft/draftmake/make_bspline.py +++ b/src/Mod/Draft/draftmake/make_bspline.py @@ -92,7 +92,8 @@ def make_bspline(pointslist, closed=False, placement=None, face=None, support=No utils.type_check([(placement,App.Placement)], "make_bspline") if len(pointslist) == 2: fname = "Line" else: fname = "BSpline" - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython",fname) + obj = App.ActiveDocument.addObject("Part::FeaturePython", fname) + obj.addExtension("Part::AttachExtensionPython") BSpline(obj) obj.Closed = closed obj.Points = pointslist diff --git a/src/Mod/Draft/draftmake/make_clone.py b/src/Mod/Draft/draftmake/make_clone.py index 8fe82ee1df..2c5bf5c9eb 100644 --- a/src/Mod/Draft/draftmake/make_clone.py +++ b/src/Mod/Draft/draftmake/make_clone.py @@ -67,10 +67,16 @@ def make_clone(obj, delta=None, forcedraft=False): if not isinstance(obj,list): obj = [obj] - if (len(obj) == 1) and obj[0].isDerivedFrom("Part::Part2DObject"): - cl = App.ActiveDocument.addObject("Part::Part2DObjectPython","Clone2D") + if len(obj) == 1 \ + and obj[0].isDerivedFrom("Part::Part2DObject") \ + and utils.get_type(obj[0]) not in ["BezCurve", "BSpline", "Wire"]: + # "BezCurve", "BSpline" and "Wire" objects created with < v1.1 + # are "Part::Part2DObject" objects but they need not be 2D. + cl = App.ActiveDocument.addObject("Part::Part2DObjectPython", "Clone2D") cl.Label = prefix + obj[0].Label + " (2D)" - elif (len(obj) == 1) and (hasattr(obj[0],"CloneOf") or (utils.get_type(obj[0]) == "BuildingPart")) and (not forcedraft): + elif len(obj) == 1 \ + and (hasattr(obj[0], "CloneOf") or utils.get_type(obj[0]) == "BuildingPart") \ + and not forcedraft: # arch objects can be clones try: import Arch @@ -106,7 +112,7 @@ def make_clone(obj, delta=None, forcedraft=False): # fall back to Draft clone mode if not cl: - cl = App.ActiveDocument.addObject("Part::FeaturePython","Clone") + cl = App.ActiveDocument.addObject("Part::FeaturePython", "Clone") cl.addExtension("Part::AttachExtensionPython") cl.Label = prefix + obj[0].Label Clone(cl) diff --git a/src/Mod/Draft/draftmake/make_wire.py b/src/Mod/Draft/draftmake/make_wire.py index bd82bdf04f..d650e431d4 100644 --- a/src/Mod/Draft/draftmake/make_wire.py +++ b/src/Mod/Draft/draftmake/make_wire.py @@ -108,7 +108,8 @@ def make_wire(pointslist, closed=False, placement=None, face=None, support=None, else: fname = "Wire" - obj = App.ActiveDocument.addObject("Part::Part2DObjectPython", fname) + obj = App.ActiveDocument.addObject("Part::FeaturePython", fname) + obj.addExtension("Part::AttachExtensionPython") Wire(obj) obj.Points = pointslist obj.Closed = closed diff --git a/src/Mod/Draft/draftobjects/base.py b/src/Mod/Draft/draftobjects/base.py index ca3860987d..507a92fec1 100644 --- a/src/Mod/Draft/draftobjects/base.py +++ b/src/Mod/Draft/draftobjects/base.py @@ -66,9 +66,7 @@ class DraftObject(object): allows distinguishing among various types of objects derived from the same C++ class. - >>> print(A.TypeId, "->", A.Proxy.Type) - Part::Part2DObjectPython -> Wire - >>> print(B.TypeId, "->", B.Proxy.Type) + >>> print(obj.TypeId, "->", obj.Proxy.Type) Part::Part2DObjectPython -> Circle This class attribute is accessible through the `Proxy` object: diff --git a/src/Mod/Draft/importAirfoilDAT.py b/src/Mod/Draft/importAirfoilDAT.py index 9380975ff4..4ad1f0de17 100644 --- a/src/Mod/Draft/importAirfoilDAT.py +++ b/src/Mod/Draft/importAirfoilDAT.py @@ -121,8 +121,8 @@ def process(filename): Returns ------- - Part::Part2DObject or None. - The created Draft Wire object or None if the file contains less + Part::Feature or None. + The created object or None if the file contains fewer than 3 points. """ # Regex to identify data rows and throw away unused metadata diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index eb58ad9586..2f458b7ab6 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -795,7 +795,7 @@ def drawLine(line, forceShape=False): Returns ------- - Part::Part2DObject or Part::TopoShape ('Edge') + Part::Feature or Part::TopoShape ('Edge') The returned object is normally a `Wire`, if the global variables `dxfCreateDraft` or `dxfCreateSketch` are set, and `forceShape` is `False`. @@ -847,7 +847,7 @@ def drawPolyline(polyline, forceShape=False, num=None): Returns ------- - Part::Part2DObject or Part::TopoShape ('Wire', 'Face', 'Shell') + Part::Feature or Part::TopoShape ('Wire', 'Face', 'Shell') It returns `None` if it fails producing a shape. If the polyline has a `width` and the global variable @@ -1292,7 +1292,7 @@ def drawSplineIterpolation(verts, closed=False, forceShape=False, Returns ------- - Part::Part2DObject or Part::TopoShape ('Edge', 'Face') + Part::Feature or Part::TopoShape ('Edge', 'Face') The returned object is normally a `Draft Wire` or `Draft BSpline`, if the global variables `dxfCreateDraft` or `dxfCreateSketch` are set, and `forceShape` is `False`. @@ -1350,7 +1350,7 @@ def drawSplineOld(spline, forceShape=False): Returns ------- - Part::Part2DObject or Part::TopoShape ('Edge', 'Face') + Part::Feature or Part::TopoShape ('Edge', 'Face') The returned object is normally a `Draft Wire` or `Draft BSpline` as returned from `drawSplineIterpolation()`. @@ -1409,7 +1409,7 @@ def drawSpline(spline, forceShape=False): Returns ------- - Part::Part2DObject or Part::TopoShape ('Edge', 'Face') + Part::Feature or Part::TopoShape ('Edge', 'Face') The returned object is normally a `Draft BezCurve` created with `Draft.make_bezcurve(controlpoints, degree=degree)`, if `forceShape` is `False` and there are no weights. @@ -1813,7 +1813,7 @@ def drawLayerBlock(objlist, name="LayerBlock"): Returns ------- - Part::Part2DObject or Part::TopoShape ('Compound') + Part::Feature or Part::TopoShape ('Compound') If the global variables `dxfCreateDraft` or `dxfCreateSketch` are set, and no element in `objlist` is a `Part.Shape`, it will try to return a `Draft Block`. @@ -1910,9 +1910,8 @@ def addObject(shape, name="Shape", layer=None): ------- Part::Feature or Part::Part2DObject If the `shape` is a simple `Part.Shape`, it will be encapsulated - inside a `Part::Feature` object and this will be returned. - Otherwise, it is assumed it is already a Draft object - (`Part::Part2DObject`) and will just return this. + inside a `Part::Feature` object and this will be returned. Otherwise, + it is assumed it is already a Draft object which will just be returned. It applies the text and line color by calling `formatObject()` before returning the new object. @@ -1941,8 +1940,6 @@ def addObject(shape, name="Shape", layer=None): l = layerObjects[lay] l.append(newob) - - formatObject(newob) return newob