diff --git a/src/Mod/Draft/draftfunctions/move.py b/src/Mod/Draft/draftfunctions/move.py index 032c4d6529..cbb22dfd66 100644 --- a/src/Mod/Draft/draftfunctions/move.py +++ b/src/Mod/Draft/draftfunctions/move.py @@ -87,16 +87,7 @@ def move(objectslist, vector, copy=False): else: real_vector = vector - if utils.get_type(obj) == "Point": - if copy: - newobj = make_copy.make_copy(obj) - else: - newobj = obj - newobj.X = obj.X.Value + real_vector.x - newobj.Y = obj.Y.Value + real_vector.y - newobj.Z = obj.Z.Value + real_vector.z - - elif obj.isDerivedFrom("App::DocumentObjectGroup"): + if obj.isDerivedFrom("App::DocumentObjectGroup"): if copy: newobj = newgroups[obj.Name] else: diff --git a/src/Mod/Draft/draftfunctions/rotate.py b/src/Mod/Draft/draftfunctions/rotate.py index 4c0c4e692c..2b6d1a14c4 100644 --- a/src/Mod/Draft/draftfunctions/rotate.py +++ b/src/Mod/Draft/draftfunctions/rotate.py @@ -121,19 +121,6 @@ def rotate(objectslist, angle, center=App.Vector(0, 0, 0), newobj.ViewObject.RotationAxis = "Z" newobj.ViewObject.Rotation = -angle - elif utils.get_type(obj) == "Point": - if copy: - newobj = make_copy.make_copy(obj) - else: - newobj = obj - v = App.Vector(newobj.X, newobj.Y, newobj.Z) - rv = v.sub(real_center) - rv = DraftVecUtils.rotate(rv, math.radians(angle), real_axis) - v = real_center.add(rv) - newobj.X = v.x - newobj.Y = v.y - newobj.Z = v.z - elif obj.isDerivedFrom("App::DocumentObjectGroup"): if copy: newobj = newgroups[obj.Name] diff --git a/src/Mod/Draft/draftguitools/gui_base_original.py b/src/Mod/Draft/draftguitools/gui_base_original.py index ada4d30486..fcde96f310 100644 --- a/src/Mod/Draft/draftguitools/gui_base_original.py +++ b/src/Mod/Draft/draftguitools/gui_base_original.py @@ -191,7 +191,13 @@ class DraftTool: pass self.call = None if self.commitList: - todo.ToDo.delayCommit(self.commitList) + last_cmd = self.commitList[-1][1][-1] + if last_cmd.find("recompute") >= 0: + self.commitList[-1] = (self.commitList[-1][0], self.commitList[-1][1][:-1]) + todo.ToDo.delayCommit(self.commitList) + todo.ToDo.delayAfter(Gui.doCommand, last_cmd) + else: + todo.ToDo.delayCommit(self.commitList) self.commitList = [] def commit(self, name, func): diff --git a/src/Mod/Draft/draftmake/make_point.py b/src/Mod/Draft/draftmake/make_point.py index 843ec2297b..e1177950a1 100644 --- a/src/Mod/Draft/draftmake/make_point.py +++ b/src/Mod/Draft/draftmake/make_point.py @@ -75,6 +75,7 @@ def make_point(X=0, Y=0, Z=0, color=None, name="Point", point_size=5): X = X.x Point(obj, X, Y, Z) + obj.Placement.Base = App.Vector(X, Y, Z) if App.GuiUp: ViewProviderPoint(obj.ViewObject) diff --git a/src/Mod/Draft/draftobjects/array.py b/src/Mod/Draft/draftobjects/array.py index 6cac791e89..284c7de8ee 100644 --- a/src/Mod/Draft/draftobjects/array.py +++ b/src/Mod/Draft/draftobjects/array.py @@ -381,7 +381,9 @@ class Array(DraftLink): def execute(self, obj): """Execute when the object is created or recomputed.""" - if not obj.Base: + if self.props_changed_placement_only() \ + or not obj.Base: + self.props_changed_clear() return pl = obj.Placement @@ -419,7 +421,9 @@ class Array(DraftLink): axis, center, obj.NumberCircles, obj.Symmetry) - return super(Array, self).buildShape(obj, pl, pls) + self.buildShape(obj, pl, pls) + self.props_changed_clear() + return (not self.use_link) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/base.py b/src/Mod/Draft/draftobjects/base.py index e6c691bc13..c248b83d42 100644 --- a/src/Mod/Draft/draftobjects/base.py +++ b/src/Mod/Draft/draftobjects/base.py @@ -81,6 +81,10 @@ class DraftObject(object): obj.Proxy = self self.Type = tp + def onDocumentRestored(self,obj): + # Object properties are updated when the document is opened. + self.props_changed_clear() + def __getstate__(self): """Return a tuple of all serializable objects or None. @@ -155,6 +159,42 @@ class DraftObject(object): """ pass + def props_changed_store(self, prop): + """Store the name of the property that will be changed in the + self.props_changed list. + + The function should be called at the start of onChanged or onBeforeChange. + + The list is used to detect Placement-only changes. In such cases the + Shape of an object does not need to be updated. Not updating the Shape + avoids Uno/Redo issues for the Windows version and is also more efficient. + """ + if not hasattr(self, "props_changed"): + self.props_changed = [prop] + else: + self.props_changed.append(prop) + + def props_changed_clear(self): + """Remove the self.props_changed attribute if it exists. + + The function should be called just before execute returns. + """ + if hasattr(self, "props_changed"): + delattr(self, "props_changed") + + def props_changed_placement_only(self): + """Return `True` if the self.props_changed list, after removing `Shape` + and `_LinkTouched` items, only contains `Placement` items. + """ + if not hasattr(self, "props_changed"): + return False + props = set(self.props_changed) + if "Shape" in props: + props.remove("Shape") + if "_LinkTouched" in props: + props.remove("_LinkTouched") + return props == {"Placement"} + # Alias for compatibility with v0.18 and earlier _DraftObject = DraftObject diff --git a/src/Mod/Draft/draftobjects/bezcurve.py b/src/Mod/Draft/draftobjects/bezcurve.py index 54f12e4eb6..a4502da150 100644 --- a/src/Mod/Draft/draftobjects/bezcurve.py +++ b/src/Mod/Draft/draftobjects/bezcurve.py @@ -77,8 +77,14 @@ class BezCurve(DraftObject): obj.setEditorMode("Continuity", 1) def execute(self, fp): + if self.props_changed_placement_only(): + fp.positionBySupport() + self.props_changed_clear() + return + self.createGeometry(fp) fp.positionBySupport() + self.props_changed_clear() def _segpoleslst(self,fp): """Split the points into segments.""" @@ -99,6 +105,8 @@ class BezCurve(DraftObject): #fp.Continuity = [0]*numsegments def onChanged(self, fp, prop): + self.props_changed_store(prop) + if prop == 'Closed': # if remove the last entry when curve gets opened oldlen = len(fp.Continuity) diff --git a/src/Mod/Draft/draftobjects/block.py b/src/Mod/Draft/draftobjects/block.py index fbcfd17b67..361e29e619 100644 --- a/src/Mod/Draft/draftobjects/block.py +++ b/src/Mod/Draft/draftobjects/block.py @@ -43,6 +43,11 @@ class Block(DraftObject): obj.addProperty("App::PropertyLinkList","Components", "Draft", _tip) def execute(self, obj): + if self.props_changed_placement_only(): + obj.positionBySupport() + self.props_changed_clear() + return + import Part plm = obj.Placement shps = [] @@ -53,6 +58,10 @@ class Block(DraftObject): obj.Shape = shape obj.Placement = plm obj.positionBySupport() + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/bspline.py b/src/Mod/Draft/draftobjects/bspline.py index 22c6de731e..a9a4e0684a 100644 --- a/src/Mod/Draft/draftobjects/bspline.py +++ b/src/Mod/Draft/draftobjects/bspline.py @@ -83,6 +83,8 @@ class BSpline(DraftObject): return params def onChanged(self, fp, prop): + self.props_changed_store(prop) + if prop == "Parameterization": if fp.Parameterization < 0.: fp.Parameterization = 0. @@ -90,13 +92,16 @@ class BSpline(DraftObject): fp.Parameterization = 1.0 def execute(self, obj): + if self.props_changed_placement_only() \ + or not obj.Points: + obj.positionBySupport() + self.props_changed_clear() + return + import Part self.assureProperties(obj) - if not obj.Points: - obj.positionBySupport() - self.knotSeq = self.parameterization(obj.Points, obj.Parameterization, obj.Closed) plm = obj.Placement if obj.Closed and (len(obj.Points) > 2): @@ -131,6 +136,7 @@ class BSpline(DraftObject): obj.Area = shape.Area obj.Placement = plm obj.positionBySupport() + self.props_changed_clear() # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/circle.py b/src/Mod/Draft/draftobjects/circle.py index 7be18b3827..de507e6e3f 100644 --- a/src/Mod/Draft/draftobjects/circle.py +++ b/src/Mod/Draft/draftobjects/circle.py @@ -64,9 +64,13 @@ class Circle(DraftObject): obj.MakeFace = utils.get_param("fillmode", True) - def execute(self, obj): """This method is run when the object is created or recomputed.""" + if self.props_changed_placement_only(): + obj.positionBySupport() + self.props_changed_clear() + return + import Part plm = obj.Placement @@ -88,8 +92,11 @@ class Circle(DraftObject): obj.Area = shape.Area obj.Placement = plm - obj.positionBySupport() + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/clone.py b/src/Mod/Draft/draftobjects/clone.py index e30bd077a6..567f164307 100644 --- a/src/Mod/Draft/draftobjects/clone.py +++ b/src/Mod/Draft/draftobjects/clone.py @@ -86,6 +86,12 @@ class Clone(DraftObject): return Part.makeCompound(shapes) def execute(self,obj): + if self.props_changed_placement_only(): + if hasattr(obj,"positionBySupport"): + obj.positionBySupport() + self.props_changed_clear() + return + import Part pl = obj.Placement shapes = [] @@ -118,6 +124,10 @@ class Clone(DraftObject): obj.Placement = pl if hasattr(obj,"positionBySupport"): obj.positionBySupport() + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) def getSubVolume(self,obj,placement=None): # this allows clones of arch windows to return a subvolume too diff --git a/src/Mod/Draft/draftobjects/draftlink.py b/src/Mod/Draft/draftobjects/draftlink.py index e2eaecc307..99aaefb1cf 100644 --- a/src/Mod/Draft/draftobjects/draftlink.py +++ b/src/Mod/Draft/draftobjects/draftlink.py @@ -181,6 +181,9 @@ class DraftLink(DraftObject): else: self.execute(obj) + # Object properties are updated when the document is opened. + self.props_changed_clear() + def buildShape(self, obj, pl, pls): """Build the shape of the link object.""" if self.use_link: @@ -229,6 +232,8 @@ class DraftLink(DraftObject): def onChanged(self, obj, prop): """Execute when a property changes.""" + self.props_changed_store(prop) + if not getattr(self, 'use_link', False): return diff --git a/src/Mod/Draft/draftobjects/ellipse.py b/src/Mod/Draft/draftobjects/ellipse.py index fb6cdc8891..2cf83010a9 100644 --- a/src/Mod/Draft/draftobjects/ellipse.py +++ b/src/Mod/Draft/draftobjects/ellipse.py @@ -63,6 +63,11 @@ class Ellipse(DraftObject): obj.MakeFace = utils.get_param("fillmode",True) def execute(self, obj): + if self.props_changed_placement_only(): + obj.positionBySupport() + self.props_changed_clear() + return + import Part plm = obj.Placement if obj.MajorRadius.Value < obj.MinorRadius.Value: @@ -91,6 +96,10 @@ class Ellipse(DraftObject): obj.Area = shape.Area obj.Placement = plm obj.positionBySupport() + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/facebinder.py b/src/Mod/Draft/draftobjects/facebinder.py index 7492a7ae62..4540f575a6 100644 --- a/src/Mod/Draft/draftobjects/facebinder.py +++ b/src/Mod/Draft/draftobjects/facebinder.py @@ -59,6 +59,10 @@ class Facebinder(DraftObject): obj.setEditorMode("Area",1) def execute(self,obj): + if self.props_changed_placement_only(): + self.props_changed_clear() + return + import Part pl = obj.Placement if not obj.Faces: @@ -117,6 +121,10 @@ class Facebinder(DraftObject): obj.Shape = sh obj.Placement = pl obj.Area = area + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) def addSubobjects(self,obj,facelinks): """adds facelinks to this facebinder""" diff --git a/src/Mod/Draft/draftobjects/hatch.py b/src/Mod/Draft/draftobjects/hatch.py index 30f47f1a56..13272b9a59 100644 --- a/src/Mod/Draft/draftobjects/hatch.py +++ b/src/Mod/Draft/draftobjects/hatch.py @@ -28,9 +28,10 @@ import FreeCAD as App from draftutils.translate import translate, QT_TRANSLATE_NOOP from draftgeoutils.general import geomType +from draftobjects.base import DraftObject -class Hatch: +class Hatch(DraftObject): def __init__(self,obj): @@ -76,24 +77,20 @@ class Hatch: def execute(self,obj): + if self.props_changed_placement_only() \ + or not obj.Base \ + or not obj.File \ + or not obj.Pattern \ + or not obj.Scale \ + or not obj.Pattern in self.getPatterns(obj.File) \ + or not obj.Base.isDerivedFrom("Part::Feature") \ + or not obj.Base.Shape.Faces: + self.props_changed_clear() + return + import Part import TechDraw - if not obj.Base: - return - if not obj.File: - return - if not obj.Pattern: - return - if not obj.Scale: - return - if not obj.Pattern in self.getPatterns(obj.File): - return - if not obj.Base.isDerivedFrom("Part::Feature"): - return - if not obj.Base.Shape.Faces: - return - shapes = [] for face in obj.Base.Shape.Faces: if face.findPlane(): # Only planar faces. @@ -132,6 +129,11 @@ class Hatch: shapes.append(shape) if shapes: obj.Shape = Part.makeCompound(shapes) + self.props_changed_clear() + + def onChanged(self, obj, prop): + + self.props_changed_store(prop) def getPatterns(self,filename): diff --git a/src/Mod/Draft/draftobjects/patharray.py b/src/Mod/Draft/draftobjects/patharray.py index 19c9a33f7c..851aa0b43c 100644 --- a/src/Mod/Draft/draftobjects/patharray.py +++ b/src/Mod/Draft/draftobjects/patharray.py @@ -272,7 +272,10 @@ class PathArray(DraftLink): def execute(self, obj): """Execute when the object is created or recomputed.""" - if not obj.Base or not obj.PathObject: + if self.props_changed_placement_only() \ + or not obj.Base \ + or not obj.PathObject: + self.props_changed_clear() return # placement of entire PathArray object @@ -303,9 +306,9 @@ class PathArray(DraftLink): obj.ForceVertical, obj.VerticalVector) - return super(PathArray, self).buildShape(obj, - array_placement, - copy_placements) + self.buildShape(obj, array_placement, copy_placements) + self.props_changed_clear() + return (not self.use_link) def get_wires(self, path_object, subelements): """Get wires from the path object.""" @@ -375,20 +378,9 @@ class PathArray(DraftLink): Add properties that don't exist. """ - super(PathArray, self).migrate_attributes(obj) self.set_properties(obj) self.migrate_properties_0v19(obj) - - if self.use_link: - self.linkSetup(obj) - else: - obj.setPropertyStatus('Shape', '-Transient') - - if obj.Shape.isNull(): - if getattr(obj, 'PlacementList', None): - self.buildShape(obj, obj.Placement, obj.PlacementList) - else: - self.execute(obj) + super(PathArray, self).onDocumentRestored(obj) def migrate_properties_0v19(self, obj): """Migrate properties of this class, not from the parent class.""" diff --git a/src/Mod/Draft/draftobjects/pathtwistedarray.py b/src/Mod/Draft/draftobjects/pathtwistedarray.py index 3615cc1da1..dd7daf8cb4 100644 --- a/src/Mod/Draft/draftobjects/pathtwistedarray.py +++ b/src/Mod/Draft/draftobjects/pathtwistedarray.py @@ -120,31 +120,20 @@ class PathTwistedArray(DraftLink): super(PathTwistedArray, self).linkSetup(obj) obj.configLinkProperty(ElementCount='Count') - def onChanged(self, obj, prop): - """Execute when a property is changed.""" - super(PathTwistedArray, self).onChanged(obj, prop) - def onDocumentRestored(self, obj): """Execute code when the document is restored. Add properties that don't exist. """ self.set_properties(obj) - - if self.use_link: - self.linkSetup(obj) - else: - obj.setPropertyStatus('Shape', '-Transient') - - if obj.Shape.isNull(): - if getattr(obj, 'PlacementList', None): - self.buildShape(obj, obj.Placement, obj.PlacementList) - else: - self.execute(obj) + super(PathTwistedArray, self).onDocumentRestored(obj) def execute(self, obj): """Execute when the object is created or recomputed.""" - if not obj.Base or not obj.PathObject: + if self.props_changed_placement_only() \ + or not obj.Base \ + or not obj.PathObject: + self.props_changed_clear() return # placement of entire PathArray object @@ -158,8 +147,8 @@ class PathTwistedArray(DraftLink): count=count, rot_factor=rot_factor) - return super(PathTwistedArray, self).buildShape(obj, - array_placement, - copy_placements) + self.buildShape(obj, array_placement, copy_placements) + self.props_changed_clear() + return (not self.use_link) ## @} diff --git a/src/Mod/Draft/draftobjects/point.py b/src/Mod/Draft/draftobjects/point.py index fda5800a74..7703693086 100644 --- a/src/Mod/Draft/draftobjects/point.py +++ b/src/Mod/Draft/draftobjects/point.py @@ -57,19 +57,25 @@ class Point(DraftObject): obj.setPropertyStatus('Placement', 'Hidden') def execute(self, obj): + base = obj.Placement.Base + xyz_vec = App.Vector(obj.X.Value, obj.Y.Value, obj.Z.Value) + + if self.props_changed_placement_only(): + if base != xyz_vec: + obj.X = base.x + obj.Y = base.y + obj.Z = base.z + self.props_changed_clear() + return + import Part - shape = Part.Vertex(App.Vector(0, 0, 0)) - obj.Shape = shape - if obj.Placement.Base != App.Vector(obj.X, obj.Y, obj.Z): - obj.Placement.Base = App.Vector(obj.X, obj.Y, obj.Z) + obj.Shape = Part.Vertex(App.Vector(0, 0, 0)) + if base != xyz_vec: + obj.Placement.Base = xyz_vec + self.props_changed_clear() def onChanged(self, obj, prop): - if prop == "Placement" \ - and obj.Placement.Base != App.Vector(obj.X, obj.Y, obj.Z): - base = obj.Placement.Base - obj.X = base.x - obj.Y = base.y - obj.Z = base.z + self.props_changed_store(prop) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/pointarray.py b/src/Mod/Draft/draftobjects/pointarray.py index 1d10f073c0..7fa088a713 100644 --- a/src/Mod/Draft/draftobjects/pointarray.py +++ b/src/Mod/Draft/draftobjects/pointarray.py @@ -105,12 +105,19 @@ class PointArray(DraftLink): def execute(self, obj): """Run when the object is created or recomputed.""" + if self.props_changed_placement_only() \ + or not obj.Base \ + or not obj.PointObject: + self.props_changed_clear() + return pt_list = get_point_list(obj.PointObject) obj.Count = len(pt_list) pls = build_placements(obj.Base, pt_list, obj.ExtraPlacement) - return super(PointArray, self).buildShape(obj, obj.Placement, pls) + self.buildShape(obj, obj.Placement, pls) + self.props_changed_clear() + return (not self.use_link) def onDocumentRestored(self, obj): """Execute code when the document is restored. @@ -134,7 +141,7 @@ class PointArray(DraftLink): self.set_properties(obj) self.migrate_properties_0v19(obj) - return super(PointArray, self).onDocumentRestored(obj) + super(PointArray, self).onDocumentRestored(obj) def migrate_properties_0v19(self, obj): """Migrate properties.""" diff --git a/src/Mod/Draft/draftobjects/polygon.py b/src/Mod/Draft/draftobjects/polygon.py index a83ddbae70..dec98b1ef5 100644 --- a/src/Mod/Draft/draftobjects/polygon.py +++ b/src/Mod/Draft/draftobjects/polygon.py @@ -77,6 +77,11 @@ class Polygon(DraftObject): obj.Radius = 1 def execute(self, obj): + if self.props_changed_placement_only(): + obj.positionBySupport() + self.props_changed_clear() + return + if (obj.FacesNumber >= 3) and (obj.Radius.Value > 0): import Part plm = obj.Placement @@ -115,6 +120,10 @@ class Polygon(DraftObject): obj.Area = shape.Area obj.Placement = plm obj.positionBySupport() + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/rectangle.py b/src/Mod/Draft/draftobjects/rectangle.py index d0db0ea0cd..4fc83fcd90 100644 --- a/src/Mod/Draft/draftobjects/rectangle.py +++ b/src/Mod/Draft/draftobjects/rectangle.py @@ -74,6 +74,11 @@ class Rectangle(DraftObject): def execute(self, obj): """This method is run when the object is created or recomputed.""" + if self.props_changed_placement_only(): + obj.positionBySupport() + self.props_changed_clear() + return + import Part if (obj.Length.Value == 0) or (obj.Height.Value == 0): @@ -164,8 +169,11 @@ class Rectangle(DraftObject): obj.Area = shape.Area obj.Placement = plm - obj.positionBySupport() + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/shape2dview.py b/src/Mod/Draft/draftobjects/shape2dview.py index b02f8c3370..57137dc1ec 100644 --- a/src/Mod/Draft/draftobjects/shape2dview.py +++ b/src/Mod/Draft/draftobjects/shape2dview.py @@ -193,12 +193,14 @@ class Shape2DView(DraftObject): objs = [o for o in objs if not(o.Name in obj.ExclusionNames)] return objs - def execute(self,obj): + def execute(self, obj): + if self.props_changed_placement_only() \ + or not getattr(obj, "AutoUpdate", True): + obj.positionBySupport() + self.props_changed_clear() + return - if not getattr(obj,"AutoUpdate", True): - return True import Part, DraftGeomUtils - obj.positionBySupport() pl = obj.Placement if obj.Base: if utils.get_type(obj.Base) in ["BuildingPart","SectionPlane"]: @@ -352,8 +354,13 @@ class Shape2DView(DraftObject): obj.Shape = Part.makeCompound(views) else: App.Console.PrintWarning(obj.ProjectionMode+" mode not implemented\n") - if not DraftGeomUtils.isNull(pl): - obj.Placement = pl + + obj.Placement = pl + obj.positionBySupport() + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/draftobjects/shapestring.py b/src/Mod/Draft/draftobjects/shapestring.py index fa157e1cf3..1ede777253 100644 --- a/src/Mod/Draft/draftobjects/shapestring.py +++ b/src/Mod/Draft/draftobjects/shapestring.py @@ -58,6 +58,11 @@ class ShapeString(DraftObject): obj.addProperty("App::PropertyBool", "MakeFace", "Draft", _tip).MakeFace = True def execute(self, obj): + if self.props_changed_placement_only(): + obj.positionBySupport() + self.props_changed_clear() + return + import Part # import OpenSCAD2Dgeom if obj.String and obj.FontFile: @@ -109,6 +114,10 @@ class ShapeString(DraftObject): if plm: obj.Placement = plm obj.positionBySupport() + self.props_changed_clear() + + def onChanged(self, obj, prop): + self.props_changed_store(prop) def makeFaces(self, wireChar): import Part diff --git a/src/Mod/Draft/draftobjects/wire.py b/src/Mod/Draft/draftobjects/wire.py index bc7c33c922..1b5c7b30d9 100644 --- a/src/Mod/Draft/draftobjects/wire.py +++ b/src/Mod/Draft/draftobjects/wire.py @@ -96,6 +96,12 @@ class Wire(DraftObject): obj.Closed = False def execute(self, obj): + if self.props_changed_placement_only(): + obj.positionBySupport() + self.update_start_end(obj) + self.props_changed_clear() + return + import Part plm = obj.Placement if obj.Base and (not obj.Tool): @@ -195,15 +201,19 @@ class Wire(DraftObject): obj.Placement = plm obj.positionBySupport() - self.onChanged(obj,"Placement") + self.update_start_end(obj) + self.props_changed_clear() def onChanged(self, obj, prop): + self.props_changed_store(prop) + tol = 1e-7 + if prop == "Start": pts = obj.Points invpl = App.Placement(obj.Placement).inverse() realfpstart = invpl.multVec(obj.Start) if pts: - if pts[0] != realfpstart: + if not pts[0].isEqual(realfpstart, tol): pts[0] = realfpstart obj.Points = pts @@ -212,29 +222,31 @@ class Wire(DraftObject): invpl = App.Placement(obj.Placement).inverse() realfpend = invpl.multVec(obj.End) if len(pts) > 1: - if pts[-1] != realfpend: + if not pts[-1].isEqual(realfpend, tol): pts[-1] = realfpend obj.Points = pts elif prop == "Length": if (len(obj.Points) == 2 - and obj.Length.Value > 1e-7 + and obj.Length.Value > tol and obj.Shape and (not obj.Shape.isNull()) - and obj.Length.Value != obj.Shape.Length): + and abs(obj.Length.Value - obj.Shape.Length) > tol): v = obj.Points[-1].sub(obj.Points[0]) v = DraftVecUtils.scaleTo(v, obj.Length.Value) obj.Points = [obj.Points[0], obj.Points[0].add(v)] - elif prop == "Placement": - pl = App.Placement(obj.Placement) - if len(obj.Points) >= 2: - displayfpstart = pl.multVec(obj.Points[0]) - displayfpend = pl.multVec(obj.Points[-1]) - if obj.Start != displayfpstart: - obj.Start = displayfpstart - if obj.End != displayfpend: - obj.End = displayfpend + def update_start_end(self, obj): + tol = 1e-7 + + pl = App.Placement(obj.Placement) + if len(obj.Points) > 1: + displayfpstart = pl.multVec(obj.Points[0]) + displayfpend = pl.multVec(obj.Points[-1]) + if not obj.Start.isEqual(displayfpstart, tol): + obj.Start = displayfpstart + if not obj.End.isEqual(displayfpend, tol): + obj.End = displayfpend # Alias for compatibility with v0.18 and earlier diff --git a/src/Mod/Draft/drafttaskpanels/task_shapestring.py b/src/Mod/Draft/drafttaskpanels/task_shapestring.py index 618c1881d1..e2097fdf56 100644 --- a/src/Mod/Draft/drafttaskpanels/task_shapestring.py +++ b/src/Mod/Draft/drafttaskpanels/task_shapestring.py @@ -170,7 +170,6 @@ class ShapeStringTaskPanelCmd(ShapeStringTaskPanel): y = App.Units.Quantity(self.form.sbY.text()).Value z = App.Units.Quantity(self.form.sbZ.text()).Value ssBase = App.Vector(x, y, z) - # this try block is almost identical to the one in DraftTools try: qr, sup, points, fil = self.sourceCmd.getStrings() Gui.addModule("Draft") @@ -181,7 +180,8 @@ class ShapeStringTaskPanelCmd(ShapeStringTaskPanel): 'plm.Rotation.Q=' + qr, 'ss.Placement=plm', 'ss.Support=' + sup, - 'Draft.autogroup(ss)']) + 'Draft.autogroup(ss)', + 'FreeCAD.ActiveDocument.recompute()']) except Exception: _err("Draft_ShapeString: error delaying commit\n")