diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 7d2c70b99c8..fba00bdf54f 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -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 { diff --git a/source/blender/makesrna/intern/rna_modifier.cc b/source/blender/makesrna/intern/rna_modifier.cc index 12515336a72..9d1a21c813b 100644 --- a/source/blender/makesrna/intern/rna_modifier.cc +++ b/source/blender/makesrna/intern/rna_modifier.cc @@ -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, diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_util.cc b/source/blender/modifiers/intern/MOD_grease_pencil_util.cc index 232dc13b587..8adf95fa132 100644 --- a/source/blender/modifiers/intern/MOD_grease_pencil_util.cc +++ b/source/blender/modifiers/intern/MOD_grease_pencil_util.cc @@ -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 get_grease_pencil_material_passes(const Object *ob) } static IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil, - const std::optional layer_name_filter, + const std::optional tree_node_name_filter, const std::optional 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 layer_passes = layer_attributes.lookup_or_default("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) {