Source/Architecture/ID

ID Datablocks

Objects, meshes, materials, scenes, those are all examples of ID Datablocks. They are generally defined in the DNA_{some type}_types.h header files.

ID Datablocks are blocks of memory that start with a set of common properties. In C this is modeled as a struct that embeds a struct of type ID as the first field. If it has animation data in the form of an AnimData struct, this MUST be the second field.

typedef struct Mesh {
  ID id;
  struct AnimData *adt;
  
};

The name of the datablock (pointer->id.name) encodes the type of the datablock. For example, a mesh that is presented in the Blender user interface with the name "Suzanne" is actually named "MESuzanne" in the datablock. This can be used to cast an ID *id to the correct type. A function GS(name) is available to take such a name and return a constant that indicates the ID data type: if (GS(id->name) == ID_SC) … can be used to test whether the ID datablock is a Scene.

Runtime Registration of ID Types

Before early 2020, ID datablock types were hard-coded in Blender. As part of the Code Cleanup Day effort, this was transformed into a runtime datastructure (see T73719). This section describes this new method of ID type registration.

Runtime type information is stored in a IDTypeInfo struct. This contains metadata of the struct, as well as pointers to functions for generic operations (create, copy, delete, make local, etc.). This is an example of such a struct, in this case for Objects:

IDTypeInfo IDType_ID_OB = {
    .id_code = ID_OB,
    .id_filter = FILTER_ID_OB,
    .main_listbase_index = INDEX_ID_OB,
    .struct_size = sizeof(Object),
    .name = "Object",
    .name_plural = "objects",
    .translation_context = BLT_I18NCONTEXT_ID_OBJECT,
    .flags = 0,

    .init_data = object_init_data,
    .copy_data = object_copy_data,
    .free_data = object_free_data,
    .make_local = object_make_local,
};

Adding a new ID Type

To add a new IDTypeInfo you need to:

  1. Define the IDTypeInfo in the relevant BKE's implementation file (e.g. mesh.c for ID_ME, etc.).
    • Put the static callbacks and then the IDTypeInfo struct definition at the start of those files.
    • If you need extra helpers, put only their forward declaration there, and implement them below the IDTypeInfo definition. This allows for a consistent clear separation between common info and specific APIs for each ID type implementation file.
    • The IDTypeInfo should be named from its idcode (e.g. IDType_ID_OB for object).
  2. Add the extern declaration of the new IDType in BKE_idtype.h.
  3. Register the new IDTypeInfo in id_type_init() of idtype.c.

Functions for Handling ID Types

There are various functions that can be used to help with handling of ID datablocks. Since listing them here is bound to become outdated, just read through BKE_idtype.h.