From 21e7fa1e8b138e7661d49ca4a4010caf0ceb24ae Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Thu, 1 Jan 2026 14:01:34 +0100 Subject: [PATCH 1/2] Draft: fix regression in Pattern display (add find_coin_node_by_name function) Adapted existing code attribution and added a new function to find a node by name. --- src/Mod/Draft/draftutils/gui_utils.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Mod/Draft/draftutils/gui_utils.py b/src/Mod/Draft/draftutils/gui_utils.py index d0010e3132..c4255a2911 100644 --- a/src/Mod/Draft/draftutils/gui_utils.py +++ b/src/Mod/Draft/draftutils/gui_utils.py @@ -939,14 +939,25 @@ def get_bbox(obj, debug=False): return App.BoundBox(xmin, ymin, zmin, xmax, ymax, zmax) -# Code by Yorik van Havre. +# Code by Yorik van Havre (adapted). def find_coin_node(parent, nodetype): + if not hasattr(parent, "getNumChildren"): + return None for i in range(parent.getNumChildren()): if isinstance(parent.getChild(i), nodetype): return parent.getChild(i) return None +def find_coin_node_by_name(parent, name): + if not hasattr(parent, "getNumChildren"): + return None + for i in range(parent.getNumChildren()): + if parent.getChild(i).getName() == name: + return parent.getChild(i) + return None + + # Code by Chris Hennes (chennes). # See https://forum.freecad.org/viewtopic.php?p=656362#p656362. # Used to fix https://github.com/FreeCAD/FreeCAD/issues/10469. From 34441b810125dd92fe23ed608c81f69b59682969 Mon Sep 17 00:00:00 2001 From: Roy-043 <70520633+Roy-043@users.noreply.github.com> Date: Thu, 1 Jan 2026 14:04:27 +0100 Subject: [PATCH 2/2] Draft: fix regression in Pattern display (Refactor texture handling in view_base.py) --- src/Mod/Draft/draftviewproviders/view_base.py | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/Mod/Draft/draftviewproviders/view_base.py b/src/Mod/Draft/draftviewproviders/view_base.py index 71774c49a7..6808858df5 100644 --- a/src/Mod/Draft/draftviewproviders/view_base.py +++ b/src/Mod/Draft/draftviewproviders/view_base.py @@ -283,52 +283,52 @@ class ViewProviderDraft(object): """ # treatment of patterns and image textures if prop in ("TextureImage", "Pattern", "ShapeAppearance"): - if hasattr(self.Object, "Shape"): - if self.Object.Shape.Faces: - path = None - if hasattr(vobj, "TextureImage"): - if vobj.TextureImage: - path = vobj.TextureImage - if not path: - if hasattr(vobj, "Pattern"): - if str(vobj.Pattern) in utils.svg_patterns(): - path = utils.svg_patterns()[vobj.Pattern][1] - else: - path = "None" - if path and vobj.RootNode: - switch = gui_utils.find_coin_node(vobj.RootNode, coin.SoSwitch) - if switch is not None: - if switch.getChildren().getLength() > 0: - innodes = switch.getChild(0).getChildren().getLength() - if innodes > 2: - r = switch.getChild(0).getChild(innodes - 1) - i = QtCore.QFileInfo(path) - if self.texture: - r.removeChild(self.texture) - self.texture = None - if self.texcoords: - r.removeChild(self.texcoords) - self.texcoords = None - if i.exists(): - size = None - if ".SVG" in path.upper(): - size = params.get_param("HatchPatternResolution") - if not size: - size = 128 - im = gui_utils.load_texture(path, size) - if im: - self.texture = coin.SoTexture2() - self.texture.image = im - r.insertChild(self.texture, 1) - if size: - s = 1 - if hasattr(vobj, "PatternSize"): - if vobj.PatternSize: - s = vobj.PatternSize - self.texcoords = coin.SoTextureCoordinatePlane() - self.texcoords.directionS.setValue(s, 0, 0) - self.texcoords.directionT.setValue(0, s, 0) - r.insertChild(self.texcoords, 2) + if hasattr(self.Object, "Shape") and self.Object.Shape.Faces: + path = None + if hasattr(vobj, "TextureImage"): + if vobj.TextureImage: + path = vobj.TextureImage + if not path: + if hasattr(vobj, "Pattern"): + if str(vobj.Pattern) in utils.svg_patterns(): + path = utils.svg_patterns()[vobj.Pattern][1] + else: + path = "None" + if path and vobj.RootNode: + switch = gui_utils.find_coin_node(vobj.RootNode, coin.SoSwitch) + if switch is not None and switch.getChildren().getLength() > 0: + flat_lines_node = switch.getChild(0) + # Get the Shaded sub-node of the Flat Lines node. The name in + # Std_SceneInspector is "Shaded", but the actual name is "FlatRoot") + shaded_node = gui_utils.find_coin_node_by_name(flat_lines_node, "FlatRoot") + if shaded_node is not None: + i = QtCore.QFileInfo(path) + if self.texture: + shaded_node.removeChild(self.texture) + self.texture = None + if self.texcoords: + shaded_node.removeChild(self.texcoords) + self.texcoords = None + if i.exists(): + size = None + if ".SVG" in path.upper(): + size = params.get_param("HatchPatternResolution") + if not size: + size = 128 + im = gui_utils.load_texture(path, size) + if im: + self.texture = coin.SoTexture2() + self.texture.image = im + shaded_node.insertChild(self.texture, 1) + if size: + s = 1 + if hasattr(vobj, "PatternSize"): + if vobj.PatternSize: + s = vobj.PatternSize + self.texcoords = coin.SoTextureCoordinatePlane() + self.texcoords.directionS.setValue(s, 0, 0) + self.texcoords.directionT.setValue(0, s, 0) + shaded_node.insertChild(self.texcoords, 2) elif prop == "PatternSize": if hasattr(self, "texcoords"): if self.texcoords: