Group Defaults node [Proposal]

This document proposes a way to generalize what values a node group input can have by default. Note that this proposal still has some weak points. However, I was referencing this node in discussions every now and then, so it’s better to have the proposal in public.

Current Limitations

There are various limitations for what default inputs for a node group can be:

  • For geometry, matrix (and later bundle and closure) sockets, there is no way to specify a default value.
  • For some primitive socket types (e.g. float and boolean) one can only specify a single value, but the default can’t be e.g. a field.
  • For some primitive types (e.g. integer and vector) one can have a single value as default, or choose from a hard-coded set of fields, including e.g. the position, normal and index field.

It isn’t possible to use arbitrary values as defaults for any socket type.

Proposal

The proposed solution is to introduce a new Group Defaults node which is conceptually on the same level as the Group Input and Group Output node. It does not do any operations on it’s own, but only helps building the interface of the node group.

There can only be a single (active) Group Defaults node. The node has an input socket for every input of the node group. The node shows the default values for all inputs.

The new part is that one can connect arbitrary other nodes to the Group Defaults node to specify more complex defaults. For example, to use the position attribute as default for the Vector input, one can do this:

image

Another common example would be to use a noise texture as default. For example a simple Displace node group could be build as shown in the next image. It’s more convenient than before because it uses the noise texture by default, but can still be customized by passing in a different noise.

In theory, the Group Defaults node could also depend on the Group Input node (as long as the default does not depend on itself). Supporting this, might be interesting at some point, but for now it’s probably not worth the implementation complexity.

Problems

While specifying the default values like this works well, things are a bit more complex on the caller site when we start to rely on more complex defaults more heavily. Currently there are three different callers: group nodes, the Geometry Nodes modifier, and the Node Tools operator.

Currently, when creating a Group node or modifier, the initial value will generally be taken from the underlying group, but then the connection to the group is lost. So when the default value changes later on, the value in the group node or modifier does not update.

The situations is different when using the Group Defaults node. In this case, the group node or modifier will automatically get the new default if it changes. While this might be nice in some cases, it’s a bit bad to be inconsistent.

Another tricky situation is when a socket that had a single value default before, suddenly gets a field as default. The question is, how should that change existing usages of the group if they have or have not yet changed the single value default?

Propagating default values to the inputs of the parent node group is also more tricky. Currently, when you hit ctrl+G on a group node, the default values of that new group will be the same as those of the inner group. It’s not obvious how that would work when the Group Defaults node is used in the inner group.

12 Likes

UI-Wise, the elegant way this is handled in some of the game engines is that the input node, which brings the data from the parent node level has inputs of its own.
So instead this:


Which looks quite wonky given that there’s a random, disconnected floating node, you’d have something like this:

…where if the input of the group input node input socket is left empty, then the value in the node group properties is used:
{7BBA4671-696E-4607-8B39-C0AFAAF6B6ED}
And if the group input node input socket is occupied, the default value its overwritten by whatever is fed into that socket.

This would also mean the input sockets of the group input node would not need to have default values displayed right in the node, as they would be present in the Group sidebar, and therefore it would not throw off the alignment of the output sockets of both new and existing group input nodes.

The issue here though, would be how to handle multiple group input nodes, which are currently possible. What will probably end up happening is that we’ll end up with sub-par solution like dedicated defaults node, because it’s now too late to fix the flawed design of multiple group input nodes being possible, which was consequence of blender not having named reroutes. It’s sad that new, modern design decision are often limited by the bad legacy ones :confused:

18 Likes

For built-in nodes, the convention is that “Hide Value” is used whenever there is a default that is not a single value. I wonder if there are good use cases for these to be different in practice, or if it’s effectively the same feature and they should always be coupled.

So that when a socket gets a field as the default, effectively the default single value just doesn’t exist anymore. It’s like changing the socket type, the modified and node group instances will not attempt to preserve the previous single value.

2 Likes

