GPv3: Opacity modifier #116946

Merged
Lukas Tönne merged 52 commits from LukasTonne/blender:gp3-opacity-modifier into main 2024-01-16 16:56:22 +01:00
5 changed files with 76 additions and 118 deletions
Showing only changes of commit 1577d8175a - Show all commits

View File

@ -2486,39 +2486,27 @@ typedef enum VolumeToMeshFlag {
VOLUME_TO_MESH_USE_SMOOTH_SHADE = 1 << 0,
} VolumeToMeshFlag;
typedef struct GreasePencilModifierLayerFilter {
/** Filter by layer name. */
char layer_name[64];
/** Filter by layer pass. */
int layer_pass;
/** GreasePencilModifierFilterFlag */
int flag;
} GreasePencilModifierLayerFilter;
typedef struct GreasePencilModifierMaterialFilter {
/** Filter by stroke material. */
struct Material *material;
/** Filter by material pass. */
int material_pass;
/** GreasePencilModifierFilterFlag */
int flag;
} GreasePencilModifierMaterialFilter;
typedef struct GreasePencilModifierVertexGroupData {
/** #MAX_VGROUP_NAME. */
char vertex_group_name[64];
/** GreasePencilModifierFilterFlag */
int flag;
char _pad[4];
} GreasePencilModifierVertexGroupData;
typedef struct GreasePencilModifierCustomCurveData {
struct CurveMapping *curve;
/** GreasePencilModifierFilterFlag */
/**
* Common influence data for grease pencil modifiers.
* Not all parts may be used by all modifier types.
*/
typedef struct GreasePencilModifierInfluenceData {
/** GreasePencilModifierInfluenceFlag */
int flag;
char _pad1[4];
/** Filter by layer name. */
char layer_name[64];
/** Filter by stroke material. */
struct Material *material;
/** Filter by layer pass. */
int layer_pass;
/** Filter by material pass. */
int material_pass;
/** #MAX_VGROUP_NAME. */
char vertex_group_name[64];
struct CurveMapping *custom_curve;
void *_pad2;
} GreasePencilModifierCustomCurveData;
} GreasePencilModifierInfluenceData;
typedef enum GreasePencilModifierInfluenceFlag {
GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER = (1 << 0),
@ -2531,17 +2519,6 @@ typedef enum GreasePencilModifierInfluenceFlag {
GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE = (1 << 7),
} GreasePencilModifierInfluenceFlag;
/**
* Combined generic influence data for grease pencil modifiers.
* Not all parts may be used by all modifier types.
*/
typedef struct GreasePencilModifierInfluenceData {
GreasePencilModifierLayerFilter layer_filter;
GreasePencilModifierMaterialFilter material_filter;
GreasePencilModifierVertexGroupData vertex_group;
GreasePencilModifierCustomCurveData custom_curve;
} GreasePencilModifierInfluenceData;
typedef struct GreasePencilOpacityModifierData {
ModifierData modifier;
GreasePencilModifierInfluenceData influence;

View File

@ -1748,8 +1748,7 @@ static void rna_GreasePencilModifier_material_set(PointerRNA *ptr,
PointerRNA *ptr, PointerRNA value, ReportList *reports) \
{ \
_type##ModifierData *tmd = static_cast<_type##ModifierData *>(ptr->data); \
rna_GreasePencilModifier_material_set( \
ptr, value, reports, &tmd->influence.material_filter.material); \
rna_GreasePencilModifier_material_set(ptr, value, reports, &tmd->influence.material); \
}
# define RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(_type) \
@ -1758,8 +1757,8 @@ static void rna_GreasePencilModifier_material_set(PointerRNA *ptr,
_type##ModifierData *tmd = static_cast<_type##ModifierData *>(ptr->data); \
rna_object_vgroup_name_set(ptr, \
value, \
tmd->influence.vertex_group.vertex_group_name, \
sizeof(tmd->influence.vertex_group.vertex_group_name)); \
tmd->influence.vertex_group_name, \
sizeof(tmd->influence.vertex_group_name)); \
}
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilOpacity);
@ -7487,38 +7486,34 @@ static void rna_def_modifier_grease_pencil_layer_filter(StructRNA *srna)
{
PropertyRNA *prop;
# define PROPNAME_PREFIX "influence.layer_filter."
prop = RNA_def_property(srna, "layer_filter", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, nullptr, PROPNAME_PREFIX "layer_name");
RNA_def_property_string_sdna(prop, nullptr, "influence.layer_name");
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "use_layer_pass_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, PROPNAME_PREFIX "flag", GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER);
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER);
RNA_def_property_ui_text(prop, "Use Layer Pass", "Use layer pass filter");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "layer_pass_filter", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, nullptr, PROPNAME_PREFIX "layer_pass");
RNA_def_property_int_sdna(prop, nullptr, "influence.layer_pass");
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_text(prop, "Layer Pass", "Layer pass filter");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "invert_layer_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, PROPNAME_PREFIX "flag", GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER);
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER);
RNA_def_property_ui_text(prop, "Invert Layer", "Invert layer filter");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "invert_layer_pass_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, PROPNAME_PREFIX "flag", GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER);
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER);
RNA_def_property_ui_text(prop, "Invert Layer Pass", "Invert layer pass filter");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
# undef PROPNAME_PREFIX
}
static void rna_def_modifier_grease_pencil_material_filter(StructRNA *srna,
@ -7526,10 +7521,8 @@ static void rna_def_modifier_grease_pencil_material_filter(StructRNA *srna,
{
PropertyRNA *prop;
# define PROPNAME_PREFIX "influence.material_filter."
prop = RNA_def_property(srna, "material_filter", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, nullptr, PROPNAME_PREFIX "material");
RNA_def_property_pointer_sdna(prop, nullptr, "influence.material");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(
prop, nullptr, material_set_fn, nullptr, "rna_GreasePencilModifier_material_poll");
@ -7538,29 +7531,27 @@ static void rna_def_modifier_grease_pencil_material_filter(StructRNA *srna,
prop = RNA_def_property(srna, "use_material_pass_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, PROPNAME_PREFIX "flag", GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER);
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER);
RNA_def_property_ui_text(prop, "Use Material Pass", "Use material pass filter");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "material_pass_filter", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, nullptr, PROPNAME_PREFIX "material_pass");
RNA_def_property_int_sdna(prop, nullptr, "influence.material_pass");
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_text(prop, "Material Pass", "Material pass");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "invert_material_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, PROPNAME_PREFIX "flag", GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER);
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER);
RNA_def_property_ui_text(prop, "Invert Material", "Invert material filter");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "invert_material_pass_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, PROPNAME_PREFIX "flag", GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER);
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER);
RNA_def_property_ui_text(prop, "Invert Material Pass", "Invert material pass filter");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
# undef PROPNAME_PREFIX
}
static void rna_def_modifier_grease_pencil_vertex_group(StructRNA *srna,
@ -7568,42 +7559,34 @@ static void rna_def_modifier_grease_pencil_vertex_group(StructRNA *srna,
{
PropertyRNA *prop;
# define PROPNAME_PREFIX "influence.vertex_group."
prop = RNA_def_property(srna, "vertex_group_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, nullptr, PROPNAME_PREFIX "vertex_group_name");
RNA_def_property_string_sdna(prop, nullptr, "influence.vertex_group_name");
RNA_def_property_ui_text(prop, "Name", "Vertex group name for modulating the deform");
RNA_def_property_string_funcs(prop, nullptr, nullptr, vertex_group_name_set_fn);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, PROPNAME_PREFIX "flag", GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP);
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP);
RNA_def_property_ui_text(prop, "Invert Vertex Group", "Invert vertex group weights");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
# undef PROPNAME_PREFIX
}
static void rna_def_modifier_grease_pencil_custom_curve(StructRNA *srna)
{
PropertyRNA *prop;
LukasTonne marked this conversation as resolved
Review

Should this be rna_def_modifier_grease_pencil_vertex_group_filter to be consistent with the other filters?

Should this be `rna_def_modifier_grease_pencil_vertex_group_filter` to be consistent with the other filters?
Review

Not really, the other "filters" are purely selection masks based on layers or materials. The vertex group is always either a multiplier or, in the case of the opacity modifier, an offset/factor/something.

I appended the "filter" suffix to layer/material mostly so it would be clear that these are just selection criteria and their settings don't otherwise affect the modifier.

Not really, the other "filters" are purely selection masks based on layers or materials. The vertex group is always either a multiplier or, in the case of the opacity modifier, an offset/factor/something. I appended the "filter" suffix to layer/material mostly so it would be clear that these are just selection criteria and their settings don't otherwise affect the modifier.
# define PROPNAME_PREFIX "influence.custom_curve."
prop = RNA_def_property(srna, "use_custom_curve", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, PROPNAME_PREFIX "flag", GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE);
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE);
RNA_def_property_ui_text(
prop, "Use Custom Curve", "Use a custom curve to define a factor along the strokes");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "custom_curve", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, nullptr, PROPNAME_PREFIX "curve");
RNA_def_property_pointer_sdna(prop, nullptr, "influence.custom_curve");
RNA_def_property_ui_text(prop, "Curve", "Custom curve to apply effect");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
# undef PROPNAME_PREFIX
}
static void rna_def_modifier_grease_pencil_opacity(BlenderRNA *brna)

