Updated Particle Nodes UI 2¶
The concept of a particle type is still very useful in my opinion, so it still exists. The last two proposals presented two different solutions on how a Particle Type node can look like. This proposals presents a third option, that can be thought of as a mix of the two.
In the original proposal, the Particle Type node had three sockets (Emitters, Modifiers and Events). There were three issues with this:
- Higher level nodes representing particle behavior cannot always be put into exactly one of these categories.
- Since the sockets pointed in different directions, the node tree grows into more directions than it should.
- Node groups containing e.g. both emitters and events would be weird to connect to the Particle Type node.
In the second proposal, the different categories of behaviors were unified. Furthermore, the Particle Type node would not be linked to nodes containing behavior directly. Instead, enum menus were used to represent the connection of behavior and particle types. This did solve the three problems the original proposal had, but introduced two new problems:
- The connection between particle types and their behaviors is not as obvious anymore.
- There can be potentially many free floating nodes in the node tree, that do not really make it more organized.
Both problems could be solved using different visualization methods, but it would be nice if it would look more similar to other node trees in Blender.
In this new proposal, the different categories of behaviors are unified at the user level as well. Nevertheless, a Particle Type node still has a socket that allows connecting behaviors to it. Functionality wise, it does not matter if this is an input or output socket or something else. However, as you'll see below, making it an input socket gives nice benefits.
When no behavior is attached to a particle type, particles of this type will do nothing (as in, they do not move and don't die). Users can add more behavior to a type, by creating links to the Particle Type node. Since users should be able to add an arbitrary number of behaviors, the Type input can accept multiple inputs. Note: the links to the Type input purely represent a relation, there is no actual data or control flow.
Internally, every behavior is of one specific type (e.g. emitter, force, event). However, a behavior at the user level might consist of multiple of those low level behaviors. For example, a behavior defined by a node group can contain an emitter and an event.
To run the simulation, the node tree has to be parsed first. This parsing consists of three main steps:
- Find Particle Type nodes.
- Find all behaviors for every particle type.
- Validate that the behaviors are not conflicting and choose the right solver for every particle type.
In the beginning, the supported behavior types will be fairly high level (emitter, event, ...). In the future, we probably want to support more low level behaviors. For example, a behavior could also represent an entire solver. To use this solver, a "solver node" would just have to be connected to the particle type to replace the default solver.
This approach allows the system to be easy to use for simple simulations while still allowing a lot of flexibility when required. The set of supported behavior types can grow whenever we need flexibility in a new direction.
The exposed inputs of behavior nodes can be computed with the normal function nodes. Those work very similar to shader and compositing nodes.
By default the input for every behavior node is computed once per time step. However, some nodes can have inputs that are computed per particle (e.g. the strength of a force).
Events can trigger actions that manipulate the state of individual particles (e.g. change particle color/size after a collision). An action can be composed by chaining multiple actions. Furthermore, it is possible to have conditions. So the control flow may differ between different particles based on e.g. the particle position.
In the original proposal actions always started at an output socket (e.g. at the output of an Age Reached Event node). To execute multiple actions, they would have to be chained, making the node tree grow to the right. While I still think that this is the more natural representation, I changed my mind on how this should work.
Instead of growing chains of actions to the right, they can now grow to the left and vertically. This makes them fit better into the node tree and also simplifies the individual nodes (most action nodes need one socket less).
What should be displayed in the "execute" input sockets still has to be decided. For example, all these "Execute If True/False" look a bit overloaded currently, but I'm sure there is a better solution.
The node tree growth problem is solved, because the tree only grows vertically and to the left. This also makes the Auto Offset feature in Blender more useful again.
The composition problem is solved as well. In this design, node groups can work the same as in all other node tree types in Blender.
While not strictly necessary, an often requested nice-to-have-feature is an output node. In this design, the Particle Type node looks like an output node. There can be multiple though. Nevertheless, it can help to orient yourself in the node tree.