Enum Sockets [Proposal]

Not saying there are no other solutions, but I think always breaking node groups just because the enum is reordered or you want to add something in the beginning feels wrong.

This would be technically possible, but does not have high priority for me atm. Of course changing the operation for every element also has a certain performance cost (although if done right, you would not have to pay this cost when only one operation is used).

That’s also not unreasonable. Creating enum data blocks should work and I’ve thought about that before. The main problem is that it seems highly unlikely that a new ID data block will be accepted just for enums. There is precedence where something similar has been done before: color palettes. However that is also seen as a mistake by some. Personally, I’m not sure when some piece of data becomes important enough to justify that it becomes its own data block.
In the original proposal I essentially worked around this by saying that you should put the Enum node into a node group to reuse it.

Right, internally the data that is passed through enum sockets from left to right is an identifier for a specific enum value (which is an integer). However, for the proposed enum sockets to work we also have to infer the enum type (which contains all the possible enum values) from right to left. So that when you expose an enum socket to the Group Input, the correct possible enum values will be shown in the parent node group.

I’m not sure which Blender version you are using but in Blender 3.0 you should see a data type selector in the sidebar that you are showing:

That can definitely work, given we have some kind of enum data block, or a non-data block alternative. I wonder, how would you expose built-in enums with this approach (which definitely do not have their own data blocks).

1 Like

Huh, so it was finally added. I had no idea, I probably missed the news. That’s great!

I wonder, are there any other parts of Blender, where user can create some custom data, which is not a data block or a part of data block? I mean, the point about exposing built-in enums, which are definitely not datablocks is valid, but at the same time, it feels like inventing new unique concept of special user generated data, which is not stored in a datablock.

There’s data, which is part of datablock, such as Vertex Colors or UV maps being part of Mesh datablock, but that’s mainly because those are always unique to the given datablock, meaning that for example vertex color and UV maps are mapped to the specific topology of given mesh geometry. Enums, on the other hand, are not tied to specific node groups or GN node networks, so I can imagine future scenario where I want multiple systems to work together, and therefore reference the same Enum.

I can already imagine a use case where, sometime in future, Shader Editor would also support enums, and I’d want to tie certain material effects to certain GN effects, and I would not want to manually synchronize multiple unique enums for shader editor, GN editor, perhaps particle and physics nodes in future, and so on…

If Enums were datablocks, this would be easy. If Enums were something special defined right inside of the node trees or node groups, I can imagine it either being harder, or inventing some new “not-quite-datablock” thing for user generated data which are not datablock worthy but still should be accessible outside of their datablock (node tree/node group).

1 Like

I think both an “Enum Switch” node and “Enum Match” node (with boolean outputs for every item) can be useful. I would guess a Enum Switch covers most cases.

Enum Match can be emulated with a boolean Enum Switch node and setting true/false in the required inputs. But you’d need to create one node for each item so that’s a bit tedious. However you can then also handle the case where you want to match one of multiple items. Not sure if that’s enough or a native Enum Match with a boolean output for each item is needed.

As for Enum datablocks, I think wrapping enums in a node group instead makes sense. I would not even consider that a workaround. To me it seems like just another building block that you use to build node graphs, like a shared math node or texture node.

I can imagine cases where you would have additional inputs associated with that enum, or certain node logic that you want to have shared. And then you would need to make it a node group anyway. We’d need to be able to share such node groups between different types of nodes, but that’s already where we are going. Also note that node group asset management will be improved, so you can organize node groups into categories in menus, and have them available next to built-in nodes.

1 Like

Having an “Enum Switch” and “Enum Match” node sounds reasonable to me. I mainly wonder where the source of truth for enum labels/names should be then. In the current prototype, the source of truth is in the Enum node.
Both the “Enum Switch” and “Enum Match” node could be the source of truth for new enums. But that makes me wonder what you’d do when you want both nodes for the same enum. Should they be kept in sync somehow? Or are the enum values stored somewhere else? Or is that just not possible?

Enum Match can be emulated with a boolean Enum Switch node

The opposite is true as well and it would be much easier if we already had an index based Switch node.

1 Like

Yeah, having multiple such nodes in a single graph might not be very elegant. They could be chained, with an output enum socket that if used would get the items from the next node.

I’m not sure how common the need for multiple nodes would be in practice. I imagine that in most cases you either want an Enum Switch, or an Enum Match with 2 items that acts like a boolean with more informative UI.

