app: quick on-canvas copy-paste multi-layer aware.

This commit is contained in:
Jehan 2020-05-17 23:00:07 +02:00
parent bb7f94ce3b
commit a7c59277fb
4 changed files with 88 additions and 35 deletions

View File

@ -35,6 +35,7 @@
#include "gimpdrawable-private.h" #include "gimpdrawable-private.h"
#include "gimperror.h" #include "gimperror.h"
#include "gimpimage.h" #include "gimpimage.h"
#include "gimpimage-new.h"
#include "gimpimage-undo.h" #include "gimpimage-undo.h"
#include "gimpimage-undo-push.h" #include "gimpimage-undo-push.h"
#include "gimplayer.h" #include "gimplayer.h"
@ -808,7 +809,7 @@ gimp_selection_extract (GimpSelection *selection,
GimpLayer * GimpLayer *
gimp_selection_float (GimpSelection *selection, gimp_selection_float (GimpSelection *selection,
GimpDrawable *drawable, GList *drawables,
GimpContext *context, GimpContext *context,
gboolean cut_image, gboolean cut_image,
gint off_x, gint off_x,
@ -817,22 +818,41 @@ gimp_selection_float (GimpSelection *selection,
{ {
GimpImage *image; GimpImage *image;
GimpLayer *layer; GimpLayer *layer;
GimpPickable *pickable;
GeglBuffer *buffer; GeglBuffer *buffer;
GimpColorProfile *profile; GimpColorProfile *profile;
GimpImage *temp_image = NULL;
const Babl *format = NULL;
GList *iter;
gint x1, y1; gint x1, y1;
gint x2, y2; gint x2, y2;
g_return_val_if_fail (GIMP_IS_SELECTION (selection), NULL); g_return_val_if_fail (GIMP_IS_SELECTION (selection), NULL);
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL);
for (iter = drawables; iter; iter = iter->next)
{
g_return_val_if_fail (GIMP_IS_DRAWABLE (iter->data), NULL);
g_return_val_if_fail (gimp_item_is_attached (iter->data), NULL);
if (! format)
format = gimp_drawable_get_format_with_alpha (iter->data);
else
g_return_val_if_fail (format == gimp_drawable_get_format_with_alpha (iter->data),
NULL);
}
image = gimp_item_get_image (GIMP_ITEM (selection)); image = gimp_item_get_image (GIMP_ITEM (selection));
/* Make sure there is a region to float... */ /* Make sure there is a region to float... */
if (! gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2) || for (iter = drawables; iter; iter = iter->next)
(x1 == x2 || y1 == y2)) {
if (gimp_item_mask_bounds (iter->data, &x1, &y1, &x2, &y2) &&
x1 != x2 && y1 != y2)
break;
}
if (iter == NULL)
{ {
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
_("Cannot float selection because the selected " _("Cannot float selection because the selected "
@ -844,22 +864,31 @@ gimp_selection_float (GimpSelection *selection,
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_FLOAT, gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_FLOAT,
C_("undo-type", "Float Selection")); C_("undo-type", "Float Selection"));
if (g_list_length (drawables) > 1)
{
temp_image = gimp_image_new_from_drawables (image->gimp, drawables, TRUE);
pickable = GIMP_PICKABLE (temp_image);
}
else
{
pickable = GIMP_PICKABLE (drawables->data);
}
/* Cut or copy the selected region */ /* Cut or copy the selected region */
buffer = gimp_selection_extract (selection, GIMP_PICKABLE (drawable), context, buffer = gimp_selection_extract (selection, pickable, context,
cut_image, FALSE, TRUE, cut_image, FALSE, TRUE,
&x1, &y1, NULL); &x1, &y1, NULL);
profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (drawable)); profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (pickable));
/* Clear the selection */ /* Clear the selection */
gimp_channel_clear (GIMP_CHANNEL (selection), NULL, TRUE); gimp_channel_clear (GIMP_CHANNEL (selection), NULL, TRUE);
/* Create a new layer from the buffer, using the drawable's type /* Create a new layer from the buffer, using the drawables' type
* because it may be different from the image's type if we cut from * because it may be different from the image's type if we cut from
* a channel or layer mask * a channel or layer mask
*/ */
layer = gimp_layer_new_from_gegl_buffer (buffer, image, layer = gimp_layer_new_from_gegl_buffer (buffer, image, format,
gimp_drawable_get_format_with_alpha (drawable),
_("Floated Layer"), _("Floated Layer"),
GIMP_OPACITY_OPAQUE, GIMP_OPACITY_OPAQUE,
gimp_image_get_default_new_layer_mode (image), gimp_image_get_default_new_layer_mode (image),
@ -872,7 +901,7 @@ gimp_selection_float (GimpSelection *selection,
g_object_unref (buffer); g_object_unref (buffer);
/* Add the floating layer to the image */ /* Add the floating layer to the image */
floating_sel_attach (layer, drawable); floating_sel_attach (layer, drawables->data);
/* End an undo group */ /* End an undo group */
gimp_image_undo_group_end (image); gimp_image_undo_group_end (image);
@ -880,5 +909,8 @@ gimp_selection_float (GimpSelection *selection,
/* invalidate the image's boundary variables */ /* invalidate the image's boundary variables */
GIMP_CHANNEL (selection)->boundary_known = FALSE; GIMP_CHANNEL (selection)->boundary_known = FALSE;
if (temp_image)
g_object_unref (temp_image);
return layer; return layer;
} }

View File

@ -65,7 +65,7 @@ GeglBuffer * gimp_selection_extract (GimpSelection *selection,
GError **error); GError **error);
GimpLayer * gimp_selection_float (GimpSelection *selection, GimpLayer * gimp_selection_float (GimpSelection *selection,
GimpDrawable *drawable, GList *drawables,
GimpContext *context, GimpContext *context,
gboolean cut_image, gboolean cut_image,
gint off_x, gint off_x,

View File

@ -595,7 +595,7 @@ gimp_edit_selection_tool_update_motion (GimpEditSelectionTool *edit_select,
case GIMP_TRANSLATE_MODE_MASK_TO_LAYER: case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER: case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
if (! gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)), if (! gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
GIMP_DRAWABLE (selected_items->data), selected_items,
gimp_get_user_context (display->gimp), gimp_get_user_context (display->gimp),
edit_select->edit_mode == edit_select->edit_mode ==
GIMP_TRANSLATE_MODE_MASK_TO_LAYER, GIMP_TRANSLATE_MODE_MASK_TO_LAYER,

View File

@ -225,7 +225,7 @@ gimp_selection_tool_oper_update (GimpTool *tool,
GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool); GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool);
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool); GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
GimpImage *image; GimpImage *image;
GimpDrawable *drawable; GList *drawables;
GimpLayer *layer; GimpLayer *layer;
GimpLayer *floating_sel; GimpLayer *floating_sel;
GdkModifierType extend_mask; GdkModifierType extend_mask;
@ -235,7 +235,7 @@ gimp_selection_tool_oper_update (GimpTool *tool,
gboolean move_floating_sel = FALSE; gboolean move_floating_sel = FALSE;
image = gimp_display_get_image (display); image = gimp_display_get_image (display);
drawable = gimp_image_get_active_drawable (image); drawables = gimp_image_get_selected_drawables (image);
layer = gimp_image_pick_layer (image, coords->x, coords->y, NULL); layer = gimp_image_pick_layer (image, coords->x, coords->y, NULL);
floating_sel = gimp_image_get_floating_selection (image); floating_sel = gimp_image_get_floating_selection (image);
@ -244,19 +244,29 @@ gimp_selection_tool_oper_update (GimpTool *tool,
have_selection = gimp_selection_tool_have_selection (selection_tool, display); have_selection = gimp_selection_tool_have_selection (selection_tool, display);
if (drawable) if (drawables)
{ {
if (floating_sel) if (floating_sel)
{ {
if (layer == floating_sel) if (layer == floating_sel)
move_floating_sel = TRUE; move_floating_sel = TRUE;
} }
else if (have_selection && else if (have_selection)
gimp_item_mask_intersect (GIMP_ITEM (drawable),
NULL, NULL, NULL, NULL))
{ {
move_layer = TRUE; GList *iter;
for (iter = drawables; iter; iter = iter->next)
{
if (gimp_item_mask_intersect (GIMP_ITEM (iter->data),
NULL, NULL, NULL, NULL))
{
move_layer = TRUE;
break;
}
}
} }
g_list_free (drawables);
} }
selection_tool->function = SELECTION_SELECT; selection_tool->function = SELECTION_SELECT;
@ -509,9 +519,8 @@ gimp_selection_tool_check (GimpSelectionTool *sel_tool,
GimpDisplay *display, GimpDisplay *display,
GError **error) GError **error)
{ {
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (sel_tool); GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (sel_tool);
GimpImage *image = gimp_display_get_image (display); GimpImage *image = gimp_display_get_image (display);
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
switch (sel_tool->function) switch (sel_tool->function)
{ {
@ -548,22 +557,34 @@ gimp_selection_tool_check (GimpSelectionTool *sel_tool,
case SELECTION_MOVE: case SELECTION_MOVE:
case SELECTION_MOVE_COPY: case SELECTION_MOVE_COPY:
if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
{ {
g_set_error (error, GIMP_ERROR, GIMP_FAILED, GList *drawables = gimp_image_get_selected_drawables (image);
_("Cannot modify the pixels of layer groups.")); GList *iter;
return FALSE; for (iter = drawables; iter; iter = iter->next)
} {
else if (gimp_item_is_content_locked (GIMP_ITEM (drawable))) if (gimp_viewable_get_children (iter->data))
{ {
g_set_error (error, GIMP_ERROR, GIMP_FAILED, g_set_error (error, GIMP_ERROR, GIMP_FAILED,
_("The active layer's pixels are locked.")); _("Cannot modify the pixels of layer groups."));
if (error) g_list_free (drawables);
gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable)); return FALSE;
}
else if (gimp_item_is_content_locked (iter->data))
{
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
_("The active layer's pixels are locked."));
return FALSE; if (error)
gimp_tools_blink_lock_box (display->gimp, iter->data);
g_list_free (drawables);
return FALSE;
}
}
g_list_free (drawables);
} }
break; break;