View File

@ -97,9 +97,9 @@ static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void
LukasTonne marked this conversation as resolved Outdated

Use the * operator overload to just store the VArray directly here

Use the * operator overload to just store the VArray directly here
/* XXX Placeholder for vertex groupn weights. */
static VArray<float> get_grease_pencil_modifier_vertex_weights(
const bke::CurvesGeometry &curves, const GreasePencilModifierVertexGroupData &vertex_group)
const bke::CurvesGeometry &curves, const GreasePencilModifierInfluenceData &influence_data)
{
const bool use_vertex_group = (vertex_group.vertex_group_name[0] != '\0');
const bool use_vertex_group = (influence_data.vertex_group_name[0] != '\0');
return VArray<float>::ForSingle(use_vertex_group ? 1.0f : 0.0f, curves.point_num);
}
@ -109,13 +109,12 @@ static void modify_stroke_color(const GreasePencilOpacityModifierData &omd,
{
const bool use_uniform_opacity = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY);
const bool use_vgroup_opacity = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_VERTEX_GROUP);
const bool invert_vertex_group = (omd.influence.vertex_group.flag &
const bool invert_vertex_group = (omd.influence.flag &
GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP);
const bool use_curve = (omd.influence.custom_curve.flag &
GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE);
const bool use_curve = (omd.influence.flag & GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE);
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const VArray<float> vgroup_weights = get_grease_pencil_modifier_vertex_weights(
curves, omd.influence.vertex_group);
const VArray<float> vgroup_weights = get_grease_pencil_modifier_vertex_weights(curves,
omd.influence);
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
bke::SpanAttributeWriter<float> opacities = attributes.lookup_or_add_for_write_span<float>(
@ -129,10 +128,9 @@ static void modify_stroke_color(const GreasePencilOpacityModifierData &omd,
const float curve_input = points_range.size() >= 2 ? (float(point_i - points_range.first()) /
float(points_range.size() - 1)) :
0.0f;
const float curve_factor = use_curve ?
BKE_curvemapping_evaluateF(
omd.influence.custom_curve.curve, 0, curve_input) :
1.0f;
const float curve_factor = use_curve ? BKE_curvemapping_evaluateF(
omd.influence.custom_curve, 0, curve_input) :
1.0f;

Wondering if this could be made much clean by using DefaultMixer?

Wondering if this could be made much clean by using `DefaultMixer`?

That seems a bit unnecessary here.

  • The attributes are all floats, no need to handle different types.
  • The math is weird and undocumented. In the "uniform" mode it uses 1 - current as some kind of cutoff point, and then allows ramping up the influence to 2.0, presumably so one can reach full opacity/hardness again. It all seems very ad-hoc.

I'd prefer to not try and "fix" this too much, since the primary purpose is compatibility with GP2.

That seems a bit unnecessary here. - The attributes are all floats, no need to handle different types. - The math is weird and undocumented. In the "uniform" mode it uses `1 - current` as some kind of cutoff point, and then allows ramping up the influence to 2.0, presumably so one can reach full opacity/hardness again. It all seems very ad-hoc. I'd prefer to not try and "fix" this too much, since the primary purpose is compatibility with GP2.
if (use_uniform_opacity) {
opacities.span[point_i] = std::clamp(curve_factor, 0.0f, 1.0f);
@ -165,11 +163,11 @@ static void modify_fill_color(const GreasePencilOpacityModifierData &omd,
const IndexMask &curves_mask)
{
const bool use_vgroup_opacity = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_VERTEX_GROUP);
LukasTonne marked this conversation as resolved
Review

points_range -> points is the cononical variable name here. "range" is already described by the type

`points_range` -> `points` is the cononical variable name here. "range" is already described by the type
const bool invert_vertex_group = (omd.influence.vertex_group.flag &
const bool invert_vertex_group = (omd.influence.flag &
LukasTonne marked this conversation as resolved
Review

You can count on the fact that curves always have at least one point

You can count on the fact that curves always have at least one point
Review

At least one or at least two? I need two for this length factor calculation.

At least one or at least two? I need two for this length factor calculation.
Review

Falk says curves can have 1 point only, so i still need to check.

Falk says curves can have 1 point only, so i still need to check.
GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP);
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const VArray<float> vgroup_weights = get_grease_pencil_modifier_vertex_weights(
curves, omd.influence.vertex_group);
const VArray<float> vgroup_weights = get_grease_pencil_modifier_vertex_weights(curves,
omd.influence);
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
/* Fill color opacity per stroke. */
@ -221,7 +219,7 @@ static void modify_curves(ModifierData *md,
IndexMaskMemory mask_memory;
IndexMask curves_mask = greasepencil::get_filtered_stroke_mask(
ctx->object, curves, omd->influence.material_filter, mask_memory);
ctx->object, curves, omd->influence, mask_memory);
switch (omd->color_mode) {
case MOD_GREASE_PENCIL_COLOR_STROKE:
@ -255,7 +253,7 @@ static void modify_geometry_set(ModifierData *md,
IndexMaskMemory mask_memory;
IndexMask layer_mask = greasepencil::get_filtered_layer_mask(
*grease_pencil, omd->influence.layer_filter, mask_memory);
*grease_pencil, omd->influence, mask_memory);
Vector<Drawing *> drawings = greasepencil::get_drawings_for_write(
*grease_pencil, layer_mask, frame);
for (Drawing *drawing : drawings) {

View File

@ -41,8 +41,8 @@ void init_influence_data(GreasePencilModifierInfluenceData *influence_data,
const bool has_custom_curve)
{
if (has_custom_curve) {
influence_data->custom_curve.curve = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_init(influence_data->custom_curve.curve);
influence_data->custom_curve = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_init(influence_data->custom_curve);
}
}
@ -51,15 +51,14 @@ void copy_influence_data(const GreasePencilModifierInfluenceData *influence_data
const int /*flag*/)
{
memcpy(influence_data_dst, influence_data_src, sizeof(GreasePencilModifierInfluenceData));
influence_data_dst->custom_curve.curve = BKE_curvemapping_copy(
influence_data_src->custom_curve.curve);
influence_data_dst->custom_curve = BKE_curvemapping_copy(influence_data_src->custom_curve);
}
void free_influence_data(GreasePencilModifierInfluenceData *influence_data)
{
if (influence_data->custom_curve.curve) {
BKE_curvemapping_free(influence_data->custom_curve.curve);
influence_data->custom_curve.curve = nullptr;
if (influence_data->custom_curve) {
BKE_curvemapping_free(influence_data->custom_curve);
influence_data->custom_curve = nullptr;
}
}
@ -68,7 +67,7 @@ void foreach_influence_ID_link(GreasePencilModifierInfluenceData *influence_data
IDWalkFunc walk,
void *user_data)
{
walk(user_data, ob, (ID **)&influence_data->material_filter.material, IDWALK_CB_USER);
walk(user_data, ob, (ID **)&influence_data->material, IDWALK_CB_USER);
}
void draw_layer_filter_settings(const bContext * /*C*/, uiLayout *layout, PointerRNA *ptr)
@ -212,19 +211,20 @@ static IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil,
}
IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil,
const GreasePencilModifierLayerFilter &filter,
const GreasePencilModifierInfluenceData &influence_data,
IndexMaskMemory &memory)
{
return get_filtered_layer_mask(grease_pencil,
filter.layer_name[0] != '\0' ?
std::make_optional<StringRef>(filter.layer_name) :
std::nullopt,
(filter.flag & GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER) ?
std::make_optional<int>(filter.layer_pass) :
std::nullopt,
filter.flag & GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER,
filter.flag & GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER,
memory);
return get_filtered_layer_mask(
grease_pencil,
influence_data.layer_name[0] != '\0' ?
std::make_optional<StringRef>(influence_data.layer_name) :
std::nullopt,
(influence_data.flag & GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER) ?
std::make_optional<int>(influence_data.layer_pass) :
std::nullopt,
influence_data.flag & GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER,
influence_data.flag & GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER,
memory);
}
static IndexMask get_filtered_stroke_mask(const Object *ob,
@ -271,19 +271,19 @@ static IndexMask get_filtered_stroke_mask(const Object *ob,
IndexMask get_filtered_stroke_mask(const Object *ob,
const bke::CurvesGeometry &curves,
const GreasePencilModifierMaterialFilter &filter,
const GreasePencilModifierInfluenceData &influence_data,
IndexMaskMemory &memory)
{
/* TODO Add an option to toggle pass filter on and off, instead of using "pass > 0". */
return get_filtered_stroke_mask(
ob,
curves,
filter.material,
(filter.flag & GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER) ?
std::make_optional<int>(filter.material_pass) :
influence_data.material,
(influence_data.flag & GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER) ?
std::make_optional<int>(influence_data.material_pass) :
std::nullopt,
filter.flag & GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER,
filter.flag & GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER,
influence_data.flag & GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER,
influence_data.flag & GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER,
memory);
}

View File

@ -47,12 +47,12 @@ void draw_vertex_group_settings(const bContext *C, uiLayout *layout, PointerRNA
void draw_custom_curve_settings(const bContext *C, uiLayout *layout, PointerRNA *ptr);
IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil,
const GreasePencilModifierLayerFilter &filter,
const GreasePencilModifierInfluenceData &influence_data,
IndexMaskMemory &memory);
IndexMask get_filtered_stroke_mask(const Object *ob,
const bke::CurvesGeometry &curves,
const GreasePencilModifierMaterialFilter &filter,
const GreasePencilModifierInfluenceData &influence_data,
IndexMaskMemory &memory);
Vector<bke::greasepencil::Drawing *> get_drawings_for_write(GreasePencil &grease_pencil,