GPv3: Onion Skinning #119792

Merged
Falk David merged 20 commits from filedescriptor/blender:gpv3-old-onion-skinning into main 2024-04-03 15:34:51 +02:00
10 changed files with 192 additions and 124 deletions
Showing only changes of commit ded41f7e7f - Show all commits

View File

@ -254,7 +254,7 @@ class DATA_PT_grease_pencil_onion_skinning(DataButtonsPanel, Panel):
class DATA_PT_grease_pencil_onion_skinning_custom_colors(DataButtonsPanel, Panel):
bl_parent_id = "DATA_PT_gpencil_onion_skinning"
bl_parent_id = "DATA_PT_grease_pencil_onion_skinning"
bl_label = "Custom Colors"
bl_options = {'DEFAULT_CLOSED'}

View File

@ -7832,6 +7832,8 @@ class VIEW3D_PT_overlay_grease_pencil_options(Panel):
'OBJECT': iface_("Grease Pencil"),
}[context.mode], translate=False)
layout.prop(overlay, "use_gpencil_onion_skin", text="Onion Skin")
if context.object.mode in {'EDIT'}:
split = layout.split()
col = split.column()

View File

@ -702,7 +702,8 @@ inline void TreeNode::set_selected(const bool selected)
}
inline bool TreeNode::use_onion_skinning() const
{
return ((this->flag & GP_LAYER_TREE_NODE_USE_ONION_SKINNING) != 0);
return ((this->flag & GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING) == 0) &&
(!this->parent_group() || this->parent_group()->as_node().use_onion_skinning());
}
inline bool TreeNode::use_masks() const
{

View File

@ -537,8 +537,8 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_USE_LIGHTS), GP_LAYER_TREE_NODE_USE_LIGHTS);
SET_FLAG_FROM_TEST(new_layer.base.flag,
(gpl->onion_flag & GP_LAYER_ONIONSKIN),
GP_LAYER_TREE_NODE_USE_ONION_SKINNING);
(gpl->onion_flag & GP_LAYER_ONIONSKIN) == 0,
GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING);
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_USE_MASK) == 0, GP_LAYER_TREE_NODE_HIDE_MASKS);

View File

