Source/Architecture/ID/ID Type

= 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.

ID Data
Here is a brief overview of some key information included in the ID structure. Its full definition can be found in the `DNA_ID.h` file.


 * Name & Type (`ID.name`)
 * The name of the ID (`pointer->id.name`) encodes the type (`ID_Type` enum) of the datablock in its first two chars. For example, a mesh that is presented in the Blender user interface with the name "Suzanne" is actually named `"MESuzanne"` in the `ID.name`. This can be used to cast an `ID *id` to the correct `ID_Type`. A macro `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 is a Scene.


 * ID Properties (`ID.properties`)
 * IDs can store random user-defined data using the `IDProperty` system.


 * Tags (`ID.tag`)
 * Tags are runtime-only information about the data-block status: does it belong the the Main data-base or not, is it evaluated data handled by the Depsgraph, is it local or linked data, etc.
 * Tags get reset on file read/write.


 * Flags (`ID.flag`)
 * Flags are persistent information about the data-block status: does it have a 'fake user' that prevents it to be deleted automatically, is it an embedded data-block, etc.


 * Recalc Flags (`ID.recalc`)
 * Flags used to control the Depsgraph Update process.


 * Users Refcounting (`ID.us`)
 * A counter of how many other data-blocks are using this one.
 * Currently in Blender, if an ID has no (`0`) users, it will not be saved on disk. To preserve an unused ID, the `LIB_FAKEUSER` flag must be set, which enforce a non-zero user count.

ID and Relationships Between Data
Ideally, an ID should own and be responsible for all sub-data it uses, and not share any kind of ownership over it with any other ID. This includes handling of its allocation, freeing, copying, etc.

Therefore, a given ID should only reference other IDs (by pointers). Referencing sub-data of another ID should be avoided as much as possible, and never done by actual pointers (conceptually, the reference should then be composed of a pointer to the ID owning that sub-data, and some form of 'path' from this owner (e.g. the name of a modifier, bone, etc.)).

Not following those principles will severely increase complexity in ID management code, and make it much less robust and maintainble than it should be.

Runtime Registration of ID Types - `IDTypeInfo`
Before early 2020, ID types were hard-coded in Blender, and their management code was spread all around BKE code base, often inside of giant `switch` statements covering all ID types.

This is being transformed into a runtime data structure (see T73719).

Ultimately this should allow to encapsulate all ID management tasks specific to an ID type into this structure, which can then be used in a fully generic way by the core ID management code.

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, file read/write, looping over other ID usages, etc.). This is an example of such a struct, in this case for Objects:

BKE_idtype.h defines the IDTypeInfo structure, its callbacks, and an API to help with handling of ID types.

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.).
 * 2) * Put the `static` callbacks and then the IDTypeInfo struct definition at the start of those files.
 * 3) * 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.
 * 4) * The IDTypeInfo should be named from its idcode (e.g. IDType_ID_OB for object).
 * 5) Add the `extern` declaration of the new `IDType` in `BKE_idtype.h`.
 * 6) Register the new `IDTypeInfo` in `id_type_init` of `idtype.c`.