Draft: fix props_changed_placement_only for attached clones and similar (#9623)

For an attached object whose Shape depends on one or more source objects props_changed_placement_only should always return False.
This commit is contained in:
Roy-043
2023-05-21 16:15:55 +02:00
committed by GitHub
parent 864f99bf98
commit 52b41fee06
12 changed files with 56 additions and 11 deletions

View File

@@ -396,7 +396,7 @@ class Array(DraftLink):
def execute(self, obj):
"""Execute when the object is created or recomputed."""
if self.props_changed_placement_only() \
if self.props_changed_placement_only(obj) \
or not obj.Base:
self.props_changed_clear()
return

View File

@@ -182,12 +182,34 @@ class DraftObject(object):
if hasattr(self, "props_changed"):
delattr(self, "props_changed")
def props_changed_placement_only(self):
def props_changed_placement_only(self, obj=None):
"""Return `True` if the self.props_changed list, after removing `Shape`
and `_LinkTouched` items, only contains `Placement` items.
Parameters
----------
obj : the scripted object. Need only be supplied if the Shape of obj
is, or can be, derived from other objects.
"""
if not hasattr(self, "props_changed"):
return False
# For an attached object whose Shape depends on one or more source
# objects the situation can occur that when those source objects
# change its Placement is also changed, but for no apparent reason:
# the new Placement is identical to the old. For such an object a
# `placement_only` change cannot be detected reliably and therefore
# this function should return `False`.
# https://github.com/FreeCAD/FreeCAD/issues/8771
if obj is not None \
and obj.OutList \
and hasattr(obj, "Support") \
and hasattr(obj, "MapMode") \
and obj.Support \
and obj.MapMode != "Deactivated":
return False
props = set(self.props_changed)
if "Shape" in props:
props.remove("Shape")

View File

@@ -43,7 +43,7 @@ class Block(DraftObject):
obj.addProperty("App::PropertyLinkList","Components", "Draft", _tip)
def execute(self, obj):
if self.props_changed_placement_only():
if self.props_changed_placement_only(obj):
obj.positionBySupport()
self.props_changed_clear()
return

View File

@@ -86,7 +86,7 @@ class Clone(DraftObject):
return Part.makeCompound(shapes)
def execute(self,obj):
if self.props_changed_placement_only():
if self.props_changed_placement_only(obj):
if hasattr(obj,"positionBySupport"):
obj.positionBySupport()
self.props_changed_clear()

View File

@@ -59,7 +59,7 @@ class Facebinder(DraftObject):
obj.setEditorMode("Area",1)
def execute(self,obj):
if self.props_changed_placement_only():
if self.props_changed_placement_only(obj):
self.props_changed_clear()
return

View File

@@ -77,7 +77,7 @@ class Hatch(DraftObject):
def execute(self,obj):
if self.props_changed_placement_only() \
if self.props_changed_placement_only(obj) \
or not obj.Base \
or not obj.File \
or not obj.Pattern \

View File

@@ -296,7 +296,7 @@ class PathArray(DraftLink):
def execute(self, obj):
"""Execute when the object is created or recomputed."""
if self.props_changed_placement_only() \
if self.props_changed_placement_only(obj) \
or not obj.Base \
or not obj.PathObject:
self.props_changed_clear()

View File

@@ -130,7 +130,7 @@ class PathTwistedArray(DraftLink):
def execute(self, obj):
"""Execute when the object is created or recomputed."""
if self.props_changed_placement_only() \
if self.props_changed_placement_only(obj) \
or not obj.Base \
or not obj.PathObject:
self.props_changed_clear()

View File

@@ -105,7 +105,7 @@ class PointArray(DraftLink):
def execute(self, obj):
"""Run when the object is created or recomputed."""
if self.props_changed_placement_only() \
if self.props_changed_placement_only(obj) \
or not obj.Base \
or not obj.PointObject:
self.props_changed_clear()

View File

@@ -196,7 +196,7 @@ class Shape2DView(DraftObject):
return objs
def execute(self, obj):
if self.props_changed_placement_only() \
if self.props_changed_placement_only(obj) \
or not getattr(obj, "AutoUpdate", True):
obj.positionBySupport()
self.props_changed_clear()

View File

@@ -96,7 +96,7 @@ class Wire(DraftObject):
obj.Closed = False
def execute(self, obj):
if self.props_changed_placement_only():
if self.props_changed_placement_only(obj): # Supplying obj is required because of `Base` and `Tool`.
obj.positionBySupport()
self.update_start_end(obj)
self.props_changed_clear()

View File

@@ -573,6 +573,29 @@ class DraftModification(unittest.TestCase):
self.assertTrue(obj.hasExtension("Part::AttachExtension"),
"'{}' failed".format(operation))
def test_attached_clone_behavior(self):
"""Check if an attached clone behaves correctly.
Test for https://github.com/FreeCAD/FreeCAD/issues/8771.
"""
operation = "Check attached Draft Clone behavior"
_msg(" Test '{}'".format(operation))
box1 = App.ActiveDocument.addObject("Part::Box")
box1.Length = 10
box2 = App.ActiveDocument.addObject("Part::Box")
App.ActiveDocument.recompute()
obj = Draft.make_clone(box1)
obj.MapMode = "ObjectXY"
obj.Support = [(box2, ("",))]
App.ActiveDocument.recompute()
box1.Length = 1
App.ActiveDocument.recompute()
self.assertTrue(obj.Shape.BoundBox.XLength == 1, "'{}' failed".format(operation))
def test_draft_to_techdraw(self):
"""Create a solid, and then a DraftView on a TechDraw page."""
operation = "TechDraw DraftView (relies on Draft code)"