GPv3: Python API for frame, drawing and drawing attributes

This is a PR that is built on top of #122094 (thanks to @SietseB
for the initial work).

Adds the following properties and functions:
* `layer.frames`,
* `layer.frames.new(frame_number)`
* `layer.frames.remove(frame_number)`
* `layer.frames.copy(from, to)`
* `frame = layer.get_frame_at(frame_number)`
* `frame.drawing`
* `frame.frame_number`
* `frame.select`: the selection state of the keyframe in the dope sheet
* `frame.keyframe_type`
* `drawing = frame.drawing`
* `drawing.type` (`DRAWING`/`REFERENCE`)
* `drawing.user_count`: The number of keyframes that use this drawing
* `drawing.attributes`: attribute read/write access to the drawing data

To be able to access attributes on drawings, a new
`AttributeOwnerType::GreasePencilDrawing` is added.
The API in `BKE_attributes.h` is updated to handle this type.

In `rna_attributes.cc`, there is a new
`rna_def_attribute_group_grease_pencil_drawing` that defines the
attribute group. For this to work, it also defines its own rna
callback functions.

Pull Request: https://projects.blender.org/blender/blender/pulls/124787
This commit is contained in:
Falk David
2024-07-26 16:29:59 +02:00
committed by Falk David
parent 5aa0695d12
commit 6f050fecfb
10 changed files with 1155 additions and 475 deletions

View File

@@ -28,6 +28,7 @@ struct Mesh;
struct PointCloud;
struct Curves;
struct GreasePencil;
struct GreasePencilDrawing;
typedef enum AttrDomainMask {
ATTR_DOMAIN_MASK_POINT = (1 << 0),
@@ -45,6 +46,7 @@ enum class AttributeOwnerType {
PointCloud,
Curves,
GreasePencil,
GreasePencilDrawing,
};
class AttributeOwner {
@@ -64,6 +66,7 @@ class AttributeOwner {
PointCloud *get_pointcloud() const;
Curves *get_curves() const;
GreasePencil *get_grease_pencil() const;
GreasePencilDrawing *get_grease_pencil_drawing() const;
};
#define ATTR_DOMAIN_AS_MASK(domain) ((AttrDomainMask)((1 << (int)(domain))))

View File

@@ -151,7 +151,14 @@ class Drawing : public ::GreasePencilDrawing {
* Returns true for when this drawing has more than one user.
*/
bool is_instanced() const;
/**
* Return true if this drawing has at least one user.
*/
bool has_users() const;
/**
* Return the number of users (keyframes) of this drawing.
*/
int user_count() const;
};
static_assert(sizeof(Drawing) == sizeof(::GreasePencilDrawing));
@@ -742,6 +749,10 @@ inline bool Drawing::has_users() const
{
return this->runtime->user_count.load(std::memory_order_relaxed) > 0;
}
inline int Drawing::user_count() const
{
return this->runtime->user_count.load(std::memory_order_relaxed);
}
inline bool TreeNode::is_group() const
{
@@ -1019,6 +1030,8 @@ inline bool GreasePencil::has_active_group() const
return (this->active_node != nullptr) && (this->active_node->wrap().is_group());
}
bool BKE_grease_pencil_drawing_attribute_required(const GreasePencilDrawing *, const char *name);
void *BKE_grease_pencil_add(Main *bmain, const char *name);
GreasePencil *BKE_grease_pencil_new_nomain();
GreasePencil *BKE_grease_pencil_copy_for_eval(const GreasePencil *grease_pencil_src);

View File

@@ -97,6 +97,13 @@ GreasePencil *AttributeOwner::get_grease_pencil() const
return reinterpret_cast<GreasePencil *>(ptr_);
}
GreasePencilDrawing *AttributeOwner::get_grease_pencil_drawing() const
{
BLI_assert(this->is_valid());
BLI_assert(type_ == AttributeOwnerType::GreasePencilDrawing);
return reinterpret_cast<GreasePencilDrawing *>(ptr_);
}
struct DomainInfo {
CustomData *customdata = nullptr;
int length = 0;
@@ -152,6 +159,14 @@ static std::array<DomainInfo, ATTR_DOMAIN_NUM> get_domains(const AttributeOwner
info[int(AttrDomain::Layer)].length = grease_pencil->layers().size();
break;
}
case AttributeOwnerType::GreasePencilDrawing: {
blender::bke::greasepencil::Drawing &drawing = owner.get_grease_pencil_drawing()->wrap();
info[int(AttrDomain::Point)].customdata = &drawing.geometry.point_data;
info[int(AttrDomain::Point)].length = drawing.geometry.point_num;
info[int(AttrDomain::Curve)].customdata = &drawing.geometry.curve_data;
info[int(AttrDomain::Curve)].length = drawing.geometry.curve_num;
break;
}
}
return info;
@@ -182,6 +197,10 @@ static std::optional<blender::bke::MutableAttributeAccessor> get_attribute_acces
GreasePencil &grease_pencil = *owner.get_grease_pencil();
return grease_pencil.attributes_for_write();
}
case AttributeOwnerType::GreasePencilDrawing: {
blender::bke::greasepencil::Drawing &drawing = owner.get_grease_pencil_drawing()->wrap();
return drawing.strokes_for_write().attributes_for_write();
}
}
return {};
}
@@ -747,6 +766,8 @@ bool BKE_attribute_required(const AttributeOwner &owner, const char *name)
return BKE_mesh_attribute_required(name);
case AttributeOwnerType::GreasePencil:
return false;
case AttributeOwnerType::GreasePencilDrawing:
return BKE_grease_pencil_drawing_attribute_required(owner.get_grease_pencil_drawing(), name);
}
return false;
}
@@ -809,6 +830,9 @@ int *BKE_attributes_active_index_p(AttributeOwner &owner)
case AttributeOwnerType::GreasePencil: {
return &(owner.get_grease_pencil())->attributes_active_index;
}
case AttributeOwnerType::GreasePencilDrawing: {
return &(owner.get_grease_pencil_drawing())->geometry.attributes_active_index;
}
}
return nullptr;
}

View File