Right, mainly I’m thinking that if we have only one, Enum Switch seems the most convenient / user friendly one. It’s not clear to me how an index based switch node could automatically get inputs named for each item.

But we don’t necessarily need just one.

To me it does not seem too far fetched that one might want to switch two values based on the same enum. But it may be fine if that requires that the user has to restructure the use of the Enum* node a bit.
Chaining nodes just to transfer enum information could work, but does come with its own difficulties. E.g. what happens when the node on the left is put into a group? The group can’t really depend on the enum values that are used in the parent group.


An alternative solution could be to combine the Enum Switch and Enum Match node into one. Unused sockets could just be hidden. For now, the node would either have a data type dropdown (which I’d not expose as socket btw, because I want to use inferencing for that eventually) or it would just have sockets for all the different types available all the time.

Long term, if we ever support type inferencing within node groups and also in the Group node, this would become much simpler. Then one could just setup the an Enum node with all the enum items and hit Ctrl+G to create a group. With inferencing, the group can work just like the Enum Switch node with the ability to change the data type outside of the underlying node group that specified the enum values.

My understanding is that you’re trying to solve both defining and using enums in a single place. What if enums are defined at the scene level, as custom properties ? then geometry nodes could just reference them.

Scene level does not work for assets. If you want to share an object with geometry nodes or a material, the enum should come along with that, it can’t be tied to a specific scene.

After thinking, I got an idea:
Why not take out the enumeration lists from the nodes.
And refer to them as a group of nodes to an option selected from the list. After selecting the available list of enumeration, the number and types of inputs are set by themselves. The same can be done with the int input setting.
And it can be a pre-processor in shaders
(Although I’m a bigger fan, if even the group of nodes used can be selected by the Enum)

I made a small example of a multiplexer, based on node group, as an example of how it might look

1 Like

Will this feature come to 3.2?

3 Likes

I don’t know what the state of this proposal is, but I just looked at this example in the manual and thought it was pretty similar to this proposal, but with instances instead of strings. It’s not like I have any specific thoughts about it. Maybe presenting enums as instances for any data would be interesting.

https://docs.blender.org/manual/en/latest/modeling/geometry_nodes/geometry/geometry_to_instance.html?highlight=geometry%20instance%20node

I think that’s something completely different. With that node you are building a list of instances to pass to another node.

With this proposal (as I understand it) you don’t want to pass the list of options, you want to pick an option from an already built-in list.

This proposal is conceptually simple, you could expose the enum as an integer and call it a day. Which would imho already be quite useful. But UI-wise it’s a lot more complicated.( If you expose the enum as an integer you need to add the numbers in the list, at the very least. Or even some more complicated system, where you don’t use ints but strings? But that would be complicated with translation. )

An enum is just an integer from inside a range, with labels for different numbers.
Thinking about it, a Bool is just a very simple enumeration with 0/False 1/True.
We do have a switch node for the Bool. But, current approach does match an Enum against many Bools. To handle, one would need many switch nodes.

New option: The socket has data from the context.
They may change during the calculation.
The idea is that enums can be entered as standard.
And as custom strings. Strings can be compared.
Standard ones can be associated with custom ones.
There is no need to keep track of the namespace in the file.
New sockets are added either as strings or as a new node.

+Edit:
It’s like if when you enter a field, you can find out what type of domain will evaluate it in the inside of the group

Solution to what happens when sockets change:

When the socket is connected to the group input, the node shows a new checkbox named ‘expose compatible only’. If ticked, the dropdown on the front end group node only shows options with the same socket names. If unticked the user can tab into the node (similar to a group node), where they’re met with x duplicates of the outer node, one for every dropdown option. So if you have 10 options in the dropdown, you’d see 10 copies of the node, each with a different option selected. The ones that have the same sockets as those already wired to on the outer node will already be wired. The ones that don’t, the user will need to wire up to tell blender what goes where if the user selects one of those options on the outer node.

Getting these exposed to the group inputs and modifier front end will be monumental for TD’s and end users with insufficient knowledge of the inner workings of the modifier’s nodes.

In fact, if an index switch node existed, then the user could implement my above suggestion themselves just by using a group (after the dropdowns have a socket of course):

They’d plug each duplicate node into the index switch, and then the dropdown’s index would choose which of the duplicate nodes to send out of the group.

4 Likes