Custom python node derived from Name Switch

162 views
Skip to first unread message

Pablo Gimenez Pizarro

unread,
Sep 4, 2026, 3:13:54 PMSep 4
to gaffer-dev
Hello.
I'm trying to make a node to switch between shots derived from NameSwitch, at the moment is basically a NameSwitch with some buttons to integrate it better in the pipe.
so I'm playing with a custom python node that uses Gaffer.NameSwitch as it base class:
class ShotSwitch( Gaffer.NameSwitch ):
   
    def __init__( self, name = "ShotSwitch" ):
        super().__init__( name )
       
IECore.registerRunTimeTyped( ShotSwitch, typeName = "ShotSwitch" )

The Ui module is super simple:
Gaffer.Metadata.registerNode(
    ShotSwitch,
    "description", "A specialized version of the NameSwitch node for shot switching.",
    "icon", "switch.png",
    "category", "Shot",
)

And also have the menu entry part.
I can see my node in the TAB menu and create it, the name of the node is fine but the internal name of the node is still NameSwitch, and if I hover over the node it says is a NameSwitch instead of the registered node type: ShotSwitch.
I should be missing something silly ...

My final goal is to have a node that acts like the NameSwitch but with the default input been a plug on the left side and the optional + plugs on the top.
My guess is that todo that I pretty much need to start from scratch since both NameSwitch and Switch works on a single plugs array, and here I have one plug and an array of plugs, so I guess the internal logic for those nodes won't work.
But for the time been I would be happy doing a prototype based on NameSwitch, I will add some buttons to automatically add entries with certain shot names.

Thanks

dan...@image-engine.com

unread,
Sep 4, 2026, 9:25:31 PMSep 4
to gaffer-dev
We're probably going to need John to chime in on this - I'm no expert in the Python bindings.

I would have expected what you're doing to work, but I tried it and confirmed it doesn't. In order to be able to derive from a class in Python, we need the way it's bound to Python to use a Wrapper class, so that when you try and call it from C++, it realizes there's a Python override and calls that instead. That's set up for classes that we expect to be overridden from Python - but looks like it isn't set up for NameSwitch.

I think the possible solutions are either we could add support for deriving from NameSwitch in Python, or you could change your approach so that instead of deriving from NameSwitch, you instead make a custom node type that just contains a NameSwitch, and then you promote all the plugs from NameSwitch, and set your node to use the same UI as NameSwitch ... I think that should be workable, but it probably makes sense to wait to hear from John before rebuilding it that way.

-Daniel

John Haddon

unread,
Sep 7, 2026, 5:05:31 AMSep 7
to gaffe...@googlegroups.com
I think Daniel's reply has it pretty well covered. There's overhead in binding C++ nodes such that they can be subclassed in Python, so we only do it for certain strategic types. And in your case, I'm not sure deriving from NameSwitch would be all that much help since it won't know anything about your additional default input. Daniel's idea of having an internal NameSwitch on a node derived from SceneNode seems pretty reasonable. You'd need a bunch of additional logic to connect your default+array plugs to the single array plug internally though.

I do wonder if all that effort is worth it just to move one plug from the top of the node to the side though. Note that you can add additional buttons etc to the NameSwitch UI without needing to subclass, by adding metadata to the specific instance of the NameSwitch you want to "shotify".

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 visit https://groups.google.com/d/msgid/gaffer-dev/60bf2bb7-f646-429a-96c3-2d299978e1den%40googlegroups.com.

Pablo Gimenez Pizarro

unread,
Sep 7, 2026, 7:44:04 AMSep 7
to gaffe...@googlegroups.com
Thanks for the answers.
Good to know the limitations, it is a pity we can't subclass certain nodes at the moment.
I tried the Box route but the limitation I found is that I can't promote the custom plug used in NameSwitch, which is the key in this tool, you lost the plus button plug to add more connections dynamically.
So probably the most realistic way is creating a new entry menu and in the post_creator function customise the NameSwitch UI , the node will still be a NameSwitch but that is not big deal, in that case I have to abandon what I wanted to do having the default plug on the left side and the rest optional plugs on the top, but again is not the end of the world :)
Can I programmatically in python add a new connection to the name switch, in this button I have in mind the python callback needs to create a dot node and "connect" it to the plus plug so it creates the new connection.
Thanks