@ -261,6 +261,45 @@ static void gpencil_layer_final_tint_and_alpha_get(const GPENCIL_PrivateData *pd
*r_alpha *= pd->xray_alpha;
}
static float4 grease_pencil_layer_final_tint_and_alpha_get(const GPENCIL_PrivateData *pd,
const GreasePencil &grease_pencil,
const int onion_id,
float *r_alpha)
{
const bool use_onion = (onion_id != 0);
if (use_onion) {
const bool use_onion_custom_col = true;
const bool use_onion_fade = true;
const bool use_next_col = onion_id > 0;
const float onion_factor = grease_pencil.onion_skinning_settings.opacity;
const float3 color_next(grease_pencil.onion_skinning_settings.color_after);
const float3 color_prev(grease_pencil.onion_skinning_settings.color_before);
const float4 onion_col_custom = (use_onion_custom_col) ?
(use_next_col ? float4(color_next, 1.0f) :
float4(color_prev, 1.0f)) :
U.gpencil_new_layer_col;
*r_alpha = use_onion_fade ? (1.0f / abs(onion_id)) : 0.5f;
*r_alpha *= onion_factor;
*r_alpha = (onion_factor > 0.0f) ? clamp_f(*r_alpha, 0.1f, 1.0f) :
clamp_f(*r_alpha, 0.01f, 1.0f);
*r_alpha *= pd->xray_alpha;
return onion_col_custom;
}
float4 layer_tint(float3(0.0f), 1.0f);
if (GPENCIL_SIMPLIFY_TINT(pd->scene)) {
layer_tint[3] = 0.0f;
}
*r_alpha = 1.0f;
*r_alpha *= pd->xray_alpha;
return layer_tint;
}
/* Random color by layer. */
static void gpencil_layer_random_color_get(const Object *ob,
const bGPDlayer *gpl,
@ -473,7 +512,7 @@ GPENCIL_tLayer *gpencil_layer_cache_get(GPENCIL_tObject *tgp_ob, int number)
GPENCIL_tLayer *grease_pencil_layer_cache_add(GPENCIL_PrivateData *pd,
const Object *ob,
const blender::bke::greasepencil::Layer &layer,
std::optional<int> /*onion_id*/,
const int onion_id,
GPENCIL_tObject *tgp_ob)
{
@ -501,10 +540,9 @@ GPENCIL_tLayer *grease_pencil_layer_cache_add(GPENCIL_PrivateData *pd,
float thickness_scale = (is_screenspace) ? -1.0f : 1.0f / 1000.0f;
float layer_opacity = grease_pencil_layer_final_opacity_get(pd, ob, grease_pencil, layer);
float4 layer_tint(0.0f);
float layer_alpha = pd->xray_alpha;
/* TODO: Onion skinning! */
// gpencil_layer_final_tint_and_alpha_get(pd, gpd, gpl, gpf, layer_tint, &layer_alpha);
const float4 layer_tint = grease_pencil_layer_final_tint_and_alpha_get(
pd, grease_pencil, onion_id, &layer_alpha);
/* Create the new layer descriptor. */
GPENCIL_tLayer *tgp_layer = static_cast<GPENCIL_tLayer *>(BLI_memblock_alloc(pd->gp_layer_pool));

View File

@ -340,7 +340,7 @@ GPENCIL_tLayer *gpencil_layer_cache_get(GPENCIL_tObject *tgp_ob, int number);
GPENCIL_tLayer *grease_pencil_layer_cache_add(GPENCIL_PrivateData *pd,
const Object *ob,
const blender::bke::greasepencil::Layer &layer,
std::optional<int> onion_id,
int onion_id,
GPENCIL_tObject *tgp_ob);
/**
* Creates a linked list of material pool containing all materials assigned for a given object.

View File

@ -663,7 +663,7 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
drawcall_flush();
GPENCIL_tLayer *tgp_layer = grease_pencil_layer_cache_add(pd, ob, layer, {}, tgp_ob);
GPENCIL_tLayer *tgp_layer = grease_pencil_layer_cache_add(pd, ob, layer, info.onion_id, tgp_ob);
const bool use_lights = pd->use_lighting &&
((layer.base.flag & GP_LAYER_TREE_NODE_USE_LIGHTS) != 0) &&

View File

@ -258,12 +258,31 @@ class LayerViewItem : public AbstractTreeViewItem {
uiBlock *block = uiLayoutGetBlock(&row);
const int icon = (layer_.base.flag & GP_LAYER_TREE_NODE_HIDE_MASKS) == 0 ? ICON_CLIPUV_DEHLT :
ICON_CLIPUV_HLT;
but = uiDefIconButR(block,
filedescriptor marked this conversation as resolved Outdated

Does it work to use a uiItem function here, instead of the lower level uiDefBut API?

Does it work to use a `uiItem` function here, instead of the lower level `uiDefBut` API?

I'd love too, but UI_but_flag_enable(but, UI_BUT_INACTIVE); takes a uiBut :/

I'd love too, but `UI_but_flag_enable(but, UI_BUT_INACTIVE);` takes a `uiBut` :/

Just like RNA, there are multiple APIs for the same functionality. Here you should be able to use uiLayoutSetActive or uiLayoutSetEnabled.

Just like RNA, there are multiple APIs for the same functionality. Here you should be able to use `uiLayoutSetActive` or `uiLayoutSetEnabled`.

Ok I'll see if I can switch to using a layout with rows and such there. I remember trying this when I wrote that code, but running into issues. Don't know what those were now. I'll try again.

Ok I'll see if I can switch to using a layout with rows and such there. I remember trying this when I wrote that code, but running into issues. Don't know what those were now. I'll try again.
UI_BTYPE_ICON_TOGGLE,
0,
icon,
ICON_NONE,
0,
0,
UI_UNIT_X,
UI_UNIT_Y,
&layer_ptr,
"use_onion_skinning",
0,
0.0f,
0.0f,
nullptr);
if (!layer_.parent_group().use_onion_skinning()) {
UI_but_flag_enable(but, UI_BUT_INACTIVE);
}
const int mask_icon = (layer_.base.flag & GP_LAYER_TREE_NODE_HIDE_MASKS) == 0 ?
ICON_CLIPUV_DEHLT :
ICON_CLIPUV_HLT;
but = uiDefIconButR(block,
UI_BTYPE_ICON_TOGGLE,
0,
mask_icon,
0,
0,
UI_UNIT_X,

View File

@ -238,7 +238,7 @@ typedef enum GreasePencilLayerTreeNodeFlag {
GP_LAYER_TREE_NODE_SELECT = (1 << 2),
GP_LAYER_TREE_NODE_MUTE = (1 << 3),
GP_LAYER_TREE_NODE_USE_LIGHTS = (1 << 4),
GP_LAYER_TREE_NODE_USE_ONION_SKINNING = (1 << 5),
GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING = (1 << 5),
filedescriptor marked this conversation as resolved
Review

What's the reason for using a negative flag here? The RNA property is positive too.

What's the reason for using a negative flag here? The RNA property is positive too.
Review

The flags on tree nodes are "inherited" when you access them (e.g. if the parent group of a layer is not visible, the layer is also not visible). This also applies to onion skinning. So to avoid having to change the root group value, it seemed easier to just invert the flag instead so that the default of 0 is sensible (onion skinning is shown).

The flags on tree nodes are "inherited" when you access them (e.g. if the parent group of a layer is not visible, the layer is also not visible). This also applies to onion skinning. So to avoid having to change the root group value, it seemed easier to just invert the flag instead so that the default of `0` is sensible (onion skinning is shown).
GP_LAYER_TREE_NODE_EXPANDED = (1 << 6),
GP_LAYER_TREE_NODE_HIDE_MASKS = (1 << 7),
} GreasePencilLayerTreeNodeFlag;

View File

@ -400,8 +400,9 @@ static void rna_def_grease_pencil_layer(BlenderRNA *brna)
/* Onion Skinning. */
prop = RNA_def_property(srna, "use_onion_skinning", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, "GreasePencilLayerTreeNode", "flag", GP_LAYER_TREE_NODE_USE_ONION_SKINNING);
RNA_def_property_ui_icon(prop, ICON_ONIONSKIN_OFF, 1);
RNA_def_property_boolean_negative_sdna(
prop, "GreasePencilLayerTreeNode", "flag", GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING);
RNA_def_property_ui_text(
prop, "Onion Skinning", "Display onion skins before and after the current frame");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
@ -544,21 +545,10 @@ 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_data(BlenderRNA *brna)
static void rna_def_grease_pencil_onion_skinning(StructRNA *srna)
{
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem prop_stroke_depth_order_items[] = {
{0, "2D", 0, "2D Layers", "Display strokes using grease pencil layers to define order"},
{GREASE_PENCIL_STROKE_ORDER_3D,
"3D",
0,
"3D Location",
"Display strokes using real 3D position in 3D space"},
{0, nullptr, 0, nullptr, nullptr},
};
static EnumPropertyItem prop_enum_onion_modes_items[] = {
{GP_ONION_SKINNING_MODE_ABSOLUTE,
"ABSOLUTE",
@ -603,6 +593,118 @@ static void rna_def_grease_pencil_data(BlenderRNA *brna)
{0, nullptr, 0, nullptr, nullptr},
};
prop = RNA_def_property(srna, "ghost_before_range", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, nullptr, "onion_skinning_settings.num_frames_before");
RNA_def_property_range(prop, 0, 120);
RNA_def_property_int_default(prop, 1);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop,
"Frames Before",
"Maximum number of frames to show before current frame "
"(0 = don't show any frames before current)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
prop = RNA_def_property(srna, "ghost_after_range", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, nullptr, "onion_skinning_settings.num_frames_after");
RNA_def_property_range(prop, 0, 120);
RNA_def_property_int_default(prop, 1);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop,
"Frames After",
"Maximum number of frames to show after current frame "
"(0 = don't show any frames after current)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
// prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE);
// RNA_def_property_boolean_sdna(
// prop, nullptr, "onion_flag", GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
// RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
// RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost
// frames"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, nullptr, "onion_skinning_settings.color_before");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
// RNA_def_property_float_array_default(prop, onion_dft1);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame");
RNA_def_property_update(prop,
NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL,
"rna_grease_pencil_update");
prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, nullptr, "onion_skinning_settings.color_after");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
// RNA_def_property_float_array_default(prop, onion_dft2);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame");
RNA_def_property_update(prop,
NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL,
"rna_grease_pencil_update");
// prop = RNA_def_property(srna, "use_ghosts_always", PROP_BOOLEAN, PROP_NONE);
// RNA_def_property_boolean_sdna(prop, nullptr, "onion_flag", GP_ONION_GHOST_ALWAYS);
// RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
// RNA_def_property_ui_text(prop,
// "Always Show Ghosts",
// "Ghosts are shown in renders and animation playback. Useful for "
// "special effects (e.g. motion blur)");
// RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "onion_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "onion_skinning_settings.mode");
RNA_def_property_enum_items(prop, prop_enum_onion_modes_items);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "Mode", "Mode to display frames");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
prop = RNA_def_property(srna, "onion_keyframe_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "onion_skinning_settings.filter");
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_enum_items(prop, prop_enum_onion_keyframe_type_items);
RNA_def_property_ui_text(prop, "Filter by Type", "Type of keyframe (for filtering)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
// prop = RNA_def_property(srna, "use_onion_fade", PROP_BOOLEAN, PROP_NONE);
// RNA_def_property_boolean_sdna(prop, nullptr, "onion_flag", GP_ONION_FADE);
// RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
// RNA_def_property_ui_text(
// prop, "Fade", "Display onion keyframes with a fade in color transparency");
// RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
// prop = RNA_def_property(srna, "use_onion_loop", PROP_BOOLEAN, PROP_NONE);
// RNA_def_property_boolean_sdna(prop, nullptr, "onion_flag", GP_ONION_LOOP);
// RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
// RNA_def_property_ui_text(
// prop, "Show Start Frame", "Display onion keyframes for looping animations");
// RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "onion_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, nullptr, "onion_skinning_settings.opacity");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0, 1.0f);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "Onion Opacity", "Change fade opacity of displayed onion frames");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
}
static void rna_def_grease_pencil_data(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem prop_stroke_depth_order_items[] = {
{0, "2D", 0, "2D Layers", "Display strokes using grease pencil layers to define order"},
{GREASE_PENCIL_STROKE_ORDER_3D,
"3D",
0,
"3D Location",
"Display strokes using real 3D position in 3D space"},
{0, nullptr, 0, nullptr, nullptr},
};
srna = RNA_def_struct(brna, "GreasePencilv3", "ID");
RNA_def_struct_sdna(srna, "GreasePencil");
RNA_def_struct_ui_text(srna, "Grease Pencil", "Grease Pencil data-block");
@ -677,102 +779,8 @@ static void rna_def_grease_pencil_data(BlenderRNA *brna)
"Defines how the strokes are ordered in 3D space (for objects not displayed 'In Front')");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
/* Onion Skinning */
prop = RNA_def_property(srna, "ghost_before_range", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, "GreasePencilOnionSkinningSettings", "num_frames_before");
RNA_def_property_range(prop, 0, 120);
RNA_def_property_int_default(prop, 1);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop,
"Frames Before",
"Maximum number of frames to show before current frame "
"(0 = don't show any frames before current)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
prop = RNA_def_property(srna, "ghost_after_range", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, "GreasePencilOnionSkinningSettings", "num_frames_after");
RNA_def_property_range(prop, 0, 120);
RNA_def_property_int_default(prop, 1);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop,
"Frames After",
"Maximum number of frames to show after current frame "
"(0 = don't show any frames after current)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
// prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE);
// RNA_def_property_boolean_sdna(
// prop, nullptr, "onion_flag", GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
// RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
// RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost
// frames"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "before_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, "GreasePencilOnionSkinningSettings", "color_before");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
// RNA_def_property_float_array_default(prop, onion_dft1);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame");
RNA_def_property_update(prop,
NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL,
"rna_grease_pencil_update");
prop = RNA_def_property(srna, "after_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, "GreasePencilOnionSkinningSettings", "color_after");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
// RNA_def_property_float_array_default(prop, onion_dft2);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame");
RNA_def_property_update(prop,
NC_SCREEN | NC_SCENE | ND_TOOLSETTINGS | ND_DATA | NC_GPENCIL,
"rna_grease_pencil_update");
// prop = RNA_def_property(srna, "use_ghosts_always", PROP_BOOLEAN, PROP_NONE);
// RNA_def_property_boolean_sdna(prop, nullptr, "onion_flag", GP_ONION_GHOST_ALWAYS);
// RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
// RNA_def_property_ui_text(prop,
// "Always Show Ghosts",
// "Ghosts are shown in renders and animation playback. Useful for "
// "special effects (e.g. motion blur)");
// RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "onion_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, "GreasePencilOnionSkinningSettings", "mode");
RNA_def_property_enum_items(prop, prop_enum_onion_modes_items);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "Mode", "Mode to display frames");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
prop = RNA_def_property(srna, "onion_keyframe_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, "GreasePencilOnionSkinningSettings", "filter");
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_enum_items(prop, prop_enum_onion_keyframe_type_items);
RNA_def_property_ui_text(prop, "Filter by Type", "Type of keyframe (for filtering)");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
// prop = RNA_def_property(srna, "use_onion_fade", PROP_BOOLEAN, PROP_NONE);
// RNA_def_property_boolean_sdna(prop, nullptr, "onion_flag", GP_ONION_FADE);
// RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
// RNA_def_property_ui_text(
// prop, "Fade", "Display onion keyframes with a fade in color transparency");
// RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
// prop = RNA_def_property(srna, "use_onion_loop", PROP_BOOLEAN, PROP_NONE);
// RNA_def_property_boolean_sdna(prop, nullptr, "onion_flag", GP_ONION_LOOP);
// RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
// RNA_def_property_ui_text(
// prop, "Show Start Frame", "Display onion keyframes for looping animations");
// RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "onion_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, "GreasePencilOnionSkinningSettings", "opacity");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0, 1.0f);
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, ParameterFlag(0));
RNA_def_property_ui_text(prop, "Onion Opacity", "Change fade opacity of displayed onion frames");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
/* Onion skinning. */
rna_def_grease_pencil_onion_skinning(srna);
}
void RNA_def_grease_pencil(BlenderRNA *brna)