From cdd5174055d6887ddbb215a1e20222de679b7dfd Mon Sep 17 00:00:00 2001 From: Alx Sa Date: Fri, 2 Feb 2024 11:33:00 +0000 Subject: [PATCH] tools: Add option for destructive filters Adds a checkbox in the Filter tool so that users can choose to apply a filter destructively or non-destructively. Currently only layers can have NDE effects so it's not shown for masks and other drawables. Additionally, filters are moved to the top or the bottom of the filter stack depending on the setting (as destructive filters are applied directly to the layer while NDE filters are put on the top by default). --- app/tools/gimpfilteroptions.c | 19 +++++++++++- app/tools/gimpfilteroptions.h | 2 ++ app/tools/gimpfiltertool.c | 55 ++++++++++++++++++++++++++++++---- app/widgets/gimpitemtreeview.c | 17 ++++++----- 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/app/tools/gimpfilteroptions.c b/app/tools/gimpfilteroptions.c index 37de75f49a..8f74366586 100644 --- a/app/tools/gimpfilteroptions.c +++ b/app/tools/gimpfilteroptions.c @@ -39,7 +39,8 @@ enum PROP_PREVIEW_SPLIT_POSITION, PROP_CONTROLLER, PROP_BLENDING_OPTIONS_EXPANDED, - PROP_COLOR_OPTIONS_EXPANDED + PROP_COLOR_OPTIONS_EXPANDED, + PROP_MERGE_FILTER }; @@ -115,6 +116,14 @@ gimp_filter_options_class_init (GimpFilterOptionsClass *klass) NULL, NULL, FALSE, GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_MERGE_FILTER, + "merge-filter", + _("_Merge filter"), + _("If enabled, the filter is immediately merged.\n" + "Otherwise, it becomes an editable non-destructive filter."), + FALSE, + GIMP_PARAM_STATIC_STRINGS); } static void @@ -160,6 +169,10 @@ gimp_filter_options_set_property (GObject *object, options->color_options_expanded = g_value_get_boolean (value); break; + case PROP_MERGE_FILTER: + options->merge_filter = g_value_get_boolean (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -204,6 +217,10 @@ gimp_filter_options_get_property (GObject *object, g_value_set_boolean (value, options->color_options_expanded); break; + case PROP_MERGE_FILTER: + g_value_set_boolean (value, options->merge_filter); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; diff --git a/app/tools/gimpfilteroptions.h b/app/tools/gimpfilteroptions.h index 7cd3b5fa26..1fb39b19a5 100644 --- a/app/tools/gimpfilteroptions.h +++ b/app/tools/gimpfilteroptions.h @@ -44,6 +44,8 @@ struct _GimpFilterOptions gboolean blending_options_expanded; gboolean color_options_expanded; + + gboolean merge_filter; }; struct _GimpFilterOptionsClass diff --git a/app/tools/gimpfiltertool.c b/app/tools/gimpfiltertool.c index 8cbf7ed719..671b471464 100644 --- a/app/tools/gimpfiltertool.c +++ b/app/tools/gimpfiltertool.c @@ -392,7 +392,20 @@ gimp_filter_tool_initialize (GimpTool *tool, toggle = gimp_prop_check_button_new (G_OBJECT (tool_info->tool_options), "preview", NULL); - gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0); + + /* Only show merge filter option if we're not editing an NDE filter */ + if (GIMP_IS_LAYER (drawable) && ! filter_tool->existing_filter) + { + gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); + + toggle = gimp_prop_check_button_new (G_OBJECT (tool_info->tool_options), + "merge-filter", NULL); + gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0); + } + else + { + gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0); + } toggle = gimp_prop_check_button_new (G_OBJECT (tool_info->tool_options), "preview-split", NULL); @@ -459,10 +472,11 @@ gimp_filter_tool_control (GimpTool *tool, GimpToolAction action, GimpDisplay *display) { - GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (tool); - GimpDrawable *drawable = NULL; - gboolean non_destructive = TRUE; - gchar *operation_name = NULL; + GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (tool); + GimpFilterOptions *options = GIMP_FILTER_TOOL_GET_OPTIONS (filter_tool); + GimpDrawable *drawable = NULL; + gboolean non_destructive = TRUE; + gchar *operation_name = NULL; switch (action) { @@ -480,7 +494,8 @@ gimp_filter_tool_control (GimpTool *tool, /* TODO: Expand non-destructive editing to other drawables * besides layers */ - if (! GIMP_IS_LAYER (drawable)) + if (! GIMP_IS_LAYER (drawable) || + (! filter_tool->existing_filter && options->merge_filter)) non_destructive = FALSE; if (filter_tool->operation) @@ -788,6 +803,28 @@ gimp_filter_tool_options_notify (GimpTool *tool, if (filter_options->preview_split) gimp_filter_tool_move_guide (filter_tool); } + else if (! strcmp (pspec->name, "merge-filter") && + filter_tool->filter) + { + GimpDrawable *drawable = tool->drawables->data; + GimpContainer *filters = gimp_drawable_get_filters (drawable); + gint count = gimp_container_get_n_children (filters); + + if (count > 1) + { + if (filter_options->merge_filter) + gimp_container_reorder (filters, GIMP_OBJECT (filter_tool->filter), + count - 1); + else + gimp_container_reorder (filters, GIMP_OBJECT (filter_tool->filter), + 0); + + gimp_item_set_visible (GIMP_ITEM (drawable), FALSE, FALSE); + gimp_image_flush (gimp_item_get_image (GIMP_ITEM (drawable))); + gimp_item_set_visible (GIMP_ITEM (drawable), TRUE, FALSE); + gimp_image_flush (gimp_item_get_image (GIMP_ITEM (drawable))); + } + } else if (! strcmp (pspec->name, "controller") && filter_tool->widget) { @@ -1127,6 +1164,7 @@ gimp_filter_tool_commit (GimpFilterTool *filter_tool, if (filter_tool->filter) { + GimpDrawable *drawable; GimpFilterOptions *options = GIMP_FILTER_TOOL_GET_OPTIONS (tool); if (! options->preview) @@ -1162,12 +1200,17 @@ gimp_filter_tool_commit (GimpFilterTool *filter_tool, drawable, filter_tool->filter); } + drawable = gimp_drawable_filter_get_drawable (filter_tool->filter); + g_clear_object (&filter_tool->filter); gimp_tool_control_pop_preserve (tool->control); gimp_filter_tool_remove_guide (filter_tool); + gimp_item_set_visible (GIMP_ITEM (drawable), FALSE, FALSE); + gimp_image_flush (gimp_display_get_image (tool->display)); + gimp_item_set_visible (GIMP_ITEM (drawable), TRUE, FALSE); gimp_image_flush (gimp_display_get_image (tool->display)); if (filter_tool->config && filter_tool->has_settings) diff --git a/app/widgets/gimpitemtreeview.c b/app/widgets/gimpitemtreeview.c index eb813b6b48..5615d63775 100644 --- a/app/widgets/gimpitemtreeview.c +++ b/app/widgets/gimpitemtreeview.c @@ -2915,16 +2915,19 @@ gimp_item_tree_view_filters_changed (GimpItem *item, filters = gimp_drawable_get_filters (GIMP_DRAWABLE (item)); /* Since floating selections are also stored in the filter stack, * we need to verify what's in there to get the correct count */ - for (filter_list = GIMP_LIST (filters)->queue->tail; filter_list; - filter_list = g_list_previous (filter_list)) + if (filters) { - if (GIMP_IS_DRAWABLE_FILTER (filter_list->data)) - n_filters++; - else - fs_disabled = TRUE; + for (filter_list = GIMP_LIST (filters)->queue->tail; filter_list; + filter_list = g_list_previous (filter_list)) + { + if (GIMP_IS_DRAWABLE_FILTER (filter_list->data)) + n_filters++; + else + fs_disabled = TRUE; + } } - if (fs_disabled) + if (n_filters == 0 || fs_disabled) view->priv->effects_filter = NULL; if (iter)