This document is based on parts of this blog post. There is a work-in-progress PR.
Problems
The goal of this proposal is to solve the following problems:
- We want to remove the need for control node groups as a way to get global input values (example). While this approach is useful in some setups, it doesn’t work all that well when building reusable node systems.
- We have no good way to pass the hair system’s surface geometry to the relevant hair nodes in a good way.
- We have no way to override existing contextual input nodes like Mouse Position, Active Camera and Scene Time. Being able to override tool inputs like mouse position and viewport transforms would be especially useful when we want to turn an edit mode operator into a modifier.
- We need a more flexible replacement for the “Is Viewport” node, which is used to control a performance vs. quality trade-off. Just making this decision based on whether we’re rendering or not is not good enough. For example, sometimes the “fast” mode of a node group should be used in edit mode.
Abstract Problem
What all these issues have in common is that we want to pass information into nested node groups without having to set up all the intermediate links which would cause a lot of annoying boilerplate. Nevertheless, we want to be able to override all these inputs at any intermediate level.
Proposal
The proposed solution is the concept of “Context Inputs”. A context input is a group input that is automatically exposed on parent node groups as well, unless it is explicitly overridden.
Built-in Context Inputs
For example, in the image below, the node group uses a Scene Time node which outputs information retrieved from the current evaluation context. The group automatically gets new inputs in a “Context” panel that are derived automatically. They are also grayed out in the side bar because they aren’t editable. The Group node also shows the context input panel. By passing in a value for the “Seconds” input explicitly, one could overwrite it. By not passing in anything, the value will be retrieved from the context.
If the root node group has context inputs, those will also be shown in the modifier, where one can then also decide to either override the input.
If the same context input is used in a node group multiple times, it is deduplicated and only exposed to the parent once.
Custom Context Inputs
In addition to the built-in context inputs of which we have many already, we can also add support for custom contexts. For that, a new Context Input node is added.
Each custom context input has the following properties:
- Data type: Type that is output from the node.
- Identifier: Used for deduplicating multiple custom context inputs.
- Name: User-friendly name for the context input that is shown in the UI.
- Description: Tooltip used for group inputs.
If multiple context input nodes have the same identifier but different types, the “most complex” type is exposed if possible (e.g. vector is more complex than float). If the types are not compatible, there is an error. If the names or descriptions are different, the first found non-empty name or description is used. The order in which nodes are checked is deterministic but not defined.
These properties of context inputs are not input sockets because they need to be known statically; they affect the interface of the node group and might also affect the dependency graph.
Custom context inputs are also propagated all the way up to the modifier if they are not overridden in the node tree. The modifier then has three choices:
- Provide a specific value for the context input.
- Retrieve the context input from an even higher level context, e.g. custom properties of the object or scene.
- Fall back to some default value. The design for default values is not entirely clear yet. For now it would just fall back to zero. The issue with storing a default value in the Context Input node is that those values can’t be deduplicated if they are different without potentially changing the evaluation result. Maybe there just needs to be an error if multiple different default values are provided for the same context input.
The video below shows how a custom default is propagated step by step all the way to a custom property on an object.
Relation to Group Input Defaults
There is a little bit of overlap with the Group Defaults node proposal. Context inputs are also inputs with special defaults.
There is also the question of whether all the context inputs have to be in the “Context” panel or if the node group author is allowed to interleave them with other inputs. For example, hair node groups often need access to the surface geometry. This can often be retrieved from context, but it still makes sense semantically to expose it as a normal input.
Currently, my stance on that is that all context inputs should be forced to stay in the separate panel which Blender manages automatically. However, the user can manually create a separate group input that uses the context value as default value. In the Group Defaults node proposal, that would mean that the Context Input is linked to the Group Defaults node.