+1 to the input having inputs, if that’s a possibility. It seems like that is the convention in other apps and is clean and intuitive. For multiple inputs, an invalid link could be used (like when there are multiple menu switches) if an existing input already has a default plugged into that socket. While the invalid link is sometimes confusing to folks, I don’t think it would be any less confusing than having a special node that can’t be duplicated, or, if it can, it would need to have invalid links anyway.

6 Likes

We thought about having this functionality in input nodes. I’m not really against it, it just has some problems as you already noticed.

There can be multiple group input nodes and there is not a single active one (like there is for Group Output nodes). The other problem with that is that then it might be harder to find the group input nodes, because they are not at the “beginning” of the tree anymore.

While the design could have been done differently, so that only a single Group Input node is allowed, I don’t think that would have actually changed the situation much. If people would used named reroutes as you mentioned instead, you’d still kind of end up with a single node somewhere that would be used to specify the defaults. Just that it is the single Group Input node and not the Group Defaults node. That said, it seems unlikely that the design for Group Input nodes is changed, because it does not seem worth the trouble.

I feel like it’s better to have a single place to specify these more complex defaults instead of mixing those with the rest of the node tree. There they can also get in the way of e.g. creating a group with ctrl+G.

Yeah, the main difference to before is that in built-in nodes we rarely change a single-value-input to one that takes a field by default. And when we do that, we have versioning to keep the behavior as before by inserting an additional node.

Doing this for node groups seems more tricky. It might be fine to just treat the value as being gone, even the user modified it already, but I don’t find the decision straight forward.

4 Likes

2 posts were merged into an existing topic: Declarative Systems in Geometry Nodes

I agree. I think this is a good argument against having a dedicated isolated node, since the workflow won’t be from left to right anymore, and in my opinion that would make the node tree harder to reason about, especially for the compositor where isolated nodes have no effects on the node tree so far.

It seems like this suggestion can cover most of the straightforward cases and is nicely discoverable. For more complex cases, we could implement a “Is Socket Connected” (already a request on RCS) which together with a switch node will give users the ability to implement defaults.

3 Likes

I love this proposal, and honestly, it could take a small step further.

Some basic nodes could benefit from having more Default Settings, while not adding actual new functionality take primitive nodes for example.
The default Grid node has 4 input sockets, XY vertices, and XY size.

My custom grid node adds Resolution Mode that lets me pick between vertices and faces, and it adds a Size Mode that lets me pick between the size (dimension) of the grid and the size of the faces. There are UV settings too, but we can ignore them for now

This node asset I created would make sense for me to be my default grid node.
A lot of Asset Libraries that I used always have their custom primitive nodes and sometimes other basic nodes with added functionality.

Here’s a demo of my custom grid node.

3 Likes

I’m not sure what part of his proposal you are refering to exactly. I did not intend to remove the default values in the sidebar. Those would still be the most common way to set simple defaults.

As for adding inputs to the Group Input node, I still don’t quite see how that can be done without reintroducing the problem we set out to solve with that in the first place. If a Group Input is used multiple times, then it’s arbitrary where the default is specified, and it will probably become a best practice to then have a separate Group Input node just to specify the default, and then you end up with loose nodes again (which I’m fine with personally, but obvious people don’t like that much).

That might be a feasible alternative, although the details are a bit more involved than the proposal makes it seem. Sockets for which we check if something is connected can’t have an input value, because that would just be ignored. Also in the modifier UI we’d still need a way to override the default value even though we don’t “link” anything there.

That also means that “Is Socket Connected” is not quite the right terminology. It only makes sense when calling the group from a group node, but not when using it with a modifier or operator. Something like “Is Input Provided” would be more correct.

Also, there still has to be a default value, because the node group might ignore the “Is Input Provided” node. Also it means the switching between the provided value and default will need to be done for each Group Input.

I also wonder what we’d show as default value in the tooltip in Group nodes, because that can’t really be automatically determined then. There might be different defaults at every Group Input node.

Nevertheless, it’s an interesting point, maybe that can be developed into a separate proposal at some point. :slight_smile:

2 Likes