Skip to content

Plug : Fix bad interaction between addChild() and reorderChildren()#7014

Merged
murraystevenson merged 1 commit into
GafferHQ:mainfrom
johnhaddon:catalogueDuplicateFix
Jul 9, 2026
Merged

Plug : Fix bad interaction between addChild() and reorderChildren()#7014
murraystevenson merged 1 commit into
GafferHQ:mainfrom
johnhaddon:catalogueDuplicateFix

Conversation

@johnhaddon

@johnhaddon johnhaddon commented Jul 9, 2026

Copy link
Copy Markdown
Member

Plug::parentChanging() and Plug::childrenReordered() both need to do work to mirror the changes onto their output plugs, so that changes to promoted plugs are reflected on the internal plugs. Likewise, they both need to avoid doubling-up this work during undo/redo, because by default the undo system will have recorded the mirroring and it won't need doing a second time.

parentChanging() avoided the doubling by checking ScriptNode::actionStage(), which is what we do generally in other spots. But childrenReordered() was taking a different approach : using UndoScope( Disabled ) to prevent the mirroring being recorded in the undo queue, and just doing the work itself every time. I actually think I prefer this latter approach, because it avoids unnecessary bloat in the undo queue. But it was the cause of a bug when adding a child and reordering in the same UndoScope.

The issue was that when UndoScope( Disabled ) closes, it calls ScriptNode::popUndoScope(). When we're in undo(), that causes ScriptNode to set m_actionStage to Invalid, which in turn means that parentChanging() will double up on the work. Which leads to two attempts to remove a child, with the second one failing because it has already been removed.

Longer term I think it's worth investigating making UndoScope( Disabled ) work better for this situation, and moving more code to use it. Or possibly even doing it all magically, by having ScriptNode not record actions that occur while an outer action is running. But for the short term the safest fix is to bring childrenReordered() into line with all our other methods that modify the graph in response to signals.

@johnhaddon johnhaddon self-assigned this Jul 9, 2026
@github-project-automation github-project-automation Bot moved this to Pending Review in Work in Progress Jul 9, 2026
@johnhaddon johnhaddon force-pushed the catalogueDuplicateFix branch from 146ede6 to fd3926b Compare July 9, 2026 11:22
`Plug::parentChanging()` and `Plug::childrenReordered()` both need to do work to mirror the changes onto their output plugs, so that changes to promoted plugs are reflected on the internal plugs. Likewise, they both need to avoid doubling-up this work during undo/redo, because by default the undo system will have recorded the mirroring and it won't need doing a second time.

`parentChanging()` avoided the doubling by checking `ScriptNode::actionStage()`, which is what we do generally in other spots. But `childrenReordered()` was taking a different approach : using `UndoScope( Disabled )` to prevent the mirroring being recorded in the undo queue, and just doing the work itself every time. I actually think I prefer this latter approach, because it avoids unnecessary bloat in the undo queue. But it was the cause of a bug when adding a child and reordering in the same UndoScope.

The issue was that when `UndoScope( Disabled )` closes, it calls `ScriptNode::popUndoScope()`. When we're in `undo()`, that causes ScriptNode to set `m_actionStage` to `Invalid`, which in turn means that `parentChanging()` will double up on the work. Which leads to _two_ attempts to remove a child, with the second one failing because it has already been removed.

Longer term I think it's worth investigating making `UndoScope( Disabled )` work better for this situation, and moving more code to use it. Or possibly even doing it all magically, by having ScriptNode not record actions that occur while an outer action is running. But for the short term the safest fix is to bring `childrenReordered()` into line with all our other methods that modify the graph in response to signals.
@murraystevenson murraystevenson force-pushed the catalogueDuplicateFix branch from fd3926b to eaa07b0 Compare July 9, 2026 17:52

@murraystevenson murraystevenson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks John. LGTM. I've rebased this to fix the Changes.md merge conflict.

@murraystevenson murraystevenson merged commit 9740e8e into GafferHQ:main Jul 9, 2026
6 of 7 checks passed
@github-project-automation github-project-automation Bot moved this from Pending Review to Pending release in Work in Progress Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Pending release

Development

Successfully merging this pull request may close these issues.

2 participants