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).
This commit is contained in:
Alx Sa 2024-02-02 11:33:00 +00:00
parent 946a4d1af9
commit cdd5174055
4 changed files with 79 additions and 14 deletions

View File

@ -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;

View File

@ -44,6 +44,8 @@ struct _GimpFilterOptions
gboolean blending_options_expanded;
gboolean color_options_expanded;
gboolean merge_filter;
};
struct _GimpFilterOptionsClass

View File

@ -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)

View File

@ -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)