From 4bb951490c0280e229ae5c4f033e5c802fea5fe3 Mon Sep 17 00:00:00 2001 From: BramVR Date: Thu, 12 Mar 2026 20:52:21 +0100 Subject: [PATCH 1/3] Fix cmds.controller segfault in get_all_tag_children on Maya 2025 cmds.controller(query=True, children=True) causes a C++ segfault in Maya 2025 when traversing certain controller tag nodes. This crashes Maya with no Python traceback, making it uncatchable by try/except. Replace cmds.controller with direct cmds.listConnections traversal of the controller tag .children and .controllerObject attributes. Also adds a seen_tags set to prevent infinite loops from circular tag references. --- release/scripts/mgear/core/pickWalk.py | 45 ++++++++++++++++++-------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/release/scripts/mgear/core/pickWalk.py b/release/scripts/mgear/core/pickWalk.py index c5a37e87..ff7f2581 100644 --- a/release/scripts/mgear/core/pickWalk.py +++ b/release/scripts/mgear/core/pickWalk.py @@ -14,6 +14,10 @@ def get_all_tag_children(node): """Gets all child tag controls from the given tag node + Traverses controller tag hierarchy using listConnections instead of + cmds.controller, which can segfault in Maya 2025 on certain + controller tag nodes. + Args: node (str): Name of controller object with tag @@ -21,22 +25,35 @@ def get_all_tag_children(node): list: List of child controls (Maya transform nodes) """ - # store child nodes children = [] - # gets first child control - child = cmds.controller(node, query=True, children=True) - - # loop on child controller nodes to get all children - while child is not None: - children.extend(child) - tags = [] - for c in child: - tag = cmds.ls(cmds.listConnections(c, type="controller")) - tags.extend(tag) - if cmds.listConnections("{}.parent".format(tag[0])) == node: - return children - child = cmds.controller(tags, query=True, children=True) + tags = cmds.ls(cmds.listConnections(node, type="controller")) + if not tags: + return children + + current_tags = tags + seen_tags = set() + while current_tags: + next_tags = [] + for tag in current_tags: + if tag in seen_tags: + continue + seen_tags.add(tag) + child_tags = cmds.listConnections( + "{}.children".format(tag), type="controller" + ) + if not child_tags: + continue + for ct in child_tags: + if ct in seen_tags: + continue + ctl = cmds.listConnections( + "{}.controllerObject".format(ct) + ) + if ctl: + children.extend(ctl) + next_tags.append(ct) + current_tags = next_tags return children From d65dbf1a07849948840b0ac5c2cc2b09eccbce2a Mon Sep 17 00:00:00 2001 From: BramVR Date: Thu, 12 Mar 2026 20:52:46 +0100 Subject: [PATCH 2/3] Fix false positive attribute matching in dagmenu space-switch menu _get_switch_node_attrs matches any keyable user-defined attribute ending with "ref" or "follow", but does not check attribute type. String attributes like guide_loc_ref match and cause downstream errors when the menu builder calls enumName on a non-enum attribute, resulting in a NoneType.split(":") crash. Add attribute type filter to skip string/typed attributes, and add a null guard on the enumName query result before calling .split(":"). --- release/scripts/mgear/core/dagmenu.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/release/scripts/mgear/core/dagmenu.py b/release/scripts/mgear/core/dagmenu.py index 4786ddfe..d74cfbdf 100644 --- a/release/scripts/mgear/core/dagmenu.py +++ b/release/scripts/mgear/core/dagmenu.py @@ -185,6 +185,12 @@ def _get_switch_node_attrs(node, end_string): "{}.{}".format(node, attr), query=True, usedAsProxy=True ): continue + # Skip string attributes — switch/blend attrs are enum or numeric + attr_type = cmds.attributeQuery( + attr, node=node, attributeType=True + ) + if attr_type in ("string", "typed"): + continue attrs.append(attr) return attrs @@ -1136,9 +1142,13 @@ def add_menu_items(attrs, attr_extension="_blend"): image="dynamicConstraint.svg", ) cmds.radioMenuItemCollection(parent=_p_switch_menu) - k_values = cmds.addAttr( + enum_name = cmds.addAttr( "{}.{}".format(uih, attr), query=True, enumName=True - ).split(":") + ) + if not enum_name: + cmds.deleteUI(_p_switch_menu) + continue + k_values = enum_name.split(":") current_state = cmds.getAttr("{}.{}".format(uih, attr)) combo_box = QtWidgets.QComboBox() From 98348774357d7f49c69e86a01fe64645656ea8fc Mon Sep 17 00:00:00 2001 From: BramVR Date: Thu, 12 Mar 2026 21:00:29 +0100 Subject: [PATCH 3/3] Mark child tags as seen at enqueue time to prevent duplicates If the same child tag is connected from multiple parent tags, it could be queued and processed multiple times. Mark it as seen immediately when encountered instead of only when processed. --- release/scripts/mgear/core/pickWalk.py | 1 + 1 file changed, 1 insertion(+) diff --git a/release/scripts/mgear/core/pickWalk.py b/release/scripts/mgear/core/pickWalk.py index ff7f2581..7ca01bfd 100644 --- a/release/scripts/mgear/core/pickWalk.py +++ b/release/scripts/mgear/core/pickWalk.py @@ -47,6 +47,7 @@ def get_all_tag_children(node): for ct in child_tags: if ct in seen_tags: continue + seen_tags.add(ct) ctl = cmds.listConnections( "{}.controllerObject".format(ct) )