--

Pablo Gimenez, Senior CG Technical Director

Important Looking Pirates - ILP

Email: pablo....@ilpvfx.com

John Haddon

unread,
Sep 7, 2026, 9:11:57 AMSep 7
to gaffe...@googlegroups.com
On Mon, Sep 7, 2026 at 12:44 PM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
I tried the Box route but the limitation I found is that I can't promote the custom plug used in NameSwitch, which is the key in this tool, you lost the plus button plug to add more connections dynamically.

I don't see any reason you couldn't promote the `in` array, if that's the plug you're talking about. It's not exposed in the UI, but using the PythonEditor it can be done like so : `Gaffer.PlugAlgo.promote( root['Box']['NameSwitch']['in'] )`. I've attached an example.

Note that you don't need to use a Box either - you could make your own Python node with its own type derived from SceneNode, make a child NameSwitch in the constructor, and promote in the constructor too.

So probably the most realistic way is creating a new entry menu and in the post_creator function customise the NameSwitch UI

That's definitely the simplest option, but your own node type with an embedded NameSwitch might give you a bit more flexibility for customisation in future.

I have to abandon what I wanted to do having the default plug on the left side and the rest optional plugs on the top

I do think it's worth abandoning the idea of a single default plug and an ArrayPlug - you'd be fighting against the natural implementation of the NameSwitch. There might be something you could do to hide the default input in the GraphEditor, and then use a custom gadget to show it again on the left hand side, but it seems fragile.
 
Can I programmatically in python add a new connection to the name switch, in this button I have in mind the python callback needs to create a dot node and "connect" it to the plus plug so it creates the new connection.

Yes, the `in` plug is an ArrayPlug, which has a `resize()` method you can use to add new children.

Cheers...
John
 
nameSwitchPromoted.gfr

Pablo Gimenez Pizarro

unread,
Sep 7, 2026, 9:38:20 PMSep 7
to gaffe...@googlegroups.com
Thanks for the explanation John.
Im not sure about promoting the parameter, that will be the ideal solution for me, do lal in a box and export, kind of HDAs in houdini.
However when I promote the in plug, first I need to connect the internal Name Switch to something so it creates te in plugin, then I promote it using your code snippet, and everything seems to be ok except
for the fact that the new connections added at the tool level are not propagated internally and the internal name switch is adding the nodes but is missing a Box In to actually create rte connections.

A different topic, the method Im following now is creating a custom menu entry , the initial creation just add a Name Switch, then in the post_create I add a Context Query node inside the Name Switch, all work well, however when I open the file again, I got an error saying the internal Context Query node doesn't exist and the parameter I did initialised removed.

Any idea what can be causing It?
Thanks

--
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.

John Haddon

unread,
Sep 8, 2026, 4:28:16 AMSep 8
to gaffe...@googlegroups.com
On Tue, Sep 8, 2026 at 2:38 AM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
However when I promote the in plug, first I need to connect the internal Name Switch to something so it creates te in plugin

Yep, the NameSwitch node can operate on any sort of input plug, so this first step is needed to tell it what sort of plug to use. In the API you can do this using the `NameSwitch.setup()` method.
 
then I promote it using your code snippet, and everything seems to be ok except
for the fact that the new connections added at the tool level are not propagated internally and the internal name switch is adding the nodes but is missing a Box In to actually create rte connections.

Does the example I sent you work? I just downloaded it and checked and it is still working for me. Perhaps the difference is that I disconnect the temporary input plug (the one I used to set the NameSwitch up) before promoting? The BoxIn node is just a convenience for users authoring boxes in the UI - it's not strictly necessary so I omitted it.
 
A different topic, the method Im following now is creating a custom menu entry , the initial creation just add a Name Switch, then in the post_create I add a Context Query node inside the Name Switch, all work well, however when I open the file again, I got an error saying the internal Context Query node doesn't exist and the parameter I did initialised removed.

By default, the internals of a node are considered private, and are not serialised. So if you inject your own node in there it will appear to work until you save and reload. Do you definitely need a ContextQuery? Could you just put `${shot}` (or whatever) in the `selector` field directly?

Cheers...
John

Pablo Gimenez Pizarro