@@ -71,6 +71,8 @@ using blender::Span;
using blender::uint3;
using blender::VectorSet;
static const char *ATTR_POSITION = "position";
/* Forward declarations. */
static void read_drawing_array(GreasePencil &grease_pencil, BlendDataReader *reader);
static void write_drawing_array(GreasePencil &grease_pencil, BlendWriter *writer);
@@ -1754,6 +1756,12 @@ std::optional<MutableSpan<float3>> GreasePencilDrawingEditHints::positions_for_w
/** \name Grease Pencil kernel functions
* \{ */
bool BKE_grease_pencil_drawing_attribute_required(const GreasePencilDrawing * /*drawing*/,
const char *name)
{
return STREQ(name, ATTR_POSITION);
}
void *BKE_grease_pencil_add(Main *bmain, const char *name)
{
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(BKE_id_new(bmain, ID_GP, name));

View File

@@ -120,6 +120,7 @@ set(APISRC
rna_camera_api.cc
rna_curve_api.cc
rna_fcurve_api.cc
rna_grease_pencil_api.cc
rna_image_api.cc
rna_lattice_api.cc
rna_main_api.cc

View File

@@ -4815,7 +4815,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_dynamicpaint.cc", nullptr, RNA_def_dynamic_paint},
{"rna_fcurve.cc", "rna_fcurve_api.cc", RNA_def_fcurve},
{"rna_annotations.cc", nullptr, RNA_def_annotations},
{"rna_grease_pencil.cc", nullptr, RNA_def_grease_pencil},
{"rna_grease_pencil.cc", "rna_grease_pencil_api.cc", RNA_def_grease_pencil},
{"rna_curves.cc", nullptr, RNA_def_curves},
{"rna_image.cc", "rna_image_api.cc", RNA_def_image},
{"rna_key.cc", nullptr, RNA_def_key},

View File

@@ -16,6 +16,7 @@
#include "DNA_curves_types.h"
#include "DNA_customdata_types.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_pointcloud_types.h"
@@ -185,18 +186,49 @@ const EnumPropertyItem rna_enum_attribute_curves_domain_items[] = {
static AttributeOwner owner_from_attribute_pointer_rna(PointerRNA *ptr)
{
ID *id = ptr->owner_id;
/* TODO: For non-ID attribute owners, iterate through the ID and find the owner that owns the
* `CustomDataLayer` that points to `ptr->data`. */
return AttributeOwner::from_id(id);
ID *owner_id = ptr->owner_id;
const CustomDataLayer *layer = static_cast<const CustomDataLayer *>(ptr->data);
/* TODO: Because we don't know the path to the `ptr`, we need to look though all possible
* candidates and search for the `layer` currently. This should be just a simple lookup. */
if (GS(owner_id->name) == ID_GP) {
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(owner_id);
/* First check the layer attributes. */
CustomData *layers_data = &grease_pencil->layers_data;
for (int i = 0; i < layers_data->totlayer; i++) {
if (&layers_data->layers[i] == layer) {
return AttributeOwner(AttributeOwnerType::GreasePencil, grease_pencil);
}
}
/* Now check all the drawings. */
for (GreasePencilDrawingBase *base : grease_pencil->drawings()) {
if (base->type == GP_DRAWING) {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(base);
CustomData *curve_data = &drawing->geometry.curve_data;
for (int i = 0; i < curve_data->totlayer; i++) {
if (&curve_data->layers[i] == layer) {
return AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
}
}
CustomData *point_data = &drawing->geometry.point_data;
for (int i = 0; i < point_data->totlayer; i++) {
if (&point_data->layers[i] == layer) {
return AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
}
}
}
}
}
return AttributeOwner::from_id(owner_id);
}
static AttributeOwner owner_from_pointer_rna(PointerRNA *ptr)
{
ID *id = ptr->owner_id;
/* TODO: For non-ID attribute owners, check the `ptr->type` to derive the `AttributeOwnerType`
/* For non-ID attribute owners, check the `ptr->type` to derive the `AttributeOwnerType`
* and construct an `AttributeOwner` from that type and `ptr->data`. */
return AttributeOwner::from_id(id);
if (ptr->type == &RNA_GreasePencilDrawing) {
return AttributeOwner(AttributeOwnerType::GreasePencilDrawing, ptr->data);
}
return AttributeOwner::from_id(ptr->owner_id);
}
static std::optional<std::string> rna_Attribute_path(const PointerRNA *ptr)
@@ -456,7 +488,7 @@ static void rna_StringAttributeValue_s_set(PointerRNA *ptr, const char *value)
/* Attribute Group */
static PointerRNA rna_AttributeGroup_new(
static PointerRNA rna_AttributeGroupID_new(
ID *id, ReportList *reports, const char *name, const int type, const int domain)
{
AttributeOwner owner = AttributeOwner::from_id(id);
@@ -484,7 +516,7 @@ static PointerRNA rna_AttributeGroup_new(
return ptr;
}
static void rna_AttributeGroup_remove(ID *id, ReportList *reports, PointerRNA *attribute_ptr)
static void rna_AttributeGroupID_remove(ID *id, ReportList *reports, PointerRNA *attribute_ptr)
{
AttributeOwner owner = AttributeOwner::from_id(id);
const CustomDataLayer *layer = (const CustomDataLayer *)attribute_ptr->data;
@@ -604,40 +636,40 @@ int rna_AttributeGroup_length(PointerRNA *ptr)
return BKE_attributes_length(owner, ATTR_DOMAIN_MASK_ALL, CD_MASK_PROP_ALL);
}
static int rna_AttributeGroup_active_index_get(PointerRNA *ptr)
static int rna_AttributeGroupID_active_index_get(PointerRNA *ptr)
{
AttributeOwner owner = owner_from_pointer_rna(ptr);
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
return *BKE_attributes_active_index_p(owner);
}
static PointerRNA rna_AttributeGroup_active_get(PointerRNA *ptr)
static PointerRNA rna_AttributeGroupID_active_get(PointerRNA *ptr)
{
AttributeOwner owner = owner_from_pointer_rna(ptr);
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
CustomDataLayer *layer = BKE_attributes_active_get(owner);
PointerRNA attribute_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Attribute, layer);
return attribute_ptr;
}
static void rna_AttributeGroup_active_set(PointerRNA *ptr,
PointerRNA attribute_ptr,
ReportList * /*reports*/)
static void rna_AttributeGroupID_active_set(PointerRNA *ptr,
PointerRNA attribute_ptr,
ReportList * /*reports*/)
{
AttributeOwner owner = owner_from_pointer_rna(ptr);
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
CustomDataLayer *layer = static_cast<CustomDataLayer *>(attribute_ptr.data);
BKE_attributes_active_set(owner, layer->name);
}
static void rna_AttributeGroup_active_index_set(PointerRNA *ptr, int value)
static void rna_AttributeGroupID_active_index_set(PointerRNA *ptr, int value)
{
AttributeOwner owner = owner_from_pointer_rna(ptr);
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
*BKE_attributes_active_index_p(owner) = value;
}
static void rna_AttributeGroup_active_index_range(
static void rna_AttributeGroupID_active_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
AttributeOwner owner = owner_from_pointer_rna(ptr);
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
*min = 0;
*max = BKE_attributes_length(owner, ATTR_DOMAIN_MASK_ALL, CD_MASK_PROP_ALL);
@@ -650,65 +682,6 @@ static void rna_AttributeGroup_update_active(Main *bmain, Scene *scene, PointerR
rna_Attribute_update_data(bmain, scene, ptr);
}
static PointerRNA rna_AttributeGroup_active_color_get(PointerRNA *ptr)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
CustomDataLayer *layer = BKE_attribute_search_for_write(
owner,
BKE_id_attributes_active_color_name(ptr->owner_id),
CD_MASK_COLOR_ALL,
ATTR_DOMAIN_MASK_COLOR);
PointerRNA attribute_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Attribute, layer);
return attribute_ptr;
}
static void rna_AttributeGroup_active_color_set(PointerRNA *ptr,
PointerRNA attribute_ptr,
ReportList * /*reports*/)
{
ID *id = ptr->owner_id;
CustomDataLayer *layer = static_cast<CustomDataLayer *>(attribute_ptr.data);
BKE_id_attributes_active_color_set(id, layer->name);
}
static int rna_AttributeGroup_active_color_index_get(PointerRNA *ptr)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
const CustomDataLayer *layer = BKE_attribute_search(
owner,
BKE_id_attributes_active_color_name(ptr->owner_id),
CD_MASK_COLOR_ALL,
ATTR_DOMAIN_MASK_COLOR);
return BKE_attribute_to_index(owner, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL);
}
static void rna_AttributeGroup_active_color_index_set(PointerRNA *ptr, int value)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
CustomDataLayer *layer = BKE_attribute_from_index(
owner, value, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL);
if (!layer) {
fprintf(stderr, "%s: error setting active color index to %d\n", __func__, value);
return;
}
BKE_id_attributes_active_color_set(ptr->owner_id, layer->name);
}
static void rna_AttributeGroup_active_color_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
*min = 0;
*max = BKE_attributes_length(owner, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL);
*softmin = *min;
*softmax = *max;
}
static void rna_AttributeGroup_update_active_color(Main * /*bmain*/,
Scene * /*scene*/,
PointerRNA *ptr)
@@ -722,7 +695,66 @@ static void rna_AttributeGroup_update_active_color(Main * /*bmain*/,
}
}
static int rna_AttributeGroup_render_color_index_get(PointerRNA *ptr)
static PointerRNA rna_AttributeGroupMesh_active_color_get(PointerRNA *ptr)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
CustomDataLayer *layer = BKE_attribute_search_for_write(
owner,
BKE_id_attributes_active_color_name(ptr->owner_id),
CD_MASK_COLOR_ALL,
ATTR_DOMAIN_MASK_COLOR);
PointerRNA attribute_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Attribute, layer);
return attribute_ptr;
}
static void rna_AttributeGroupMesh_active_color_set(PointerRNA *ptr,
PointerRNA attribute_ptr,
ReportList * /*reports*/)
{
ID *id = ptr->owner_id;
CustomDataLayer *layer = static_cast<CustomDataLayer *>(attribute_ptr.data);
BKE_id_attributes_active_color_set(id, layer->name);
}
static int rna_AttributeGroupMesh_active_color_index_get(PointerRNA *ptr)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
const CustomDataLayer *layer = BKE_attribute_search(
owner,
BKE_id_attributes_active_color_name(ptr->owner_id),
CD_MASK_COLOR_ALL,
ATTR_DOMAIN_MASK_COLOR);
return BKE_attribute_to_index(owner, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL);
}
static void rna_AttributeGroupMesh_active_color_index_set(PointerRNA *ptr, int value)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
CustomDataLayer *layer = BKE_attribute_from_index(
owner, value, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL);
if (!layer) {
fprintf(stderr, "%s: error setting active color index to %d\n", __func__, value);
return;
}
BKE_id_attributes_active_color_set(ptr->owner_id, layer->name);
}
static void rna_AttributeGroupMesh_active_color_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
*min = 0;
*max = BKE_attributes_length(owner, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL);
*softmin = *min;
*softmax = *max;
}
static int rna_AttributeGroupMesh_render_color_index_get(PointerRNA *ptr)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
const CustomDataLayer *layer = BKE_id_attributes_color_find(
@@ -731,7 +763,7 @@ static int rna_AttributeGroup_render_color_index_get(PointerRNA *ptr)
return BKE_attribute_to_index(owner, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL);
}
static void rna_AttributeGroup_render_color_index_set(PointerRNA *ptr, int value)
static void rna_AttributeGroupMesh_render_color_index_set(PointerRNA *ptr, int value)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
CustomDataLayer *layer = BKE_attribute_from_index(
@@ -745,7 +777,7 @@ static void rna_AttributeGroup_render_color_index_set(PointerRNA *ptr, int value
BKE_id_attributes_default_color_set(ptr->owner_id, layer->name);
}
static void rna_AttributeGroup_render_color_index_range(
static void rna_AttributeGroupMesh_render_color_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
AttributeOwner owner = AttributeOwner::from_id(ptr->owner_id);
@@ -756,7 +788,7 @@ static void rna_AttributeGroup_render_color_index_range(
*softmax = *max;
}
static void rna_AttributeGroup_default_color_name_get(PointerRNA *ptr, char *value)
static void rna_AttributeGroupMesh_default_color_name_get(PointerRNA *ptr, char *value)
{
const ID *id = ptr->owner_id;
const char *name = BKE_id_attributes_default_color_name(id);
@@ -767,14 +799,14 @@ static void rna_AttributeGroup_default_color_name_get(PointerRNA *ptr, char *val
strcpy(value, name);
}
static int rna_AttributeGroup_default_color_name_length(PointerRNA *ptr)
static int rna_AttributeGroupMesh_default_color_name_length(PointerRNA *ptr)
{
const ID *id = ptr->owner_id;
const char *name = BKE_id_attributes_default_color_name(id);
return name ? strlen(name) : 0;
}
static void rna_AttributeGroup_default_color_name_set(PointerRNA *ptr, const char *value)
static void rna_AttributeGroupMesh_default_color_name_set(PointerRNA *ptr, const char *value)
{
ID *id = ptr->owner_id;
if (GS(id->name) == ID_ME) {
@@ -786,7 +818,7 @@ static void rna_AttributeGroup_default_color_name_set(PointerRNA *ptr, const cha
}
}
static void rna_AttributeGroup_active_color_name_get(PointerRNA *ptr, char *value)
static void rna_AttributeGroupMesh_active_color_name_get(PointerRNA *ptr, char *value)
{
const ID *id = ptr->owner_id;
const char *name = BKE_id_attributes_active_color_name(id);
@@ -797,14 +829,14 @@ static void rna_AttributeGroup_active_color_name_get(PointerRNA *ptr, char *valu
strcpy(value, name);
}
static int rna_AttributeGroup_active_color_name_length(PointerRNA *ptr)
static int rna_AttributeGroupMesh_active_color_name_length(PointerRNA *ptr)
{
const ID *id = ptr->owner_id;
const char *name = BKE_id_attributes_active_color_name(id);
return name ? strlen(name) : 0;
}
static void rna_AttributeGroup_active_color_name_set(PointerRNA *ptr, const char *value)
static void rna_AttributeGroupMesh_active_color_name_set(PointerRNA *ptr, const char *value)
{
ID *id = ptr->owner_id;
if (GS(id->name) == ID_ME) {
@@ -816,6 +848,96 @@ static void rna_AttributeGroup_active_color_name_set(PointerRNA *ptr, const char
}
}
static PointerRNA rna_AttributeGroupGreasePencilDrawing_new(ID *grease_pencil_id,
GreasePencilDrawing *drawing,
ReportList *reports,
const char *name,
const int type,
const int domain)
{
AttributeOwner owner = AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
CustomDataLayer *layer = BKE_attribute_new(
owner, name, eCustomDataType(type), AttrDomain(domain), reports);
if (!layer) {
return PointerRNA_NULL;
}
DEG_id_tag_update(grease_pencil_id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, grease_pencil_id);
PointerRNA ptr = RNA_pointer_create(grease_pencil_id, &RNA_Attribute, layer);
return ptr;
}
static void rna_AttributeGroupGreasePencilDrawing_remove(ID *grease_pencil_id,
GreasePencilDrawing *drawing,
ReportList *reports,
PointerRNA *attribute_ptr)
{
AttributeOwner owner = AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
const CustomDataLayer *layer = (const CustomDataLayer *)attribute_ptr->data;
BKE_attribute_remove(owner, layer->name, reports);
RNA_POINTER_INVALIDATE(attribute_ptr);
DEG_id_tag_update(grease_pencil_id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, grease_pencil_id);
}
static PointerRNA rna_AttributeGroupGreasePencilDrawing_active_get(PointerRNA *ptr)
{
GreasePencilDrawing *drawing = static_cast<GreasePencilDrawing *>(ptr->data);
AttributeOwner owner = AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
CustomDataLayer *layer = BKE_attributes_active_get(owner);
PointerRNA attribute_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Attribute, layer);
return attribute_ptr;
}
static void rna_AttributeGroupGreasePencilDrawing_active_set(PointerRNA *ptr,
PointerRNA attribute_ptr,
ReportList * /*reports*/)
{
GreasePencilDrawing *drawing = static_cast<GreasePencilDrawing *>(ptr->data);
AttributeOwner owner = AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
CustomDataLayer *layer = static_cast<CustomDataLayer *>(attribute_ptr.data);
BKE_attributes_active_set(owner, layer->name);
}
static bool rna_AttributeGroupGreasePencilDrawing_active_poll(PointerRNA *ptr,
const PointerRNA value)
{
AttributeOwner owner = owner_from_attribute_pointer_rna(const_cast<PointerRNA *>(&value));
return owner.is_valid() && owner.type() == AttributeOwnerType::GreasePencilDrawing &&
owner.get_grease_pencil_drawing() == static_cast<GreasePencilDrawing *>(ptr->data);
}
static int rna_AttributeGroupGreasePencilDrawing_active_index_get(PointerRNA *ptr)
{
GreasePencilDrawing *drawing = static_cast<GreasePencilDrawing *>(ptr->data);
AttributeOwner owner = AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
return *BKE_attributes_active_index_p(owner);
}
static void rna_AttributeGroupGreasePencilDrawing_active_index_set(PointerRNA *ptr, int value)
{
GreasePencilDrawing *drawing = static_cast<GreasePencilDrawing *>(ptr->data);
AttributeOwner owner = AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
*BKE_attributes_active_index_p(owner) = value;
}
static void rna_AttributeGroupGreasePencilDrawing_active_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
GreasePencilDrawing *drawing = static_cast<GreasePencilDrawing *>(ptr->data);
AttributeOwner owner = AttributeOwner(AttributeOwnerType::GreasePencilDrawing, drawing);
*min = 0;
*max = BKE_attributes_length(owner, ATTR_DOMAIN_MASK_ALL, CD_MASK_PROP_ALL);
*softmin = *min;
*softmax = *max;
}
#else
static void rna_def_attribute_float(BlenderRNA *brna)
@@ -1315,7 +1437,7 @@ static void rna_def_attribute_group_id_common(StructRNA *srna)
PropertyRNA *parm;
/* API */
func = RNA_def_function(srna, "new", "rna_AttributeGroup_new");
func = RNA_def_function(srna, "new", "rna_AttributeGroupID_new");
RNA_def_function_ui_description(func, "Add attribute to geometry");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_string(func, "name", "Attribute", 0, "Name", "Name of geometry attribute");
@@ -1337,7 +1459,7 @@ static void rna_def_attribute_group_id_common(StructRNA *srna)
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_AttributeGroup_remove");
func = RNA_def_function(srna, "remove", "rna_AttributeGroupID_remove");
RNA_def_function_ui_description(func, "Remove attribute from geometry");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "attribute", "Attribute", "", "Geometry Attribute");
@@ -1348,8 +1470,11 @@ static void rna_def_attribute_group_id_common(StructRNA *srna)
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Attribute");
RNA_def_property_ui_text(prop, "Active Attribute", "Active attribute");
RNA_def_property_pointer_funcs(
prop, "rna_AttributeGroup_active_get", "rna_AttributeGroup_active_set", nullptr, nullptr);
RNA_def_property_pointer_funcs(prop,
"rna_AttributeGroupID_active_get",
"rna_AttributeGroupID_active_set",
nullptr,
nullptr);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active");
@@ -1357,9 +1482,9 @@ static void rna_def_attribute_group_id_common(StructRNA *srna)
RNA_def_property_ui_text(prop, "Active Attribute Index", "Active attribute index");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_funcs(prop,
"rna_AttributeGroup_active_index_get",
"rna_AttributeGroup_active_index_set",
"rna_AttributeGroup_active_index_range");
"rna_AttributeGroupID_active_index_get",
"rna_AttributeGroupID_active_index_set",
"rna_AttributeGroupID_active_index_range");
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active");
}
@@ -1380,8 +1505,8 @@ static void rna_def_attribute_group_mesh(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Attribute");
RNA_def_property_ui_text(prop, "Active Color", "Active color attribute for display and editing");
RNA_def_property_pointer_funcs(prop,
"rna_AttributeGroup_active_color_get",
"rna_AttributeGroup_active_color_set",
"rna_AttributeGroupMesh_active_color_get",
"rna_AttributeGroupMesh_active_color_set",
nullptr,
nullptr);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
@@ -1391,9 +1516,9 @@ static void rna_def_attribute_group_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Color Index", "Active color attribute index");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_funcs(prop,
"rna_AttributeGroup_active_color_index_get",
"rna_AttributeGroup_active_color_index_set",
"rna_AttributeGroup_active_color_index_range");
"rna_AttributeGroupMesh_active_color_index_get",
"rna_AttributeGroupMesh_active_color_index_set",
"rna_AttributeGroupMesh_active_color_index_range");
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active_color");
prop = RNA_def_property(srna, "render_color_index", PROP_INT, PROP_NONE);
@@ -1402,17 +1527,17 @@ static void rna_def_attribute_group_mesh(BlenderRNA *brna)
"The index of the color attribute used as a fallback for rendering");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_funcs(prop,
"rna_AttributeGroup_render_color_index_get",
"rna_AttributeGroup_render_color_index_set",
"rna_AttributeGroup_render_color_index_range");
"rna_AttributeGroupMesh_render_color_index_get",
"rna_AttributeGroupMesh_render_color_index_set",
"rna_AttributeGroupMesh_render_color_index_range");
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active_color");
prop = RNA_def_property(srna, "default_color_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_maxlength(prop, MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX);
RNA_def_property_string_funcs(prop,
"rna_AttributeGroup_default_color_name_get",
"rna_AttributeGroup_default_color_name_length",
"rna_AttributeGroup_default_color_name_set");
"rna_AttributeGroupMesh_default_color_name_get",
"rna_AttributeGroupMesh_default_color_name_length",
"rna_AttributeGroupMesh_default_color_name_set");
RNA_def_property_ui_text(
prop,
"Default Color Attribute",
@@ -1421,9 +1546,9 @@ static void rna_def_attribute_group_mesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "active_color_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_maxlength(prop, MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX);
RNA_def_property_string_funcs(prop,
"rna_AttributeGroup_active_color_name_get",
"rna_AttributeGroup_active_color_name_length",
"rna_AttributeGroup_active_color_name_set");
"rna_AttributeGroupMesh_active_color_name_get",
"rna_AttributeGroupMesh_active_color_name_length",
"rna_AttributeGroupMesh_active_color_name_set");
RNA_def_property_ui_text(prop,
"Active Color Attribute",
"The name of the active color attribute for display and editing");
@@ -1462,6 +1587,69 @@ static void rna_def_attribute_group_grease_pencil(BlenderRNA *brna)
rna_def_attribute_group_id_common(srna);
}
static void rna_def_attribute_group_grease_pencil_drawing(BlenderRNA *brna)
{
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
StructRNA *srna;
srna = RNA_def_struct(brna, "AttributeGroupGreasePencilDrawing", nullptr);
RNA_def_struct_ui_text(srna, "Attribute Group", "Group of geometry attributes");
RNA_def_struct_sdna(srna, "GreasePencilDrawing");
/* API */
func = RNA_def_function(srna, "new", "rna_AttributeGroupGreasePencilDrawing_new");
RNA_def_function_ui_description(func, "Add attribute to geometry");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
parm = RNA_def_string(func, "name", "Attribute", 0, "Name", "Name of geometry attribute");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_enum(
func, "type", rna_enum_attribute_type_items, CD_PROP_FLOAT, "Type", "Attribute type");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_enum(func,
"domain",
rna_enum_attribute_domain_items,
int(AttrDomain::Point),
"Domain",
"Type of element that attribute is stored on");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_pointer(func, "attribute", "Attribute", "", "New geometry attribute");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_AttributeGroupGreasePencilDrawing_remove");
RNA_def_function_ui_description(func, "Remove attribute from geometry");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "attribute", "Attribute", "", "Geometry Attribute");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
/* Active */
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Attribute");
RNA_def_property_ui_text(prop, "Active Attribute", "Active attribute");
RNA_def_property_pointer_funcs(prop,
"rna_AttributeGroupGreasePencilDrawing_active_get",
"rna_AttributeGroupGreasePencilDrawing_active_set",
nullptr,
"rna_AttributeGroupGreasePencilDrawing_active_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active");
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE);
RNA_def_property_ui_text(prop, "Active Attribute Index", "Active attribute index");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_funcs(prop,
"rna_AttributeGroupGreasePencilDrawing_active_index_get",
"rna_AttributeGroupGreasePencilDrawing_active_index_set",
"rna_AttributeGroupGreasePencilDrawing_active_index_range");
RNA_def_property_update(prop, 0, "rna_AttributeGroup_update_active");
}
void rna_def_attributes_common(StructRNA *srna, const AttributeOwnerType type)
{
PropertyRNA *prop;
@@ -1492,6 +1680,9 @@ void rna_def_attributes_common(StructRNA *srna, const AttributeOwnerType type)
case AttributeOwnerType::GreasePencil:
RNA_def_property_srna(prop, "AttributeGroupGreasePencil");
break;
case AttributeOwnerType::GreasePencilDrawing:
RNA_def_property_srna(prop, "AttributeGroupGreasePencilDrawing");
break;
}
prop = RNA_def_property(srna, "color_attributes", PROP_COLLECTION, PROP_NONE);
@@ -1519,6 +1710,9 @@ void rna_def_attributes_common(StructRNA *srna, const AttributeOwnerType type)
case AttributeOwnerType::GreasePencil:
RNA_def_property_srna(prop, "AttributeGroupGreasePencil");
break;
case AttributeOwnerType::GreasePencilDrawing:
RNA_def_property_srna(prop, "AttributeGroupGreasePencilDrawing");
break;
}
}
@@ -1529,5 +1723,6 @@ void RNA_def_attribute(BlenderRNA *brna)
rna_def_attribute_group_point_cloud(brna);
rna_def_attribute_group_curves(brna);
rna_def_attribute_group_grease_pencil(brna);
rna_def_attribute_group_grease_pencil_drawing(brna);
}
#endif

