identify box node on import

191 views
Skip to first unread message

Robert Kolbeins

unread,
Oct 19, 2023, 11:49:22 AM10/19/23
to gaffer-dev
atm I'm only able to identify Box node by it's name on import.  If I add metadata or string plug as a tag and try to query I just get empty lists.   I get the user plug only but not sure what todo,  any solution out there?
thanks,
Robert

----------------------------------
def on_node_created(script,node):

    print(node['user'].children())


def add_node_child_callback(container, script):

    script.childAddedSignal().connect(on_node_created, scoped=False)

application.root()['scripts'].childAddedSignal().connect(add_node_child_callback,scoped=False)

John Haddon

unread,
Oct 20, 2023, 4:08:54 AM10/20/23
to gaffe...@googlegroups.com
Hi Robert,
Using metadata to categorise these special boxes seems like a reasonable approach, and I can't see any reason it wouldn't work. Can you post a small example file with a node containing the metadata, and the Python code you're using to query it so we can help further?
Cheers...
John

--
You received this message because you are subscribed to the Google Groups "gaffer-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gaffer-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gaffer-dev/a0039a23-473b-4482-b961-72e70f7dda54n%40googlegroups.com.

Robert Kolbeins

unread,
Oct 20, 2023, 4:58:04 AM10/20/23
to gaffe...@googlegroups.com
Hi John
Thank you for your reply.

I attach a simple scene that has a box with metadata applied by running this in script editor:


node = root['Box']

Gaffer.Metadata.registerValue( node, "Foo", "Foobar" )


Checking with this print and I see it in the list

print(Gaffer.Metadata.registeredValues(node))



Then I chucked the nodeCreated.py script in the startup/gui to see if I get the metadata on file/import. It prints all except the one I added.


I'm sure there is a reasonable explanation why it should not be listed.


Thanks,

Robert




You received this message because you are subscribed to a topic in the Google Groups "gaffer-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/gaffer-dev/pz4VJVUVz24/unsubscribe.
To unsubscribe from this group and all its topics, send an email to gaffer-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gaffer-dev/CAB8pVgKkFnCM24Y9Uw933V0aK-kRnr4uW04z-QQ1ZfaSEHeefA%40mail.gmail.com.
BoxWithMetadata.gfr
nodeCreated.py

John Haddon

unread,
Oct 20, 2023, 7:02:11 AM10/20/23
to gaffe...@googlegroups.com
Ah, I see the problem now. If you take a look at the contents of the `BoxWithMetadata.gfr` file, you'll see that the Box is parented via `addChild()` before the metadata is registered. Your callback is run in response to `addChild()` so sees the node before it gets the metadata. Although we could change the serialisation order to fix this, that could have quite a few side effects, so it's not somewhere I really want to go.

What are these special boxes exactly, and what is it that you need to do when they're created? Back when I coded for other DCCs, I always found workflows like `on_node_created()` to be pretty fragile so I tend not to promote them in Gaffer. I wonder if a better approach might be to have your special boxes be subclasses of Box implemented in Python, so they can encapsulate their own behaviour? That would also make it much easier to deal with cases like them being pasted into nested boxes (something your callback wouldn't know about, because it's only operating on the top level). I feel like with a bit more information, we might be able to suggest a better solution...

Cheers...
John



Robert Kolbeins

unread,
Oct 20, 2023, 7:47:24 AM10/20/23
to gaffe...@googlegroups.com
Hi John
Thank you for the helpful information.
Instead of attempting to go all the way using only the Box node, I'm now exporting the box using Gaffer.ExtensionAlgo.exportExtension().  That way I can filter using node.typeName() on addChild.
However, like you said, the problem of duplicating nodes is still valid. I need the node to be aware of a root variable changing and a preset plug changing which will be the next step to try to get working inside the extension code

Many thanks,
R


John Haddon

unread,
Oct 20, 2023, 9:10:32 AM10/20/23
to gaffe...@googlegroups.com
I'm now exporting the box using Gaffer.ExtensionAlgo.exportExtension().

Now you've got your own node type, it might be useful to override `_parentChanged()` on the node itself, instead of connect to `childAdded()` on the script. You can see an example of that here :


I need the node to be aware of a root variable changing

Generally speaking we try to avoid this sort of thing in the design of Gaffer's native nodes, with the idea being that any node should work in any context at any time. There are cases where this is tricky though - what is it you're trying to do? I'm wondering if there might be a more "Gaffery" approach...

Cheers...
John

Robert Kolbeins

unread,
Oct 20, 2023, 10:17:53 AM10/20/23
to gaffe...@googlegroups.com
Thanks John
What I'm attempting to create is an all in one node image plate reader that is aware of root variable current:shotName in a multi shot setup. Then you can choose what plate type bg, roto, clean plate etc
shotName/sourceplate/bg/v001/sequence.exr
shotName/sourceplate/roto/v001/sequence.exr
shotName/sourceplate/clean/v002/sequence.exr

image.png

When switching shots, the version always goes to the latest version, but you can check the previous version.
Inside the box there is an expression that compiles the shotName/sourceplate path that gets fed into a function that generates version dictionary fed into plug preset
It works as long as you don't duplicate the node so the rule is import new one to get the signal, but ultimately I need to learn how to work with plug signals after using the Gaffer.ExtensionAlgo.exportExtension()

Cheers,
R



John Haddon

unread,
Oct 20, 2023, 10:47:37 AM10/20/23
to gaffe...@googlegroups.com
Now you've got your own node type via `exportExtension()`, I think it might be possible to do this completely dynamically on the fly, with no need for battling with signals to try to keep everything in sync :
  • You can register callback functions (rather than static values) for the `presetNames` and `presetValues` metadata, and these can return different presets in different contexts. Gaffer will automatically update the menu whenever the context changes.There's an example of that in the ColorSpace UI, where we query the available color spaces based on the OCIO transform defined in the current context : https://github.com/GafferHQ/gaffer/blob/main/python/GafferImageUI/ColorSpaceUI.py#L65-L66. The functions that calls are here : https://github.com/GafferHQ/gaffer/blob/main/python/GafferImageUI/OpenColorIOTransformUI.py#L62-L92. The particular implementation there isn't important. What is important is that you can call `Gaffer.Context.current().get( "current:shotName" )` to get the current shot, and then do whatever you want to build the result.
  • You could use a special "vLatest" version tag that the internal expression uses to dynamically choose the latest version for the current shot.
  • If users want to lock to specific versions on specific shots, they could use a Spreadsheet to map from shot name to version, with the default fallback value being "vLatest". You could even embed that spreadsheet in your node's UI if you wanted.
I'm sure I'm missing some details, but I do think this might be possible without having to do a bunch of painful state tracking and synchronisation. Our general goal in Gaffer is just to have everything react to the current context on the fly, rather than have to manually sync everything...
Cheers...
John


Robert Kolbeins

unread,
Oct 24, 2023, 5:46:18 AM10/24/23
to gaffe...@googlegroups.com
Hi John
Your suggestion worked really well.  No signals headaches :)
keeping it simple I'm always displaying the latest plate version as that should be the main version but with the option of poking into previous publish.
Gaffer Spreadsheet is the bread and butter for my multi shot setups.  I promote it to box ui and fill it with all relevant per shot info from database or csv files feeding into root context vars.
Gaffer Awesomeness!!

Many thanks,
Robert


Reply all
Reply to author
Forward
0 new messages