unread,
Sep 8, 2026, 5:10:21 AMSep 8
to gaffe...@googlegroups.com
Thanks for the answers John, and sorry for bombing with questions, just trying to find the best way to develop new nodes.
The example you sent me unfortunately didn't work, got lots of errors when using it in a Reference node:
ERROR   [Line 13 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 14 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 15 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 16 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 32 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 33 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 34 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 35 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 36 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Line 37 of /users/pagp/Downloads/nameSwitchPromoted.gfr] KeyError: "'variables' is not a child of 'Reference'"
ERROR   [Errors Occurred During Loading] IECore.Exception: Error loading reference "/users/pagp/Downloads/nameSwitchPromoted.gfr"

My comment about the BoxIn missing is because I thought you need a box in to establish a connection from the graph at the box node level with its internals, Houdini does the same thing with subnets.
As said, I managed to promote the NameSwitch, did something similar as you, just created a cube node and connected it to the NameSwitch, all inside the box just to force the switch to create the in Plug.
Then promote the Plug, it looks like it needs a minimum of 2 elements in the plug array to promote it, all god there and the UI works as expected.
I started to add connection to the Box node, nex plugs are correctly created for the Box node and the internal Name switch, but the Plugs in the Box node are not connected internally, which yields the NameSwitch to be useless unfortunately. I can probably post a couple of captures in Discord and is going to be easier to explain :)


About the Context Query, the reason I wanted to use it internally is because then the selector parameter shows the evaluated context variable with the shot name, which is much clearer for artists than $shot.
This takes me to an issue I have with gaffer, and probably has an easy answer: would be great to know the context variables evaluated at a certain node, let's say you right click on the node and you have an option "Evaluate Context" and the user can get a window with all the context variables for that node evaluated at that point.

Cheers

--
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.

John Haddon

unread,
Sep 8, 2026, 5:21:48 AMSep 8
to gaffe...@googlegroups.com
On Tue, Sep 8, 2026 at 10:10 AM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
Thanks for the answers John, and sorry for bombing with questions, just trying to find the best way to develop new nodes.
The example you sent me unfortunately didn't work, got lots of errors when using it in a Reference node:

Don't load it as a reference - just load it with "File/Open", and it will work fine. Note the different extensions - `.gfr` for regular files and `.grf` for reference files.
I also tested exporting the box for referencing here and that works too.
 
My comment about the BoxIn missing is because I thought you need a box in to establish a connection from the graph at the box node level with its internals

You do need a connection from the external plug to the internal one, which `promote()` makes for you. The BoxIn is just another node in the middle which gives you a visible source point for the connection in the UI - it's not essential.
 
I started to add connection to the Box node, nex plugs are correctly created for the Box node and the internal Name switch, but the Plugs in the Box node are not connected internally, which yields the NameSwitch to be useless unfortunately.

Please try with the example I sent, loaded normally. I have tested it multiple times now, both before and after referencing, and didn't see a problem.
 
Cheers...
John

Pablo Gimenez Pizarro

unread,
Sep 8, 2026, 5:41:22 AMSep 8
to gaffe...@googlegroups.com
Ups sorry, I thought the difference in the extension was a typo :)
I sent you some captures via Discord, can't paste anything here.
Got your example working and yes it looks exactly the same I have, just to keep the conversation here I'm going to paste what I put in Discord:
The differences I have found in the promoted In Plug: 
- The plug name only appears for the default plug if I hover over them , in the internal NameSwitch plugs names appear correctly. 
- I can't delete a Plug entry from the NodeEditor, like doing right click in the NameSwitch parameters and select Delete. 
- Since inputs are hidden in the internal NameSwitch I can't connect whatever is connected to the default Plug to the passTrough plug in the BoxOut node. 

But is super close ...
Thanks!

--
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.

John Haddon

unread,
Sep 8, 2026, 5:51:56 AMSep 8
to gaffe...@googlegroups.com
On Tue, Sep 8, 2026 at 10:41 AM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
The differences I have found in the promoted In Plug: 
- The plug name only appears for the default plug if I hover over them , in the internal NameSwitch plugs names appear correctly. 

