From 4696f2b0481daf646783ee0a00102b3197f58a6a Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Fri, 27 Feb 2026 17:04:43 -0800 Subject: [PATCH 1/2] PlugLayout : Fix error when accessory metadata removed from widgets --- Changes.md | 5 +++++ python/GafferUI/PlugLayout.py | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/Changes.md b/Changes.md index 03df03588a..fe9df7c866 100644 --- a/Changes.md +++ b/Changes.md @@ -10,6 +10,11 @@ Improvements - PlugPopup : Improved default popup title. Plugs and non-viewable nodes are no longer included in the title. - Viewer : Added D hotkey for toggling between denoised and undenoised layers. +Fixes +----- + +- PlugLayout : Fixed `Internal C++ object already deleted` errors when removing "layout:accessory" metadata from plugs currently visible in the Node Editor. + API --- diff --git a/python/GafferUI/PlugLayout.py b/python/GafferUI/PlugLayout.py index b387060236..e75d4b1e11 100644 --- a/python/GafferUI/PlugLayout.py +++ b/python/GafferUI/PlugLayout.py @@ -338,6 +338,12 @@ def __updateLayout( self ) : row.append( widget ) section.widgets[-1] = row else : + parent = widget.parent() + if isinstance( parent, _AccessoryRow ) : + # Widget is no longer an accessory or no longer has an accessory, reparent to + # grandparent to prevent the widget from being deleted with the old _AccessoryRow. + parent.parent().addChild( widget ) + section.widgets.append( widget ) if self.__itemMetadataValue( item, "divider" ) : From d848e63571ae5e97b7d87498bbd3ebd48d6cabd8 Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Fri, 27 Feb 2026 17:04:52 -0800 Subject: [PATCH 2/2] PlugLayout : Prevent dividers from being included in _AccessoryRow Otherwise a plug with "accessory" metadata following a plug with "divider" metadata resulted in the Divider and the accessory plug being put into an _AccessoryRow below the primary plug. This change groups the primary plug and its accessory in an _AccessoryRow, with the Divider below. Dividers aren't deduplicated, so if both the primary plug and the accessory have divider metadata, two Dividers will be created. --- Changes.md | 4 +++- python/GafferUI/PlugLayout.py | 14 ++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Changes.md b/Changes.md index fe9df7c866..a38e94baf2 100644 --- a/Changes.md +++ b/Changes.md @@ -13,7 +13,9 @@ Improvements Fixes ----- -- PlugLayout : Fixed `Internal C++ object already deleted` errors when removing "layout:accessory" metadata from plugs currently visible in the Node Editor. +- PlugLayout : + - Fixed `Internal C++ object already deleted` errors when removing "layout:accessory" metadata from plugs currently visible in the Node Editor. + - Fixed layout issues when combining "layout:divider" and "layout:accessory" metadata. API --- diff --git a/python/GafferUI/PlugLayout.py b/python/GafferUI/PlugLayout.py index e75d4b1e11..3b4eabbb27 100644 --- a/python/GafferUI/PlugLayout.py +++ b/python/GafferUI/PlugLayout.py @@ -330,13 +330,19 @@ def __updateLayout( self ) : section = section.subsection( sectionName ) if len( section.widgets ) and self.__itemMetadataValue( item, "accessory" ) : - if isinstance( section.widgets[-1], _AccessoryRow ) : - section.widgets[-1].append( widget ) + primaryIndex = -1 + for i in range( len( section.widgets ) - 1, -1, -1 ) : + if not isinstance( section.widgets[i], GafferUI.Divider ) : + primaryIndex = i + break + + if isinstance( section.widgets[primaryIndex], _AccessoryRow ) : + section.widgets[primaryIndex].append( widget ) else : row = _AccessoryRow() - row.append( section.widgets[-1] ) + row.append( section.widgets[primaryIndex] ) row.append( widget ) - section.widgets[-1] = row + section.widgets[primaryIndex] = row else : parent = widget.parent() if isinstance( parent, _AccessoryRow ) :