GafferHQ / gaffer

Gaffer is a node-based application for lookdev, lighting and automation
http://www.gafferhq.org
BSD 3-Clause "New" or "Revised" License
960 stars 206 forks source link

Expression broken when source plug is in a nested node whose parent is deleted #3461

Closed ivanimanishi closed 4 years ago

ivanimanishi commented 4 years ago

Version: Gaffer 0.54.2.1-linux Third-party tools: None Third-party modules: None

Description

Expressions reading a plug value from a node (A) inside another node (B), are left in a broken state if you delete (A), where they still try to read the deleted plug value.

Steps to reproduce

  1. Create a Box, and a node inside the box
  2. At the top level, create an expression that reads some plug from the node inside the box
  3. Then delete the box and try to view (or serialise) the expression.

Here is an example graph you can use. Try deleting the "Box", then clicking on the expression node.

Example

``` import Gaffer import GafferImage import GafferScene import IECore import imath Gaffer.Metadata.registerValue( parent, "serialiser:milestoneVersion", 0, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:majorVersion", 54, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:minorVersion", 2, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:patchVersion", 1, persistent=False ) __children = {} __children["Box"] = Gaffer.Box( "Box" ) parent.addChild( __children["Box"] ) __children["Box"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Box"].addChild( Gaffer.ContextVariables( "ContextVariables" ) ) __children["Box"]["ContextVariables"].setup( GafferScene.ScenePlug( "in", ) ) __children["Box"]["ContextVariables"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Box"].addChild( GafferScene.Sphere( "Sphere" ) ) __children["Box"]["Sphere"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Text"] = GafferImage.Text( "Text" ) parent.addChild( __children["Text"] ) __children["Text"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Expression"] = Gaffer.Expression( "Expression" ) parent.addChild( __children["Expression"] ) __children["Expression"]["__in"].addChild( Gaffer.StringPlug( "p0", defaultValue = 'sphere', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Expression"]["__out"].addChild( Gaffer.StringPlug( "p0", direction = Gaffer.Plug.Direction.Out, defaultValue = 'Hello World', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Expression"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Box"]["__uiPosition"].setValue( imath.V2f( 7.30611849, 5.37886429 ) ) Gaffer.Metadata.registerValue( __children["Box"]["ContextVariables"]["in"], 'noduleLayout:section', 'top' ) Gaffer.Metadata.registerValue( __children["Box"]["ContextVariables"]["out"], 'noduleLayout:section', 'bottom' ) __children["Box"]["ContextVariables"]["__uiPosition"].setValue( imath.V2f( 26.8999977, -1.10000002 ) ) __children["Box"]["Sphere"]["__uiPosition"].setValue( imath.V2f( 39.9879379, -1.50000131 ) ) __children["Text"]["out"].setInput( __children["Text"]["__merge"]["out"] ) __children["Text"]["text"].setInput( __children["Expression"]["__out"]["p0"] ) __children["Text"]["area"].setValue( imath.Box2i( imath.V2i( 0, 0 ), imath.V2i( 2444, 1798 ) ) ) __children["Text"]["__uiPosition"].setValue( imath.V2f( 7.3726716, 12.8995705 ) ) __children["Expression"]["__in"]["p0"].setInput( __children["Box"]["Sphere"]["name"] ) __children["Expression"]["__uiPosition"].setValue( imath.V2f( -1.27267027, 12.9652576 ) ) __children["Expression"]["__engine"].setValue( 'python' ) __children["Expression"]["__expression"].setValue( 'var = parent["__in"]["p0"]\nparent["__out"]["p0"] = repr(var)\n' ) del __children ```

Debug log

Click to Expand

``` Traceback (most recent call last): File "/software/apps/gaffer/0.54.2.1/cent7.x86_64/cortex/10/gaffer/python/GafferUI/Widget.py", line 937, in eventFilter self.__showHide( qObject, qEvent ) File "/software/apps/gaffer/0.54.2.1/cent7.x86_64/cortex/10/gaffer/python/GafferUI/Widget.py", line 1004, in __showHide widget._visibilityChangedSignal( widget ) IECore.Exception: Object "ScriptNode" is not an ancestor of "name". ```

johnhaddon commented 4 years ago

Thanks for the simple repro Ivan. I'm inclined to close as "won't fix" for the following reasons :

Let me know if you want to make the case for fixing it instead.

ivanimanishi commented 4 years ago

Yes. We can work around the issue.