Grease Pencil: Allow filtering by layer groups in modifiers

Previously modifiers can only filter single layers, now filtering by
layer group is also supported.

This adds a toggle to the layer filter to switch to filtering by groups.

Resolves  #123323.

Pull Request: https://projects.blender.org/blender/blender/pulls/123353
This commit is contained in:
YimingWu
2025-05-19 13:56:35 +02:00
committed by Falk David
parent d87e0ecb61
commit 236f401695
3 changed files with 54 additions and 15 deletions

View File

@@ -2663,6 +2663,7 @@ typedef enum GreasePencilModifierInfluenceFlag {
GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER = (1 << 5),
GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP = (1 << 6),
GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE = (1 << 7),
GREASE_PENCIL_INFLUENCE_USE_LAYER_GROUP_FILTER = (1 << 8),
} GreasePencilModifierInfluenceFlag;
typedef struct GreasePencilOpacityModifierData {

View File

@@ -8374,7 +8374,7 @@ static void rna_def_modifier_grease_pencil_layer_filter(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "layer_filter", PROP_STRING, PROP_NONE);
prop = RNA_def_property(srna, "tree_node_filter", PROP_STRING, PROP_NONE);
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");
@@ -8402,6 +8402,12 @@ static void rna_def_modifier_grease_pencil_layer_filter(StructRNA *srna)
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");
prop = RNA_def_property(srna, "use_layer_group_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_USE_LAYER_GROUP_FILTER);
RNA_def_property_ui_text(prop, "Layer Group", "Filter by layer group name");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_grease_pencil_material_filter(StructRNA *srna,

View File

@@ -38,6 +38,7 @@ namespace blender::modifier::greasepencil {
using bke::greasepencil::Drawing;
using bke::greasepencil::FramesMapKeyT;
using bke::greasepencil::Layer;
using bke::greasepencil::LayerGroup;
void init_influence_data(GreasePencilModifierInfluenceData *influence_data,
const bool has_custom_curve)
@@ -96,6 +97,7 @@ void draw_layer_filter_settings(const bContext * /*C*/, uiLayout *layout, Pointe
PointerRNA ob_ptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_Object, ptr->owner_id);
PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
const bool use_layer_pass = RNA_boolean_get(ptr, "use_layer_pass_filter");
const bool use_layer_group_filter = RNA_boolean_get(ptr, "use_layer_group_filter");
uiLayout *row, *col, *sub, *subsub;
uiLayoutSetPropSep(layout, true);
@@ -103,14 +105,26 @@ void draw_layer_filter_settings(const bContext * /*C*/, uiLayout *layout, Pointe
col = &layout->column(true);
row = &col->row(true);
uiLayoutSetPropDecorate(row, false);
uiItemPointerR(row,
ptr,
"layer_filter",
&obj_data_ptr,
"layers",
std::nullopt,
ICON_OUTLINER_DATA_GP_LAYER);
if (use_layer_group_filter) {
uiItemPointerR(row,
ptr,
"tree_node_filter",
&obj_data_ptr,
"layer_groups",
"Group",
ICON_GREASEPENCIL_LAYER_GROUP);
}
else {
uiItemPointerR(row,
ptr,
"tree_node_filter",
&obj_data_ptr,
"layers",
std::nullopt,
ICON_OUTLINER_DATA_GP_LAYER);
}
sub = &row->row(true);
sub->prop(ptr, "use_layer_group_filter", UI_ITEM_NONE, "", ICON_GREASEPENCIL_LAYER_GROUP);
sub->prop(ptr, "invert_layer_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
row = &col->row(true, IFACE_("Layer Pass"));
@@ -202,14 +216,14 @@ static Vector<int> get_grease_pencil_material_passes(const Object *ob)
}
static IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil,
const std::optional<StringRef> layer_name_filter,
const std::optional<StringRef> tree_node_name_filter,
const std::optional<int> layer_pass_filter,
const bool layer_filter_invert,
const bool layer_pass_filter_invert,
IndexMaskMemory &memory)
{
const IndexMask full_mask = grease_pencil.layers().index_range();
if (!layer_name_filter && !layer_pass_filter) {
if (!tree_node_name_filter && !layer_pass_filter) {
return full_mask;
}
@@ -218,13 +232,31 @@ static IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil,
const VArray<int> layer_passes =
layer_attributes.lookup_or_default<int>("pass_index", bke::AttrDomain::Layer, 0).varray;
const LayerGroup *filter_layer_group = nullptr;
if (tree_node_name_filter) {
for (const LayerGroup *group : grease_pencil.layer_groups()) {
if (group->name() == tree_node_name_filter.value()) {
filter_layer_group = group;
break;
}
}
}
IndexMask result = IndexMask::from_predicate(
full_mask, GrainSize(4096), memory, [&](const int64_t layer_i) {
if (layer_name_filter) {
const Layer &layer = *layers[layer_i];
const bool match = (layer.name() == layer_name_filter.value());
if (match == layer_filter_invert) {
return false;
if (tree_node_name_filter) {
const Layer *layer = layers[layer_i];
if (filter_layer_group) {
const bool match = layer->is_child_of(*filter_layer_group);
if (match == layer_filter_invert) {
return false;
}
}
else {
const bool match = (layer->name() == tree_node_name_filter.value());
if (match == layer_filter_invert) {
return false;
}
}
}
if (layer_pass_filter) {