For some time now the plan has existed to make access to Blenders internal data much easier and generic by using the API system called “RNA”. This system declares unified access methods for anything you can see and manipulate in a Blender file: from objects, meshes and lamps to materials, particles and even the user interface elements. It is the same system used also for defining the stuff you can script on with python (though python is not involved so far).
If you watched the previous demo videos, you may have noticed that the Get/Set nodes are all very limited and static, i.e. their input/output sockets do are not changing at all (that is especially annoying with the Set nodes, because you essentially are resetting each of the input values in each node). Well, these problems will be solved soon, here are some first impressions of the generic data nodes (still WIP):
Before any sockets can be added, the type of the data node has to be set (for coders: this is a StructRNA identifier). This is could be simplified further by adding the most common struct types (objects, meshes, particles, etc.) to the menu as shortcuts to predefined nodes and adding a search and/or tab-completion feature. After setting the type, all available properties of that type can be added as sockets (outputs for the GetData node, inputs for SetData). This too could benefit from search/tab-completion.
The “Path” sockets you see in the image are used to define the actual source of the data, i.e. an instance (or collection) of the nodes struct type. This is basically a shortened version of the RNA paths known from python scripting: They point to some entry in the bpy.data namespace. Here are some examples:
|Object||objects['MySpaceship']||plain object data (not a mesh!)|
|Mesh||meshes['MySpaceshipMesh']||not vertex data, just the mesh properties|
|Mesh||objects['MySpaceship'].data||access to the same mesh via its parent object|
|MeshVertex||meshes['MySpaceshipMesh'].vertices||this actually gives you the vertex data collection, like positions, colors, etc.|
Note that the paths are only really evaluated at runtime (though most often you will end up using the default socket values). Also you may notice in the image that the GetData node has an additional “Path” output too: This can be used to quickly construct chains of data nodes without the use of a third value node just to have a common input for the paths.
Not all properties which are part of the RNA can or should be selectable as sockets:
- Read-only properties can not be part of SetData
- Structs that are exclusively part of the GUI system and other sensitive areas not intended for simulation should not be selectable for data node types
- Pointer properties can not be used as sockets. To access primitive properties of their target structs, the RNA path should be refined further and used in other data nodes
- Property collections can be tricky, especially when using varying sizes (but should be possible in the end by putting them into their own unique context)
Important: Collections of primitive types (float, int, etc.) are not to be confused with collection contexts generated from the node path input! The latter are arguably the most important new feature for doing scalable simulations. In short: path inputs define a pointer or collection of pointers, whereas the sockets define primitive properties from the structs their node paths point to.
Last but not least there is one feature that should give the nodes good usability boost: the implicit “self” path. This is a path to the context in which the node tree is executed:
- For particle simulations this would be the particle system
- For mesh modifiers it’s the mesh object
Whenever a node has no path input specified, the “self” context (or alternatively called “this”) is used. This means that a node tree (or more often node group) can be easily reused in different contexts without having to retype the data paths every time! Furthermore the “self” path can be redefined by certain nodes, such as special “ForGroup” nodes, which allow the execution of a tree branch for each member of an object group (more on that later).