# Grease Pencil 3.0: Final technical design ### The data-block The following code describes the proposed structure of the new grease pencil data-block: ```cpp= /** * A grease pencil drawing is a set of strokes. The data is stored using * the CurvesGeometry data structure and the custom attributes within it. * It can either own the data or reference it from another GreasePencil * data-block. * * Note: When a drawing references another data-block, it will always * reference all the drawings in that data-block sequentially. */ struct GreasePencilDrawing { /** * The stroke data for this drawing. Can be nullptr in case the drawing * references its data from another data-block. */ CurvesGeometry *geometry; /** * A reference to another GreasePencil data-block. Can be nullptr in * case the drawing owns its data. * * If the data-block has multiple drawings, this drawing references * all of them sequentially. */ GreasePencil *id_reference; /** * Flag. Used to set e.g. the selection status. */ int flag; ... }; /** * Properties for layers and layer groups. */ struct GreasePencilLayerProperties { /** * Name of the layer/group. */ String name; /** * Flag. Used to set e.g. the selection, visibility, ... status. */ int flag; /** * Color tag. */ uchar color[3]; ... }; /** * A grease pencil layer is a collection of drawings. It maps them * to specific scene times on the timeline. */ struct GreasePencilLayer { /** * Settings of this layer. */ GreasePencilLayerProperties settings; /** * This Map maps a scene frame number (key) to an index into * GreasePencil->drawings (value). The frame number indicates * the first frame the drawing is shown. The end time is implicitly * defined by the next greater frame number (key) in the map. * If the value mapped to (index) is -1, no drawing is shown * at this frame. * * Example: * * {0: 0, 5: 1, 10: -1, 12: 2, 16: -1} * * In this example there are three drawings (drawing #0, * drawing #1 and drawing #2). The first drawing starts at frame 0 * and ends at frame 5 (excusive). The second drawing starts at * frame 5 and ends at frame 10. Finally, the third drawing starts * at frame 12 and ends at frame 16. * * | | | | | | | | | | |1|1|1|1|1|1|1| * Time: |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|... * Frame: [#0 ][#1 ] [#2 ] * * Note: If a drawing references another data-block, all of the drawings * in that data-block are mapped sequentially to the frames. * If another frame starts, the rest of the mapped drawings * are discarded. */ Map<int, int> frames; }; /** * A grease pencil layer group is a collection of zero or more * grease pencil layers. * It is also an element of a tree-like structure of other layer groups. */ struct GreasePencilLayerGroup { /** * Settings of this layer group. */ GreasePencilLayerProperties settings; /** * Pointer to the parent group and to zero or more children groups. */ GreasePencilLayerGroup *parent; GreasePencilLayerGroup *children; int children_size; /** * An array of GreasePencilLayer's. */ GreasePencilLayer *layers; int layer_size; }; /** * The grease pencil data-block. * * It holds a set of drawings, a tree of layer groups, and a set of layers * whithin each layer group. * * Note: When this data-block is marked as an assets, the layers * and layer groups are ignored. The asset treats the drawings * as a sequence of (one or more) frames with no timing. */ struct GreasePencil { ID id; AnimData adt; /** * An array of GreasePencilDrawing's. */ GreasePencilDrawing *drawings; int drawings_size; /** * The root layer group (is not shown in the UI). * Its parent group is always nullptr. */ GreasePencilLayerGroup *root_group; /** * An array of materials. */ struct Material **mat; int mat_size; /** * Global flag on the data-block. */ int flag; ... }; ``` ### New Object Type The new data-block will be `ID_GP` and the old one will be renamed to `ID_GD_LEGACY`. Also, there will be a new object type `OB_GPENCIL` and the old one will be renamed to `OB_GPENCIL_LEGACY`. ### Grease Pencil Operators In order to not have to redefine all the operator types, the operators will have a switch on the object type. If it's `OB_GPENCIL_LEGACY` they will run the old behavior, and with `OB_GPENCIL` they will run the new functions. The idea is that at some point we can deprecate `OB_GPENCIL_LEGACY` and remove the switch and all the old functions. ### Geometry Nodes Integration ~~As a first step the plan is to read the current frame of a grease pencil object as a single `CurvesGeometry` and feed this to geometry nodes as the input. All the curves get a `layer_id` so that they can be seperated into the layers if needed. The output will also be a single `CurvesGeometry`.~~ EDIT: Some concerns have been raised with this approach. Will have to be discussed further. ### Dependency Graph In order to allow for more granular copy-on-write updates, there will be a way to tag a single grease pencil drawing for an update. The exact way of how this will be implemented still has to be decided on. Either we add new flags that are specific to grease pencil, or there is a more general solution.