Next to wrapping data internal Blender data, RNA also comes with support for registering new types at runtime. Existing RNA types can be subclassed, and have properties and callback functions set to extend Blender. At the time of writing, Panels, Menus, Headers and Render Engines can be subclassed this way.
Python Interface Example
As an example we will subclass a Panel. This is done using standard python syntax for subclassing:
class ObjectTransformPanel(bpy.types.Panel): __label__ = "Transform" __space_type__ = "BUTTONS_WINDOW" __region_type__ = "WINDOW" __context__ = "object" def draw(self, context): ob = context.active_object layout = self.layout if not ob: return layout.row() layout.itemR(ob, "location") layout.itemR(ob, "rotation") layout.itemR(ob, "scale")
First it initializes static properties of the class, which is done by using the __identifier__ syntax. These are properties of the Panel type, with the property "registered" set to true. Some are optional, some are required. We have left out the __idname__ property as it will automatically use the python class name if we don't provide it.
Next we provide a callback called draw. This again is a function of the Panel type, with the property "registered" set true. Some callbacks are optional, some are required.
At this point Blender does not know about this new type yet, so we have to register it:
It is also possible to unregister the type:
The system is designed to wrap the mechanism that Blender uses in many places to make it extensible. This relies on (as an example) a Panel and a PanelType to be defined. The former is a specific instance, while the latter defines information about the type like flags and callback functions. The instance typically points to the type at runtime.
The RNA type registration system is designed to hook into such systems optionally, after they already work for internal C code. Afterwards, the type can be wrapped with RNA and made extensible for plugins as well.
In order to make a type subclassable, it must provide the following:
- RNA struct wrapping the Panel.
- Properties with flag PROP_REGISTER, that wrap properties of PanelType.
- Functions with flag FUNC_REGISTER, that correspond to callbacks of PanelType.
- Register, unregister and refine functions for the RNA struct.
- Callback functions that translate C function arguments into RNA function parameters.
The register function is the most important one. It gets run when bpy.types.register (or similar function) is called. It has to create a PanelType, and a corresponding StructRNA, from the data it gets from the plugin.
The first step is to validate if the data from the plugin matches what was defined in RNA, and to get the values of the properties. For this a dummy Panel and PanelType is created, which is passed to a validate() callback that is provided. If the plugin provided correct data, the properties will be stored in the dummy PanelType, otherwise registration should be aborted.
The next step is to allocate an actual new PanelType and define the corresponding RNA struct. Typically the PanelType will provide an idname property to be used as the unique identifier and name of the RNA struct.
The PanelType stores a pointer to the RNA struct, a void data pointer used by the plugin, a free function pointer to be used when the PanelType is freed, and a call function pointer. The call function pointer is used in the PanelType callbacks that translate the function arguments to RNA.
This function must free the PanelType and corresponding RNA struct. The RNA struct is given as input, and the PanelType can be retrieved from the RNA struct.