For the NameSwitch, this is achieved using `noduleLayout:label` metadata registered in NameSwitchUI.py. You could do the same, but only if you create your own node type (derived from SceneNode, with an internal NameSwitch like you've been making). This is what Daniel was talking about in his original reply. It will mean a bit of Python coding using the API, but it will give you more power and flexibility than authoring it as a Box.
 
- I can't delete a Plug entry from the NodeEditor, like doing right click in the NameSwitch parameters and select Delete.

This is driven by the `deletable` metadata, also registered in NameSwitchUI.py.

- Since inputs are hidden in the internal NameSwitch I can't connect whatever is connected to the default Plug to the passTrough plug in the BoxOut node. 

 It isn't visible in the UI, but you can still connect via the API, using the `plug.setInput()` call.

Cheers...
John

Pablo Gimenez Pizarro

unread,
Sep 8, 2026, 5:59:58 AMSep 8
to gaffe...@googlegroups.com
Ah nice, I guess I can add that metadata to the plugs  also in a custom menu entry, in the post_create function.
But the custom node which inherits SceneNode  is almost the same.
If I do a custom node I have a fully new name which internal name and description is whatever I want.
If I create a custom menu entry that creates a reference node and then loads my graph with the tool is not so integrated, the internal name for the node is still Reference, and I can't change the description that appears when you hover the mouse over the node (AFAIK), however I keep a node that is easy to manipulate from the Box interface and users can dive inside to debug stuff if needed, more like Houdini HDAs.
I'll try both approaches, thanks for the help!

--
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.

John Haddon

unread,
Sep 8, 2026, 6:02:15 AMSep 8
to gaffe...@googlegroups.com
You could do the same, but only if you create your own node type (derived from SceneNode, with an internal NameSwitch like you've been making).

I must admit this is a bit fiddlier than I would like. I checked out what Cinesite are doing, and they've made their own C++ subclass of NameSwitch and rebound it so it can be subclassed in Python. I'm going to talk to the team about just making it subclassable in the first place... 

John Haddon

unread,
Sep 9, 2026, 4:35:55 AMSep 9
to gaffe...@googlegroups.com
On Tue, Sep 8, 2026 at 11:02 AM John Haddon <jo...@gafferhq.org> wrote:
I must admit this is a bit fiddlier than I would like. I checked out what Cinesite are doing, and they've made their own C++ subclass of NameSwitch and rebound it so it can be subclassed in Python. I'm going to talk to the team about just making it subclassable in the first place... 

I've opened a PR to make it possible to just subclass NameSwitch directly : https://github.com/GafferHQ/gaffer/pull/7143. All being well, that should appear in Gaffer 1.7.2.0.
Cheers...
John 

Pablo Gimenez Pizarro

unread,
Sep 9, 2026, 6:38:25 AMSep 9
to gaffer-dev
Nice, thanks!
Yesterday I tried the 3 approaches I'm testing, some with more success than others:
- Using a menu entry to customize NameSwitch. This is the most successful at the moment, I have all working except the internal ContextQuery, I have to keep it outside at the moment.
Would be great if there is any way to force internal. private, nodes to be serializable so they can be saved in the gfr file.

- A menu entry in combination with a reference, most of the node is develop in aBox and I use the menu entry module to finish all customizations. This is the method I currently prefer to develop nodes since
is very similar to Houdini's HDA. Her I found several issues:
  - I cant get the plugs label to work, when you hover over then, the metadata you specified, as you said, seems can only be used on creation but is not something I can add later ( noduleLayout:label)
  - Is interesting because I manage  to add the deletable metadata for the plugs correctly
  - I couldn't connect whatever the default plug receives in the internal NameSwitch to the passTrouch plug in the BoxOut, I tried different options with setInput() but I always get a message
   about the passTrough plug rejecting any input I assign to it. I tried this:
      root['ShotSwitchDev']['BoxOut']['passThrough'].setInput(root['ShotSwitchDev']['NameSwitch']['in']['in0'])
      IECore.Exception : line 1 : Plug "gui.scripts.ScriptNode1.ShotSwitchDev.BoxOut.passThrough" rejects input "gui.scripts.ScriptNode1.ShotSwitchDev.NameSwitch.in.in0". 

   And this:
      root['ShotSwitchDev']['BoxOut']['passThrough'].setInput(root['ShotSwitchDev']['NameSwitch']['in']['in0'].getInput())

- Custom Node from scratch with uses SceneNode as base class and creates an internal NameSwitch.  I didn't spent too much time with this to ne honest.
I prefer not to use this route if possible, although I know is the one that gives more flexibility, I'm also looking about good ways for artists to build their own tools in Gaffer since they are very used to do that in Houdini
and the second approach as I mention early is closer to that. My issue now with tis approach is that the internal NameSwith still don't have the In plug until is connected, so I can't promote it, I guess I need to create another internal node
and connect it to the NameSwitch somehow, I have no idea how to that since the In plugin still doesnt exists ...

Cheers

John Haddon

unread,
Sep 9, 2026, 8:41:24 AMSep 9
to gaffe...@googlegroups.com
On Wed, Sep 9, 2026 at 11:38 AM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
  - I cant get the plugs label to work, when you hover over then, the metadata you specified, as you said, seems can only be used on creation but is not something I can add later ( noduleLayout:label)
  - Is interesting because I manage  to add the deletable metadata for the plugs correctly

Yeah, the `deletable` metadata is different because it is just a static value. The label metadata is actually a function that computes the label on the fly. We can serialise the static values when saving to `.gfr` or `.grf` but we can't serialise the function.

  - I couldn't connect whatever the default plug receives in the internal NameSwitch to the passTrouch plug in the BoxOut, I tried different options with setInput() but I always get a message
   about the passTrough plug rejecting any input I assign to it. I tried this:
      root['ShotSwitchDev']['BoxOut']['passThrough'].setInput(root['ShotSwitchDev']['NameSwitch']['in']['in0'])

The array elements are NameValuePlugs, which have two child plugs - one for the name and one for the value (the scene in this case). You're trying to connect the whole thing, but you need to connect from just the value :

     root['ShotSwitchDev']['BoxOut']['passThrough'].setInput( root['ShotSwitchDev']['NameSwitch']['in'][0]["value"] )

- Custom Node from scratch with uses SceneNode as base class and creates an internal NameSwitch.  I didn't spent too much time with this to ne honest.
I prefer not to use this route if possible, although I know is the one that gives more flexibility

It's also the approach which is closest to your original attempt at deriving from NameSwitch. I'm confident that this approach could be made to work, including having the labels working. More faff though for sure, which is why I've just made NameSwitch subclassable.
 
I'm also looking about good ways for artists to build their own tools in Gaffer

We're big on that too - all the Gaffer pipelines I've seen make big use of it, and we use it in our own development (ContactSheet and PointInstancer are authored as Boxes before exporting them as nodes). It's just unfortunate that your first use case hit the "metadata function" limitation.
 
I have no idea how to that since the In plugin still doesnt exists ...

I think I mentioned in an earlier message, but there's a `setup()` method on the NameSwitch that will add the plug for you, assuming you're trying to do this from the API. Here's a Switch example from our unit tests : https://github.com/GafferHQ/gaffer/blob/main/python/GafferSceneTest/SceneSwitchTest.py#L52-L53.

If you can wait a few days for the next release, then my recommendation would be go back to your original approach though, and subclass NameSwitch...

Cheers...
John

Pablo Gimenez Pizarro

unread,
Sep 9, 2026, 10:18:09 AMSep 9
to gaffe...@googlegroups.com
On Wed, 9 Sept 2026 at 14:41, John Haddon <jo...@gafferhq.org> wrote:
On Wed, Sep 9, 2026 at 11:38 AM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
  - I cant get the plugs label to work, when you hover over then, the metadata you specified, as you said, seems can only be used on creation but is not something I can add later ( noduleLayout:label)
  - Is interesting because I manage  to add the deletable metadata for the plugs correctly

Yeah, the `deletable` metadata is different because it is just a static value. The label metadata is actually a function that computes the label on the fly. We can serialise the static values when saving to `.gfr` or `.grf` but we can't serialise the function.
Yes saw how it is implemented in NameSwitch and it uses lambda to get the plug name. 
This could probably be solved adding a python callback to plugs to define their labels in the UI Editor. that code can be serialised and converted into a function when the Reference process the gfr file.

  - I couldn't connect whatever the default plug receives in the internal NameSwitch to the passTrouch plug in the BoxOut, I tried different options with setInput() but I always get a message
   about the passTrough plug rejecting any input I assign to it. I tried this:
      root['ShotSwitchDev']['BoxOut']['passThrough'].setInput(root['ShotSwitchDev']['NameSwitch']['in']['in0'])

The array elements are NameValuePlugs, which have two child plugs - one for the name and one for the value (the scene in this case). You're trying to connect the whole thing, but you need to connect from just the value :

     root['ShotSwitchDev']['BoxOut']['passThrough'].setInput( root['ShotSwitchDev']['NameSwitch']['in'][0]["value"] )
Ah ok, got it, I'll try it

- Custom Node from scratch with uses SceneNode as base class and creates an internal NameSwitch.  I didn't spent too much time with this to ne honest.
I prefer not to use this route if possible, although I know is the one that gives more flexibility

It's also the approach which is closest to your original attempt at deriving from NameSwitch. I'm confident that this approach could be made to work, including having the labels working. More faff though for sure, which is why I've just made NameSwitch subclassable.
 
I'm also looking about good ways for artists to build their own tools in Gaffer

We're big on that too - all the Gaffer pipelines I've seen make big use of it, and we use it in our own development (ContactSheet and PointInstancer are authored as Boxes before exporting them as nodes). It's just unfortunate that your first use case hit the "metadata function" limitation.
About this it would be great for References if they could be disguised as a proper node type, probably using some metadata, let say in python you create a reference node and then add some metadata to the node so it is treated as a different type and in the Node Editor or when you hover over the node instead of getting Reference as the type you can get whatever you want, but I guess this would go against of some of Gaffer's  foundations . At the moment I'm just setting a proper name, but I'm sure some users will be confused at the beginning when they see Reference in the Node Editor.
BTW I have actually already built a couple of tools using Box/Reference and works pretty well, this Shot Switch tool is the first one where I hit the wall.
 
I have no idea how to that since the In plugin still doesnt exists ...

I think I mentioned in an earlier message, but there's a `setup()` method on the NameSwitch that will add the plug for you, assuming you're trying to do this from the API. Here's a Switch example from our unit tests : https://github.com/GafferHQ/gaffer/blob/main/python/GafferSceneTest/SceneSwitchTest.py#L52-L53.

If you can wait a few days for the next release, then my recommendation would be go back to your original approach though, and subclass NameSwitch...
Ok I can path the full node from scratch at the moment, I think I will use my NameSwitch customised from entry menu for the time  being.
Just going back to my first point in my previous email, is there any way to make nodes that I create inside NameSwitch, in the private area, serializable? So they got saved in the scene.

Thanks

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.

John Haddon

unread,
Sep 9, 2026, 1:15:05 PMSep 9
to gaffe...@googlegroups.com
On Wed, Sep 9, 2026 at 3:18 PM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
About this it would be great for References if they could be disguised as a proper node type....

A Reference is a Reference, and that won't change (ignoring https://github.com/GafferHQ/gaffer/issues/5664 for a second).

But you can actually already export Boxes into custom node types - that's how ContactSheet and others end up as their own type. This is done using `Gaffer.ExtensionAlgo`. Currently it isn't exposed in the UI because we're not sure how it should interact with people's pipelines. Where would it export to? Would all nodes go in one module? Would people want to put the Box in source control and export when building (that's what we do)? But it's very much available if you want to script it up for use in your pipeline.

Just going back to my first point in my previous email, is there any way to make nodes that I create inside NameSwitch, in the private area, serializable? 

Not really no - the internals of nodes are private and reserved for use by the node, both now and in the future. There are plenty of options for extending Gaffer without needing to break that encapsulation...

Cheers...
John

Pablo Gimenez Pizarro

unread,
Sep 9, 2026, 1:21:21 PMSep 9
to gaffe...@googlegroups.com
--
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.

Pablo Gimenez Pizarro

unread,
Sep 9, 2026, 1:27:47 PMSep 9
to gaffe...@googlegroups.com
Sorry I sent the previous email by mistake

On Wed, 9 Sept 2026 at 19:14, John Haddon <jo...@gafferhq.org> wrote:
On Wed, Sep 9, 2026 at 3:18 PM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
About this it would be great for References if they could be disguised as a proper node type....

A Reference is a Reference, and that won't change (ignoring https://github.com/GafferHQ/gaffer/issues/5664 for a second).

But you can actually already export Boxes into custom node types - that's how ContactSheet and others end up as their own type. This is done using `Gaffer.ExtensionAlgo`. Currently it isn't exposed in the UI because we're not sure how it should interact with people's pipelines. Where would it export to? Would all nodes go in one module? Would people want to put the Box in source control and export when building (that's what we do)? But it's very much available if you want to script it up for use in your pipeline.
Ah that sounds interesting, yes I remember seen it in the changelogs, is there any doc/example about how can I use it? 

Just going back to my first point in my previous email, is there any way to make nodes that I create inside NameSwitch, in the private area, serializable? 

Not really no - the internals of nodes are private and reserved for use by the node, both now and in the future. There are plenty of options for extending Gaffer without needing to break that encapsulation...
Any suggestions? I want the Selector parameter to show the evaluation of the context variable shot, instead of using $shot. And if possible keep things tidy and not having external expression or context query nodes hanging around. The problem with the context variable is that is not easy to debug for most users, in Houdini you can middle click on the parameter and it evaluates the expression and you can check the result but I believe there is no way to do that in Gaffer.

Thanks

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.

dan...@image-engine.com

unread,
Sep 9, 2026, 5:20:43 PMSep 9
to gaffer-dev
> Any suggestions? I want the Selector parameter to show the evaluation of the context variable shot, instead of using $shot. And if possible keep things tidy and not having external expression or context query nodes hanging around.

I haven't fully followed this conversation, but if you're using the next Gaffer release where John has added support for subclassing NameSwitch, and you're planning to subclass NameSwitch, then you can add private internal nodes in the constructor of your NameSwitch subclass. Since they're an inherent part of the node, always added by the subclass constructor, they won't need to be serialized.

-Daniel

Pablo Gimenez Pizarro

unread,
Sep 9, 2026, 6:38:14 PMSep 9
to gaffe...@googlegroups.com
Thanks Dan, yes I'll try that.

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/fBjSrnaQ8U0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to gaffer-dev+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/gaffer-dev/dc6e05c0-a61a-4bd1-a12d-9ab35c07b32an%40googlegroups.com.

John Haddon

unread,
Sep 10, 2026, 4:32:35 AMSep 10
to gaffe...@googlegroups.com
On Wed, Sep 9, 2026 at 6:27 PM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
This is done using `Gaffer.ExtensionAlgo`.
Ah that sounds interesting, yes I remember seen it in the changelogs, is there any doc/example about how can I use it?

We're very light on documentation, but the unit tests contain a pretty simple example of how to use ExtensionAlgo : https://github.com/GafferHQ/gaffer/blob/main/python/GafferTest/ExtensionAlgoTest.py#L55. You can also see where we use it in our own build process here, but that's more complex than you'll need because you don't have the "chicken and egg" problem it talks about : https://github.com/GafferHQ/gaffer/blob/main/SConstruct#L2089-L2128.
 

Just going back to my first point in my previous email, is there any way to make nodes that I create inside NameSwitch, in the private area, serializable? 

Not really no - the internals of nodes are private and reserved for use by the node, both now and in the future. There are plenty of options for extending Gaffer without needing to break that encapsulation...
Any suggestions? I want the Selector parameter to show the evaluation of the context variable shot, instead of using $shot.

As Daniel suggested, subclassing NameSwitch will allow you to have an internal node.
 
in Houdini you can middle click on the parameter and it evaluates the expression and you can check the result but I believe there is no way to do that in Gaffer.

In Gaffer you can alt+middle click for the same. 

Cheers...
John

Pablo Gimenez Pizarro

unread,
Sep 11, 2026, 6:09:25 AMSep 11
to gaffe...@googlegroups.com
On Thu, 10 Sept 2026 at 10:32, John Haddon <jo...@gafferhq.org> wrote:
On Wed, Sep 9, 2026 at 6:27 PM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
This is done using `Gaffer.ExtensionAlgo`.
Ah that sounds interesting, yes I remember seen it in the changelogs, is there any doc/example about how can I use it?

We're very light on documentation, but the unit tests contain a pretty simple example of how to use ExtensionAlgo : https://github.com/GafferHQ/gaffer/blob/main/python/GafferTest/ExtensionAlgoTest.py#L55. You can also see where we use it in our own build process here, but that's more complex than you'll need because you don't have the "chicken and egg" problem it talks about : https://github.com/GafferHQ/gaffer/blob/main/SConstruct#L2089-L2128.
Interesting, this is closer to HDAs, would be super nice to have this in the GUI,like "Export as Node Type" or something similar.  But since Im promoting plugs here I will have the same issue with the plugs dynamic labels.
 

Just going back to my first point in my previous email, is there any way to make nodes that I create inside NameSwitch, in the private area, serializable? 

Not really no - the internals of nodes are private and reserved for use by the node, both now and in the future. There are plenty of options for extending Gaffer without needing to break that encapsulation...
Any suggestions? I want the Selector parameter to show the evaluation of the context variable shot, instead of using $shot.

As Daniel suggested, subclassing NameSwitch will allow you to have an internal node.
 
in Houdini you can middle click on the parameter and it evaluates the expression and you can check the result but I believe there is no way to do that in Gaffer.

In Gaffer you can alt+middle click for the same. 
Oh thanks, you learn something new every day :) 

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.

John Haddon

unread,
Sep 15, 2026, 4:21:48 AMSep 15
to gaffe...@googlegroups.com
Hi Pablo,
Quick note just to say that as of Gaffer 1.7.2.0, released yesterday, you can subclass NameSwitch from Python. Hope that helps...
Cheers...
John

Pablo Gimenez Pizarro

unread,
Sep 17, 2026, 10:01:42 AMSep 17
to gaffer-dev
Just tested it and it works great.
I'm going to port what I did with my custom tool in the menu to this proper new node type derived from NameSwitch.
Also tested the Alembic issue with the Pref and it also works perfectly.
Thanks!!!

John Haddon

unread,
Sep 17, 2026, 10:43:38 AMSep 17
to gaffe...@googlegroups.com
That's great - thanks for letting us know..

--
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.

Pablo Gimenez Pizarro

unread,
Oct 5, 2026, 8:14:35 PM (5 days ago) Oct 5
to gaffer-dev
Finally got some time to go back to Gaffer.
Got all nicely working in the custom node for the shot switch node, much better than the hack customising a NameSwitch node from a menu entry.
One last thing, in Houdini I tend to assign different color to the inputs plugs and have some sort of color convention depending of the porpose of the input.
Would be great for this tool to be able to have a color for the in0 plug and a different color for the rest of the in* plugs.
I have managed to do it on an existing node using:
Gaffer.Metadata.registerValue( p, "nodule:color", imath.Color3f( 0, 1, 0 ))
Been p the plug. (in0.value)
However when I try to add this to the register node callback in my UI module I cant get it to work, Im adding something like:
"in*.value" : [
            "nodule:color", imath.Color3f( 1, 1, 0 ),
            "connectionGadget:color", imath.Color3f( 1, 1, 0 ),
            ]
I have tried different  names for the plug, like in0.value, or just in0, but no one works as expected, when I create the node the in0 plug appears with the usual blue color.
I have to mention in my custom node I have this:
    def __setup(self) -> None:
        # initialise node for ScenePlugs. Thhis also forces to create the in plug array
        self.setup( GafferScene.ScenePlug( "value", ) )
To initialise the node on creation and already have a valid default shot plug.

Cheers

John Haddon

unread,
Oct 6, 2026, 10:04:28 AM (4 days ago) Oct 6
to gaffe...@googlegroups.com
On Tue, Oct 6, 2026 at 1:14 AM 'Pablo Gimenez Pizarro' via gaffer-dev <gaffe...@googlegroups.com> wrote:
Got all nicely working in the custom node for the shot switch node, much better than the hack customising a NameSwitch node from a menu entry.

Great!
 
I have tried different  names for the plug, like in0.value, or just in0, but no one works as expected

I think you'll need "in.*.value". The top-level array plug is called "in", then there are arbitrary numbers of children (array elements), and then they each have "name" and "value" children.

Cheers...
John
Reply all
Reply to author
Forward
0 new messages