View File

@@ -1,4 +1,4 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
@@ -12,6 +12,7 @@
#include "BLI_string.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_scene_types.h"
#include "RNA_access.hh"
#include "RNA_define.hh"
@@ -21,12 +22,6 @@
#include "WM_api.hh"
const EnumPropertyItem rna_enum_tree_node_move_type_items[] = {
{-1, "DOWN", 0, "Down", ""},
{1, "UP", 0, "Up", ""},
{0, nullptr, 0, nullptr, nullptr},
};
#ifdef RNA_RUNTIME
# include <fmt/format.h>
@@ -74,6 +69,107 @@ static void rna_grease_pencil_dependency_update(Main *bmain, Scene * /*scene*/,
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, rna_grease_pencil(ptr));
}
static int rna_Drawing_user_count_get(PointerRNA *ptr)
{
using namespace blender::bke::greasepencil;
const GreasePencilDrawing *drawing = static_cast<const GreasePencilDrawing *>(ptr->data);
return drawing->wrap().user_count();
}
static void rna_GreasePencilLayer_frames_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
using namespace blender::bke::greasepencil;
Layer &layer = static_cast<GreasePencilLayer *>(ptr->data)->wrap();
blender::Span<FramesMapKeyT> sorted_keys = layer.sorted_keys();
rna_iterator_array_begin(
iter, (void *)sorted_keys.data(), sizeof(FramesMapKeyT), sorted_keys.size(), false, nullptr);
}
static PointerRNA rna_GreasePencilLayer_frames_get(CollectionPropertyIterator *iter)
{
using namespace blender::bke::greasepencil;
const FramesMapKeyT frame_key = *static_cast<FramesMapKeyT *>(rna_iterator_array_get(iter));
const Layer &layer = static_cast<GreasePencilLayer *>(iter->parent.data)->wrap();
const GreasePencilFrame *frame = layer.frames().lookup_ptr(frame_key);
return rna_pointer_inherit_refine(&iter->parent,
&RNA_GreasePencilFrame,
static_cast<void *>(const_cast<GreasePencilFrame *>(frame)));
}
static int rna_GreasePencilLayer_frames_length(PointerRNA *ptr)
{
using namespace blender::bke::greasepencil;
Layer &layer = static_cast<GreasePencilLayer *>(ptr->data)->wrap();
return layer.frames().size();
}
static bool rna_GreasePencilLayer_frames_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
{
using namespace blender::bke::greasepencil;
GreasePencil &grease_pencil = *rna_grease_pencil(ptr);
Layer &layer = static_cast<GreasePencilLayer *>(ptr->data)->wrap();
if (index < 0 || index >= layer.sorted_keys().size()) {
return false;
}
const FramesMapKeyT frame_key = layer.sorted_keys()[index];
const GreasePencilFrame *frame = layer.frames().lookup_ptr(frame_key);
r_ptr->owner_id = &grease_pencil.id;
r_ptr->type = &RNA_GreasePencilFrame;
r_ptr->data = static_cast<void *>(const_cast<GreasePencilFrame *>(frame));
return true;
}
static std::pair<int, const blender::bke::greasepencil::Layer *> find_layer_of_frame(
const GreasePencil &grease_pencil, const GreasePencilFrame &find_frame)
{
using namespace blender::bke::greasepencil;
for (const Layer *layer : grease_pencil.layers()) {
for (const auto &[key, frame] : layer->frames().items()) {
if (&frame == &find_frame) {
return {int(key), layer};
}
}
}
return {0, nullptr};
}
static PointerRNA rna_Frame_drawing_get(PointerRNA *ptr)
{
using namespace blender::bke::greasepencil;
const GreasePencil &grease_pencil = *rna_grease_pencil(ptr);
GreasePencilFrame &frame_to_find = *static_cast<GreasePencilFrame *>(ptr->data);
if (frame_to_find.is_end()) {
return PointerRNA_NULL;
}
/* RNA doesn't give access to the parented layer object, so we have to iterate over all layers
* and search for the matching GreasePencilFrame pointer in the frames collection. */
auto [frame_number, this_layer] = find_layer_of_frame(grease_pencil, frame_to_find);
if (this_layer == nullptr) {
return PointerRNA_NULL;
}
const Drawing *drawing = grease_pencil.get_drawing_at(*this_layer, frame_number);
return rna_pointer_inherit_refine(
ptr, &RNA_GreasePencilDrawing, static_cast<void *>(const_cast<Drawing *>(drawing)));
}
static int rna_Frame_frame_number_get(PointerRNA *ptr)
{
using namespace blender::bke::greasepencil;
const GreasePencil &grease_pencil = *rna_grease_pencil(ptr);
GreasePencilFrame &frame_to_find = *static_cast<GreasePencilFrame *>(ptr->data);
/* RNA doesn't give access to the parented layer object, so we have to iterate over all layers
* and search for the matching GreasePencilFrame pointer in the frames collection. */
auto [frame_number, this_layer] = find_layer_of_frame(grease_pencil, frame_to_find);
/* Layer should exist. */
BLI_assert(this_layer != nullptr);
return frame_number;
}
static void rna_grease_pencil_layer_mask_name_get(PointerRNA *ptr, char *dst)
{
using namespace blender;
@@ -254,206 +350,6 @@ static PointerRNA rna_GreasePencilLayer_parent_layer_group_get(PointerRNA *ptr)
ptr, &RNA_GreasePencilLayerGroup, static_cast<void *>(layer_group));
}
static PointerRNA rna_GreasePencil_layer_group_new(GreasePencil *grease_pencil,
const char *name,
PointerRNA *parent_group_ptr)
{
using namespace blender::bke::greasepencil;
LayerGroup *parent_group;
if (parent_group_ptr && parent_group_ptr->data) {
parent_group = static_cast<LayerGroup *>(parent_group_ptr->data);
}
else {
parent_group = &grease_pencil->root_group();
}
LayerGroup *new_layer_group = &grease_pencil->add_layer_group(*parent_group, name);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
PointerRNA ptr = RNA_pointer_create(
&grease_pencil->id, &RNA_GreasePencilLayerGroup, new_layer_group);
return ptr;
}
static void rna_GreasePencil_layer_group_remove(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr,
bool keep_children)
{
using namespace blender::bke::greasepencil;
LayerGroup &layer_group = *static_cast<LayerGroup *>(layer_group_ptr->data);
grease_pencil->remove_group(layer_group, keep_children);
RNA_POINTER_INVALIDATE(layer_group_ptr);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_SELECTED, grease_pencil);
}
static void rna_GreasePencil_layer_group_move(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr,
int direction)
{
if (direction == 0) {
return;
}
blender::bke::greasepencil::TreeNode &layer_group_node =
static_cast<blender::bke::greasepencil::LayerGroup *>(layer_group_ptr->data)->as_node();
switch (direction) {
case -1:
grease_pencil->move_node_down(layer_group_node, 1);
break;
case 1:
grease_pencil->move_node_up(layer_group_node, 1);
break;
}
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_group_move_top(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr)
{
blender::bke::greasepencil::TreeNode &layer_group_node =
static_cast<blender::bke::greasepencil::LayerGroup *>(layer_group_ptr->data)->as_node();
grease_pencil->move_node_top(layer_group_node);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_group_move_bottom(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr)
{
blender::bke::greasepencil::TreeNode &layer_group_node =
static_cast<blender::bke::greasepencil::LayerGroup *>(layer_group_ptr->data)->as_node();
grease_pencil->move_node_bottom(layer_group_node);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_group_move_to_layer_group(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr,
PointerRNA *parent_group_ptr)
{
using namespace blender::bke::greasepencil;
TreeNode &layer_group_node = static_cast<LayerGroup *>(layer_group_ptr->data)->as_node();
LayerGroup *parent_group;
if (parent_group_ptr && parent_group_ptr->data) {
parent_group = static_cast<LayerGroup *>(parent_group_ptr->data);
}
else {
parent_group = &grease_pencil->root_group();
}
grease_pencil->move_node_into(layer_group_node, *parent_group);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static GreasePencilLayer *rna_GreasePencil_layer_new(GreasePencil *grease_pencil,
const char *name,
const bool set_active,
PointerRNA *layer_group_ptr)
{
using namespace blender::bke::greasepencil;
LayerGroup *layer_group = nullptr;
if (layer_group_ptr && layer_group_ptr->data) {
layer_group = static_cast<LayerGroup *>(layer_group_ptr->data);
}
Layer *layer;
if (layer_group) {
layer = &grease_pencil->add_layer(*layer_group, name);
}
else {
layer = &grease_pencil->add_layer(name);
}
if (set_active) {
grease_pencil->set_active_layer(layer);
}
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
return layer;
}
static void rna_GreasePencil_layer_remove(GreasePencil *grease_pencil, PointerRNA *layer_ptr)
{
blender::bke::greasepencil::Layer &layer = *static_cast<blender::bke::greasepencil::Layer *>(
layer_ptr->data);
grease_pencil->remove_layer(layer);
RNA_POINTER_INVALIDATE(layer_ptr);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_SELECTED, grease_pencil);
}
static void rna_GreasePencil_layer_move(GreasePencil *grease_pencil,
PointerRNA *layer_ptr,
const int direction)
{
if (direction == 0) {
return;
}
blender::bke::greasepencil::TreeNode &layer_node =
static_cast<blender::bke::greasepencil::Layer *>(layer_ptr->data)->as_node();
switch (direction) {
case -1:
grease_pencil->move_node_down(layer_node, 1);
break;
case 1:
grease_pencil->move_node_up(layer_node, 1);
break;
}
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_move_top(GreasePencil *grease_pencil, PointerRNA *layer_ptr)
{
blender::bke::greasepencil::TreeNode &layer_node =
static_cast<blender::bke::greasepencil::Layer *>(layer_ptr->data)->as_node();
grease_pencil->move_node_top(layer_node);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_move_bottom(GreasePencil *grease_pencil, PointerRNA *layer_ptr)
{
blender::bke::greasepencil::TreeNode &layer_node =
static_cast<blender::bke::greasepencil::Layer *>(layer_ptr->data)->as_node();
grease_pencil->move_node_bottom(layer_node);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_move_to_layer_group(GreasePencil *grease_pencil,
PointerRNA *layer_ptr,
PointerRNA *layer_group_ptr)
{
using namespace blender::bke::greasepencil;
TreeNode &layer_node = static_cast<Layer *>(layer_ptr->data)->as_node();
LayerGroup *layer_group;
if (layer_group_ptr && layer_group_ptr->data) {
layer_group = static_cast<LayerGroup *>(layer_group_ptr->data);
}
else {
layer_group = &grease_pencil->root_group();
}
if (layer_group == nullptr) {
return;
}
grease_pencil->move_node_into(layer_node, *layer_group);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static PointerRNA rna_GreasePencil_active_layer_get(PointerRNA *ptr)
{
GreasePencil *grease_pencil = rna_grease_pencil(ptr);
@@ -542,24 +438,123 @@ static int rna_iterator_grease_pencil_layer_groups_length(PointerRNA *ptr)
#else
static void rna_def_grease_pencil_layers_mask_api(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_grease_pencil_drawing(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
RNA_def_property_srna(cprop, "GreasePencilLayerMasks");
srna = RNA_def_struct(brna, "GreasePencilLayerMasks", nullptr);
RNA_def_struct_sdna(srna, "GreasePencilLayer");
RNA_def_struct_ui_text(
srna, "Grease Pencil Mask Layers", "Collection of grease pencil masking layers");
static const EnumPropertyItem rna_enum_drawing_type_items[] = {
{GP_DRAWING, "DRAWING", 0, "Drawing", ""},
{GP_DRAWING_REFERENCE, "REFERENCE", 0, "Reference", ""},
{0, nullptr, 0, nullptr, nullptr}};
prop = RNA_def_property(srna, "active_mask_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_funcs(prop,
"rna_grease_pencil_active_mask_index_get",
"rna_grease_pencil_active_mask_index_set",
"rna_grease_pencil_active_mask_index_range");
RNA_def_property_ui_text(prop, "Active Layer Mask Index", "Active index in layer mask array");
srna = RNA_def_struct(brna, "GreasePencilDrawing", nullptr);
RNA_def_struct_sdna(srna, "GreasePencilDrawing");
RNA_def_struct_ui_text(srna, "Grease Pencil Drawing", "A Grease Pencil drawing");
/* Type. */
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "base.type");
RNA_def_property_enum_items(prop, rna_enum_drawing_type_items);
RNA_def_parameter_clear_flags(prop, PROP_EDITABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "Type", "Drawing type");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
/* User Count. */
prop = RNA_def_property(srna, "user_count", PROP_INT, PROP_NONE);
RNA_def_property_int_funcs(prop, "rna_Drawing_user_count_get", nullptr, nullptr);
RNA_def_parameter_clear_flags(prop, PROP_EDITABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "User Count", "The number of keyframes this drawing is used by");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
/* Attributes. */
rna_def_attributes_common(srna, AttributeOwnerType::GreasePencilDrawing);
}
static void rna_def_grease_pencil_frame(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem rna_enum_keyframe_type_items[] = {
{BEZT_KEYTYPE_KEYFRAME,
"KEYFRAME",
ICON_KEYTYPE_KEYFRAME_VEC,
"Keyframe",
"Normal keyframe, e.g. for key poses"},
{BEZT_KEYTYPE_BREAKDOWN,
"BREAKDOWN",
ICON_KEYTYPE_BREAKDOWN_VEC,
"Breakdown",
"A breakdown pose, e.g. for transitions between key poses"},
{BEZT_KEYTYPE_MOVEHOLD,
"MOVING_HOLD",
ICON_KEYTYPE_MOVING_HOLD_VEC,
"Moving Hold",
"A keyframe that is part of a moving hold"},
{BEZT_KEYTYPE_EXTREME,
"EXTREME",
ICON_KEYTYPE_EXTREME_VEC,
"Extreme",
"An 'extreme' pose, or some other purpose as needed"},
{BEZT_KEYTYPE_JITTER,
"JITTER",
ICON_KEYTYPE_JITTER_VEC,
"Jitter",
"A filler or baked keyframe for keying on ones, or some other purpose as needed"},
{BEZT_KEYTYPE_GENERATED,
"GENERATED",
ICON_KEYTYPE_GENERATED_VEC,
"Generated",
"A key generated automatically by a tool, not manually created"},
{0, nullptr, 0, nullptr, nullptr},
};
srna = RNA_def_struct(brna, "GreasePencilFrame", nullptr);
RNA_def_struct_sdna(srna, "GreasePencilFrame");
RNA_def_struct_ui_text(srna, "Grease Pencil Frame", "A Grease Pencil keyframe");
/* Drawing. */
prop = RNA_def_property(srna, "drawing", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "GreasePencilDrawing");
RNA_def_property_pointer_funcs(prop, "rna_Frame_drawing_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(prop, "Drawing", "A Grease Pencil drawing");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
/* Frame number. */
prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE);
/* TODO: Make property editable, ensure frame number isn't already in use. */
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_funcs(prop, "rna_Frame_frame_number_get", nullptr, nullptr);
RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
RNA_def_property_ui_text(prop, "Frame Number", "The frame number in the scene");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
/* Selection status. */
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GP_FRAME_SELECTED);
RNA_def_property_ui_text(prop, "Select", "Frame Selection in the Dope Sheet");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
/* Keyframe type. */
prop = RNA_def_property(srna, "keyframe_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "type");
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_enum_items(prop, rna_enum_keyframe_type_items);
RNA_def_property_ui_text(prop, "Keyframe Type", "Type of keyframe");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
}
static void rna_def_grease_pencil_frames(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
RNA_def_property_srna(cprop, "GreasePencilFrames");
srna = RNA_def_struct(brna, "GreasePencilFrames", nullptr);
RNA_def_struct_sdna(srna, "GreasePencilLayer");
RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of Grease Pencil frames");
RNA_api_grease_pencil_frames(srna);
}
static void rna_def_grease_pencil_layer_mask(BlenderRNA *brna)
@@ -596,6 +591,26 @@ static void rna_def_grease_pencil_layer_mask(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
}
static void rna_def_grease_pencil_layer_masks(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *prop;
RNA_def_property_srna(cprop, "GreasePencilLayerMasks");
srna = RNA_def_struct(brna, "GreasePencilLayerMasks", nullptr);
RNA_def_struct_sdna(srna, "GreasePencilLayer");
RNA_def_struct_ui_text(
srna, "Grease Pencil Mask Layers", "Collection of grease pencil masking layers");
prop = RNA_def_property(srna, "active_mask_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_funcs(prop,
"rna_grease_pencil_active_mask_index_get",
"rna_grease_pencil_active_mask_index_set",
"rna_grease_pencil_active_mask_index_range");
RNA_def_property_ui_text(prop, "Active Layer Mask Index", "Active index in layer mask array");
}
static void rna_def_grease_pencil_layer(BlenderRNA *brna)
{
StructRNA *srna;
@@ -627,12 +642,27 @@ static void rna_def_grease_pencil_layer(BlenderRNA *brna)
RNA_def_struct_name_property(srna, prop);
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_RENAME, "rna_grease_pencil_update");
/* Frames. */
prop = RNA_def_property(srna, "frames", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "GreasePencilFrame");
RNA_def_property_ui_text(prop, "Frames", "Grease Pencil frames");
RNA_def_property_collection_funcs(prop,
"rna_GreasePencilLayer_frames_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_GreasePencilLayer_frames_get",
"rna_GreasePencilLayer_frames_length",
"rna_GreasePencilLayer_frames_lookup_int",
nullptr,
nullptr);
rna_def_grease_pencil_frames(brna, prop);
/* Mask Layers */
prop = RNA_def_property(srna, "mask_layers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, nullptr, "masks", nullptr);
RNA_def_property_struct_type(prop, "GreasePencilLayerMask");
RNA_def_property_ui_text(prop, "Masks", "List of Masking Layers");
rna_def_grease_pencil_layers_mask_api(brna, prop);
rna_def_grease_pencil_layer_masks(brna, prop);
/* Visibility */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
@@ -795,82 +825,20 @@ static void rna_def_grease_pencil_layer(BlenderRNA *brna)
prop, "rna_GreasePencilLayer_parent_layer_group_get", nullptr, nullptr, nullptr);
RNA_def_property_ui_text(
prop, "Parent Layer Group", "The parent layer group this layer is part of");
RNA_api_grease_pencil_layer(srna);
}
static void rna_def_grease_pencil_layers_api(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_grease_pencil_layers(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
RNA_def_property_srna(cprop, "GreasePencilv3Layers");
srna = RNA_def_struct(brna, "GreasePencilv3Layers", nullptr);
RNA_def_struct_sdna(srna, "GreasePencil");
RNA_def_struct_ui_text(srna, "Grease Pencil Layers", "Collection of Grease Pencil layers");
func = RNA_def_function(srna, "new", "rna_GreasePencil_layer_new");
RNA_def_function_ui_description(func, "Add a new Grease Pencil layer");
parm = RNA_def_string(func, "name", "GreasePencilLayer", MAX_NAME, "Name", "Name of the layer");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
RNA_def_boolean(
func, "set_active", true, "Set Active", "Set the newly created layer as the active layer");
parm = RNA_def_pointer(
func,
"layer_group",
"GreasePencilLayerGroup",
"",
"The layer group the new layer will be created in (use None for the main stack)");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The newly created layer");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_GreasePencil_layer_remove");
RNA_def_function_ui_description(func, "Remove a Grease Pencil layer");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(srna, "move", "rna_GreasePencil_layer_move");
RNA_def_function_ui_description(func,
"Move a Grease Pencil layer in the layer group or main stack");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_enum(
func, "type", rna_enum_tree_node_move_type_items, 1, "", "Direction of movement");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
func = RNA_def_function(srna, "move_top", "rna_GreasePencil_layer_move_top");
RNA_def_function_ui_description(
func, "Move a Grease Pencil layer to the top of the layer group or main stack");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(srna, "move_bottom", "rna_GreasePencil_layer_move_bottom");
RNA_def_function_ui_description(
func, "Move a Grease Pencil layer to the bottom of the layer group or main stack");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(
srna, "move_to_layer_group", "rna_GreasePencil_layer_move_to_layer_group");
RNA_def_function_ui_description(func, "Move a Grease Pencil layer into a layer group");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_pointer(
func,
"layer_group",
"GreasePencilLayerGroup",
"",
"The layer group the layer will be moved into (use None for the main stack)");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "GreasePencilLayer");
RNA_def_property_pointer_funcs(prop,
@@ -881,6 +849,8 @@ static void rna_def_grease_pencil_layers_api(BlenderRNA *brna, PropertyRNA *cpro
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Active Layer", "Active Grease Pencil layer");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_SELECTED, nullptr);
RNA_api_grease_pencil_layers(srna);
}
static void rna_def_grease_pencil_layer_group(BlenderRNA *brna)
@@ -939,91 +909,16 @@ static void rna_def_grease_pencil_layer_group(BlenderRNA *brna)
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
}
static void rna_def_grease_pencil_layer_group_api(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_grease_pencil_layer_groups(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
RNA_def_property_srna(cprop, "GreasePencilv3LayerGroup");
srna = RNA_def_struct(brna, "GreasePencilv3LayerGroup", nullptr);
RNA_def_struct_sdna(srna, "GreasePencil");
RNA_def_struct_ui_text(srna, "Grease Pencil Group", "Collection of Grease Pencil layers");
func = RNA_def_function(srna, "new", "rna_GreasePencil_layer_group_new");
RNA_def_function_ui_description(func, "Add a new Grease Pencil layer group");
parm = RNA_def_string(
func, "name", "GreasePencilLayerGroup", MAX_NAME, "Name", "Name of the layer group");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_pointer(
func,
"parent_group",
"GreasePencilLayerGroup",
"",
"The parent layer group the new group will be created in (use None for the main stack)");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The newly created layer group");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_GreasePencil_layer_group_remove");
RNA_def_function_ui_description(func, "Remove a new Grease Pencil layer group");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_boolean(func,
"keep_children",
false,
"",
"Keep the children nodes of the group and only delete the group itself");
func = RNA_def_function(srna, "move", "rna_GreasePencil_layer_group_move");
RNA_def_function_ui_description(func,
"Move a layer group in the parent layer group or main stack");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_enum(
func, "type", rna_enum_tree_node_move_type_items, 1, "", "Direction of movement");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
func = RNA_def_function(srna, "move_top", "rna_GreasePencil_layer_group_move_top");
RNA_def_function_ui_description(
func, "Move a layer group to the top of the parent layer group or main stack");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(srna, "move_bottom", "rna_GreasePencil_layer_group_move_bottom");
RNA_def_function_ui_description(
func, "Move a layer group to the bottom of the parent layer group or main stack");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(
srna, "move_to_layer_group", "rna_GreasePencil_layer_group_move_to_layer_group");
RNA_def_function_ui_description(func, "Move a layer group into a parent layer group");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_pointer(
func,
"parent_group",
"GreasePencilLayerGroup",
"",
"The parent layer group the layer group will be moved into (use None for the main stack)");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "GreasePencilLayerGroup");
RNA_def_property_pointer_funcs(prop,
@@ -1034,6 +929,8 @@ static void rna_def_grease_pencil_layer_group_api(BlenderRNA *brna, PropertyRNA
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Active Layer Group", "Active Grease Pencil layer group");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_SELECTED, nullptr);
RNA_api_grease_pencil_layer_groups(srna);
}
static void rna_def_grease_pencil_onion_skinning(StructRNA *srna)
@@ -1230,7 +1127,7 @@ static void rna_def_grease_pencil_data(BlenderRNA *brna)
nullptr, /* TODO */
nullptr);
RNA_def_property_ui_text(prop, "Layers", "Grease Pencil layers");
rna_def_grease_pencil_layers_api(brna, prop);
rna_def_grease_pencil_layers(brna, prop);
/* Layer Groups */
prop = RNA_def_property(srna, "layer_groups", PROP_COLLECTION, PROP_NONE);
@@ -1245,7 +1142,7 @@ static void rna_def_grease_pencil_data(BlenderRNA *brna)
nullptr, /* TODO */
nullptr);
RNA_def_property_ui_text(prop, "Layer Groups", "Grease Pencil layer groups");
rna_def_grease_pencil_layer_group_api(brna, prop);
rna_def_grease_pencil_layer_groups(brna, prop);
prop = RNA_def_property(srna, "use_autolock_layers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GREASE_PENCIL_AUTOLOCK_LAYERS);
@@ -1275,6 +1172,8 @@ void RNA_def_grease_pencil(BlenderRNA *brna)
rna_def_grease_pencil_layer(brna);
rna_def_grease_pencil_layer_mask(brna);
rna_def_grease_pencil_layer_group(brna);
rna_def_grease_pencil_frame(brna);
rna_def_grease_pencil_drawing(brna);
}
#endif

View File

@@ -0,0 +1,533 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup RNA
*/
#include "DNA_grease_pencil_types.h"
#include "DNA_scene_types.h"
#include "RNA_define.hh"
#include "WM_api.hh"
#include "rna_internal.hh" /* own include */
const EnumPropertyItem rna_enum_tree_node_move_type_items[] = {
{-1, "DOWN", 0, "Down", ""},
{1, "UP", 0, "Up", ""},
{0, nullptr, 0, nullptr, nullptr},
};
#ifdef RNA_RUNTIME
# include "BKE_grease_pencil.hh"
# include "BKE_report.hh"
# include "DEG_depsgraph.hh"
static GreasePencilFrame *rna_Frames_frame_new(ID *id,
GreasePencilLayer *layer_in,
ReportList *reports,
int frame_number)
{
using namespace blender::bke::greasepencil;
GreasePencil &grease_pencil = *reinterpret_cast<GreasePencil *>(id);
Layer &layer = static_cast<GreasePencilLayer *>(layer_in)->wrap();
if (layer.frames().contains(frame_number)) {
BKE_reportf(reports, RPT_ERROR, "Frame already exists on frame number %d", frame_number);
return nullptr;
}
grease_pencil.insert_frame(layer, frame_number, 0, BEZT_KEYTYPE_KEYFRAME);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, &grease_pencil);
return layer.frame_at(frame_number);
}
static void rna_Frames_frame_remove(ID *id,
GreasePencilLayer *layer_in,
ReportList *reports,
int frame_number)
{
using namespace blender::bke::greasepencil;
GreasePencil &grease_pencil = *reinterpret_cast<GreasePencil *>(id);
Layer &layer = static_cast<GreasePencilLayer *>(layer_in)->wrap();
if (!layer.frames().contains(frame_number)) {
BKE_reportf(reports, RPT_ERROR, "Frame doesn't exists on frame number %d", frame_number);
return;
}
if (grease_pencil.remove_frames(layer, {frame_number})) {
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, &grease_pencil);
}
}
static GreasePencilFrame *rna_Frames_frame_copy(ID *id,
GreasePencilLayer *layer_in,
ReportList *reports,
int from_frame_number,
int to_frame_number,
bool instance_drawing)
{
using namespace blender::bke::greasepencil;
GreasePencil &grease_pencil = *reinterpret_cast<GreasePencil *>(id);
Layer &layer = static_cast<GreasePencilLayer *>(layer_in)->wrap();
if (!layer.frames().contains(from_frame_number)) {
BKE_reportf(reports, RPT_ERROR, "Frame doesn't exists on frame number %d", from_frame_number);
return nullptr;
}
if (layer.frames().contains(to_frame_number)) {
BKE_reportf(reports, RPT_ERROR, "Frame already exists on frame number %d", to_frame_number);
return nullptr;
}
grease_pencil.insert_duplicate_frame(
layer, from_frame_number, to_frame_number, instance_drawing);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, &grease_pencil);
return layer.frame_at(to_frame_number);
}
static GreasePencilFrame *rna_GreasePencilLayer_get_frame_at(GreasePencilLayer *layer,
int frame_number)
{
using namespace blender::bke::greasepencil;
return static_cast<Layer *>(layer)->frame_at(frame_number);
}
static GreasePencilLayer *rna_GreasePencil_layer_new(GreasePencil *grease_pencil,
const char *name,
const bool set_active,
PointerRNA *layer_group_ptr)
{
using namespace blender::bke::greasepencil;
LayerGroup *layer_group = nullptr;
if (layer_group_ptr && layer_group_ptr->data) {
layer_group = static_cast<LayerGroup *>(layer_group_ptr->data);
}
Layer *layer;
if (layer_group) {
layer = &grease_pencil->add_layer(*layer_group, name);
}
else {
layer = &grease_pencil->add_layer(name);
}
if (set_active) {
grease_pencil->set_active_layer(layer);
}
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
return layer;
}
static void rna_GreasePencil_layer_remove(GreasePencil *grease_pencil, PointerRNA *layer_ptr)
{
blender::bke::greasepencil::Layer &layer = *static_cast<blender::bke::greasepencil::Layer *>(
layer_ptr->data);
grease_pencil->remove_layer(layer);
RNA_POINTER_INVALIDATE(layer_ptr);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_SELECTED, grease_pencil);
}
static void rna_GreasePencil_layer_move(GreasePencil *grease_pencil,
PointerRNA *layer_ptr,
const int direction)
{
if (direction == 0) {
return;
}
blender::bke::greasepencil::TreeNode &layer_node =
static_cast<blender::bke::greasepencil::Layer *>(layer_ptr->data)->as_node();
switch (direction) {
case -1:
grease_pencil->move_node_down(layer_node, 1);
break;
case 1:
grease_pencil->move_node_up(layer_node, 1);
break;
}
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_move_top(GreasePencil *grease_pencil, PointerRNA *layer_ptr)
{
blender::bke::greasepencil::TreeNode &layer_node =
static_cast<blender::bke::greasepencil::Layer *>(layer_ptr->data)->as_node();
grease_pencil->move_node_top(layer_node);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_move_bottom(GreasePencil *grease_pencil, PointerRNA *layer_ptr)
{
blender::bke::greasepencil::TreeNode &layer_node =
static_cast<blender::bke::greasepencil::Layer *>(layer_ptr->data)->as_node();
grease_pencil->move_node_bottom(layer_node);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_move_to_layer_group(GreasePencil *grease_pencil,
PointerRNA *layer_ptr,
PointerRNA *layer_group_ptr)
{
using namespace blender::bke::greasepencil;
TreeNode &layer_node = static_cast<Layer *>(layer_ptr->data)->as_node();
LayerGroup *layer_group;
if (layer_group_ptr && layer_group_ptr->data) {
layer_group = static_cast<LayerGroup *>(layer_group_ptr->data);
}
else {
layer_group = &grease_pencil->root_group();
}
if (layer_group == nullptr) {
return;
}
grease_pencil->move_node_into(layer_node, *layer_group);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static PointerRNA rna_GreasePencil_layer_group_new(GreasePencil *grease_pencil,
const char *name,
PointerRNA *parent_group_ptr)
{
using namespace blender::bke::greasepencil;
LayerGroup *parent_group;
if (parent_group_ptr && parent_group_ptr->data) {
parent_group = static_cast<LayerGroup *>(parent_group_ptr->data);
}
else {
parent_group = &grease_pencil->root_group();
}
LayerGroup *new_layer_group = &grease_pencil->add_layer_group(*parent_group, name);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
PointerRNA ptr = RNA_pointer_create(
&grease_pencil->id, &RNA_GreasePencilLayerGroup, new_layer_group);
return ptr;
}
static void rna_GreasePencil_layer_group_remove(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr,
bool keep_children)
{
using namespace blender::bke::greasepencil;
LayerGroup &layer_group = *static_cast<LayerGroup *>(layer_group_ptr->data);
grease_pencil->remove_group(layer_group, keep_children);
RNA_POINTER_INVALIDATE(layer_group_ptr);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_SELECTED, grease_pencil);
}
static void rna_GreasePencil_layer_group_move(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr,
int direction)
{
if (direction == 0) {
return;
}
blender::bke::greasepencil::TreeNode &layer_group_node =
static_cast<blender::bke::greasepencil::LayerGroup *>(layer_group_ptr->data)->as_node();
switch (direction) {
case -1:
grease_pencil->move_node_down(layer_group_node, 1);
break;
case 1:
grease_pencil->move_node_up(layer_group_node, 1);
break;
}
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_group_move_top(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr)
{
blender::bke::greasepencil::TreeNode &layer_group_node =
static_cast<blender::bke::greasepencil::LayerGroup *>(layer_group_ptr->data)->as_node();
grease_pencil->move_node_top(layer_group_node);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_group_move_bottom(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr)
{
blender::bke::greasepencil::TreeNode &layer_group_node =
static_cast<blender::bke::greasepencil::LayerGroup *>(layer_group_ptr->data)->as_node();
grease_pencil->move_node_bottom(layer_group_node);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
static void rna_GreasePencil_layer_group_move_to_layer_group(GreasePencil *grease_pencil,
PointerRNA *layer_group_ptr,
PointerRNA *parent_group_ptr)
{
using namespace blender::bke::greasepencil;
TreeNode &layer_group_node = static_cast<LayerGroup *>(layer_group_ptr->data)->as_node();
LayerGroup *parent_group;
if (parent_group_ptr && parent_group_ptr->data) {
parent_group = static_cast<LayerGroup *>(parent_group_ptr->data);
}
else {
parent_group = &grease_pencil->root_group();
}
grease_pencil->move_node_into(layer_group_node, *parent_group);
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, grease_pencil);
}
#else
void RNA_api_grease_pencil_frames(StructRNA *srna)
{
FunctionRNA *func;
PropertyRNA *parm;
func = RNA_def_function(srna, "new", "rna_Frames_frame_new");
RNA_def_function_ui_description(func, "Add a new Grease Pencil frame");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
parm = RNA_def_int(func,
"frame_number",
1,
MINAFRAME,
MAXFRAME,
"Frame Number",
"The frame on which the drawing appears",
MINAFRAME,
MAXFRAME);
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_pointer(func, "frame", "GreasePencilFrame", "", "The newly created frame");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_Frames_frame_remove");
RNA_def_function_ui_description(func, "Remove a Grease Pencil frame");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
parm = RNA_def_int(func,
"frame_number",
1,
MINAFRAME,
MAXFRAME,
"Frame Number",
"The frame number of the frame to remove",
MINAFRAME,
MAXFRAME);
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
func = RNA_def_function(srna, "copy", "rna_Frames_frame_copy");
RNA_def_function_ui_description(func, "Copy a Grease Pencil frame");
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
parm = RNA_def_int(func,
"from_frame_number",
1,
MINAFRAME,
MAXFRAME,
"Source Frame Number",
"The frame number of the source frame",
MINAFRAME,
MAXFRAME);
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_int(func,
"to_frame_number",
2,
MINAFRAME,
MAXFRAME,
"Frame Number of Copy",
"The frame number to copy the frame to",
MINAFRAME,
MAXFRAME);
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_boolean(func,
"instance_drawing",
false,
"Instance Drawing",
"Let the copied frame use the same drawing as the source");
parm = RNA_def_pointer(func, "copy", "GreasePencilFrame", "", "The newly copied frame");
RNA_def_function_return(func, parm);
}
void RNA_api_grease_pencil_layer(StructRNA *srna)
{
FunctionRNA *func;
PropertyRNA *parm;
func = RNA_def_function(srna, "get_frame_at", "rna_GreasePencilLayer_get_frame_at");
RNA_def_function_ui_description(func, "Get the frame at given frame number");
parm = RNA_def_int(
func, "frame_number", 1, MINAFRAME, MAXFRAME, "Frame Number", "", MINAFRAME, MAXFRAME);
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_pointer(func, "frame", "GreasePencilFrame", "Frame", "");
RNA_def_function_return(func, parm);
}
void RNA_api_grease_pencil_layers(StructRNA *srna)
{
FunctionRNA *func;
PropertyRNA *parm;
func = RNA_def_function(srna, "new", "rna_GreasePencil_layer_new");
RNA_def_function_ui_description(func, "Add a new Grease Pencil layer");
parm = RNA_def_string(func, "name", "GreasePencilLayer", MAX_NAME, "Name", "Name of the layer");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
RNA_def_boolean(
func, "set_active", true, "Set Active", "Set the newly created layer as the active layer");
parm = RNA_def_pointer(
func,
"layer_group",
"GreasePencilLayerGroup",
"",
"The layer group the new layer will be created in (use None for the main stack)");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The newly created layer");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_GreasePencil_layer_remove");
RNA_def_function_ui_description(func, "Remove a Grease Pencil layer");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(srna, "move", "rna_GreasePencil_layer_move");
RNA_def_function_ui_description(func,
"Move a Grease Pencil layer in the layer group or main stack");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_enum(
func, "type", rna_enum_tree_node_move_type_items, 1, "", "Direction of movement");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
func = RNA_def_function(srna, "move_top", "rna_GreasePencil_layer_move_top");
RNA_def_function_ui_description(
func, "Move a Grease Pencil layer to the top of the layer group or main stack");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(srna, "move_bottom", "rna_GreasePencil_layer_move_bottom");
RNA_def_function_ui_description(
func, "Move a Grease Pencil layer to the bottom of the layer group or main stack");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(
srna, "move_to_layer_group", "rna_GreasePencil_layer_move_to_layer_group");
RNA_def_function_ui_description(func, "Move a Grease Pencil layer into a layer group");
parm = RNA_def_pointer(func, "layer", "GreasePencilLayer", "", "The layer to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_pointer(
func,
"layer_group",
"GreasePencilLayerGroup",
"",
"The layer group the layer will be moved into (use None for the main stack)");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
}
void RNA_api_grease_pencil_layer_groups(StructRNA *srna)
{
FunctionRNA *func;
PropertyRNA *parm;
func = RNA_def_function(srna, "new", "rna_GreasePencil_layer_group_new");
RNA_def_function_ui_description(func, "Add a new Grease Pencil layer group");
parm = RNA_def_string(
func, "name", "GreasePencilLayerGroup", MAX_NAME, "Name", "Name of the layer group");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_pointer(
func,
"parent_group",
"GreasePencilLayerGroup",
"",
"The parent layer group the new group will be created in (use None for the main stack)");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The newly created layer group");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_GreasePencil_layer_group_remove");
RNA_def_function_ui_description(func, "Remove a new Grease Pencil layer group");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_boolean(func,
"keep_children",
false,
"",
"Keep the children nodes of the group and only delete the group itself");
func = RNA_def_function(srna, "move", "rna_GreasePencil_layer_group_move");
RNA_def_function_ui_description(func,
"Move a layer group in the parent layer group or main stack");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_enum(
func, "type", rna_enum_tree_node_move_type_items, 1, "", "Direction of movement");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
func = RNA_def_function(srna, "move_top", "rna_GreasePencil_layer_group_move_top");
RNA_def_function_ui_description(
func, "Move a layer group to the top of the parent layer group or main stack");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(srna, "move_bottom", "rna_GreasePencil_layer_group_move_bottom");
RNA_def_function_ui_description(
func, "Move a layer group to the bottom of the parent layer group or main stack");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
func = RNA_def_function(
srna, "move_to_layer_group", "rna_GreasePencil_layer_group_move_to_layer_group");
RNA_def_function_ui_description(func, "Move a layer group into a parent layer group");
parm = RNA_def_pointer(
func, "layer_group", "GreasePencilLayerGroup", "", "The layer group to move");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
parm = RNA_def_pointer(
func,
"parent_group",
"GreasePencilLayerGroup",
"",
"The parent layer group the layer group will be moved into (use None for the main stack)");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
}
#endif

View File

@@ -427,6 +427,10 @@ void RNA_api_operator(StructRNA *srna);
void RNA_api_macro(StructRNA *srna);
void RNA_api_gizmo(StructRNA *srna);
void RNA_api_gizmogroup(StructRNA *srna);
void RNA_api_grease_pencil_frames(StructRNA *srna);
void RNA_api_grease_pencil_layer(StructRNA *srna);
void RNA_api_grease_pencil_layers(StructRNA *srna);
void RNA_api_grease_pencil_layer_groups(StructRNA *srna);
void RNA_api_keyconfig(StructRNA *srna);
void RNA_api_keyconfigs(StructRNA *srna);
void RNA_api_keyingset(StructRNA *srna);