From f5cb425f8671d16147ffc2eccac49d0168d8fe74 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Tue, 28 Jan 2025 19:14:56 +0200 Subject: [PATCH] Add a "Paste from Clipboard" edit menu option Eventually, if Godot adds copying images into clipboard, we can replace Pixelorama's custom clipboard logic and just copy and paste to/from the operating system's clipboard. --- Translations/Translations.pot | 4 ++ project.godot | 5 +++ src/Autoload/Global.gd | 14 ++++++- src/UI/Canvas/Selection.gd | 42 +++++++++++++++++++++ src/UI/TopMenuContainer/TopMenuContainer.gd | 3 ++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/Translations/Translations.pot b/Translations/Translations.pot index fa56170b1..045f59023 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -134,6 +134,10 @@ msgstr "" msgid "Paste in Place" msgstr "" +#. Found under the Edit menu. When selected, the image from the clipboard, if it exists, gets pasted into Pixelorama. +msgid "Paste from Clipboard" +msgstr "" + msgid "Delete" msgstr "" diff --git a/project.godot b/project.godot index 248a3919d..1650d204a 100644 --- a/project.godot +++ b/project.godot @@ -177,6 +177,11 @@ paste_in_place={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"command_or_control_autoremap":true,"alt_pressed":true,"shift_pressed":false,"pressed":false,"keycode":86,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } +paste_from_clipboard={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":86,"key_label":0,"unicode":86,"location":0,"echo":false,"script":null) +] +} delete={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194312,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 37ff88a9b..b1add62ba 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -25,7 +25,18 @@ enum MeasurementMode { NONE, MOVE } ## Enumeration of items present in the File Menu. enum FileMenu { NEW, OPEN, OPEN_LAST_PROJECT, RECENT, SAVE, SAVE_AS, EXPORT, EXPORT_AS, QUIT } ## Enumeration of items present in the Edit Menu. -enum EditMenu { UNDO, REDO, COPY, CUT, PASTE, PASTE_IN_PLACE, DELETE, NEW_BRUSH, PREFERENCES } +enum EditMenu { + UNDO, + REDO, + COPY, + CUT, + PASTE, + PASTE_IN_PLACE, + PASTE_FROM_CLIPBOARD, + DELETE, + NEW_BRUSH, + PREFERENCES +} ## Enumeration of items present in the View Menu. enum ViewMenu { CENTER_CANVAS, @@ -793,6 +804,7 @@ func _initialize_keychain() -> void: &"copy": Keychain.InputAction.new("", "Edit menu", true), &"paste": Keychain.InputAction.new("", "Edit menu", true), &"paste_in_place": Keychain.InputAction.new("", "Edit menu", true), + &"paste_from_clipboard": Keychain.InputAction.new("", "Edit menu", true), &"delete": Keychain.InputAction.new("", "Edit menu", true), &"new_brush": Keychain.InputAction.new("", "Edit menu", true), &"preferences": Keychain.InputAction.new("", "Edit menu", true), diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index f116f0e2d..dda7a3758 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -883,6 +883,48 @@ func paste(in_place := false) -> void: project.selection_map_changed() +func paste_from_clipboard() -> void: + if not DisplayServer.clipboard_has_image(): + return + var clipboard_image := DisplayServer.clipboard_get_image() + if clipboard_image.is_empty() or clipboard_image.is_invisible(): + return + if is_moving_content: + transform_content_confirm() + undo_data = get_undo_data(true) + clear_selection() + var project := Global.current_project + var clip_map := SelectionMap.new() + clip_map.copy_from( + Image.create( + clipboard_image.get_width(), + clipboard_image.get_height(), + false, + project.selection_map.get_format() + ) + ) + clip_map.fill_rect(Rect2i(Vector2i.ZERO, clipboard_image.get_size()), Color(1, 1, 1, 1)) + var max_size := Vector2i( + maxi(clip_map.get_size().x, project.selection_map.get_size().x), + maxi(clip_map.get_size().y, project.selection_map.get_size().y) + ) + + project.selection_map.copy_from(clip_map) + project.selection_map.crop(max_size.x, max_size.y) + big_bounding_rectangle = project.selection_map.get_used_rect() + temp_rect = big_bounding_rectangle + resized_rect = big_bounding_rectangle + is_moving_content = true + is_pasting = true + original_preview_image = clipboard_image + original_big_bounding_rectangle = big_bounding_rectangle + original_offset = project.selection_offset + original_bitmap.copy_from(project.selection_map) + preview_image.copy_from(original_preview_image) + preview_image_texture = ImageTexture.create_from_image(preview_image) + project.selection_map_changed() + + ## Deletes the drawing enclosed within the selection's area. func delete(selected_cels := true) -> void: var project := Global.current_project diff --git a/src/UI/TopMenuContainer/TopMenuContainer.gd b/src/UI/TopMenuContainer/TopMenuContainer.gd index 2633e6fcd..940b5344e 100644 --- a/src/UI/TopMenuContainer/TopMenuContainer.gd +++ b/src/UI/TopMenuContainer/TopMenuContainer.gd @@ -211,6 +211,7 @@ func _setup_edit_menu() -> void: "Cut": "cut", "Paste": "paste", "Paste in Place": "paste_in_place", + "Paste from Clipboard": "paste_from_clipboard", "Delete": "delete", "New Brush": "new_brush", "Preferences": "preferences" @@ -682,6 +683,8 @@ func edit_menu_id_pressed(id: int) -> void: Global.canvas.selection.paste() Global.EditMenu.PASTE_IN_PLACE: Global.canvas.selection.paste(true) + Global.EditMenu.PASTE_FROM_CLIPBOARD: + Global.canvas.selection.paste_from_clipboard() Global.EditMenu.DELETE: Global.canvas.selection.delete() Global.EditMenu.NEW_BRUSH: