1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-31 07:29:49 +00:00

Change paste placement behavior

Paste now places the pasted content in the middle of the canvas view, instead of its original position. A new option in the Edit menu has been added, "Paste in Place", that preserves the previous behavior. This is similar to how GIMP works.
This commit is contained in:
Emmanouil Papadeas 2022-09-15 00:08:22 +03:00
parent 7558c2c891
commit a64f102b9a
5 changed files with 75 additions and 41 deletions

View file

@ -124,6 +124,9 @@ msgstr ""
msgid "Paste" msgid "Paste"
msgstr "" msgstr ""
msgid "Paste in Place"
msgstr ""
msgid "Delete" msgid "Delete"
msgstr "" msgstr ""

View file

@ -850,6 +850,11 @@ gradient_map={
"deadzone": 0.5, "deadzone": 0.5,
"events": [ ] "events": [ ]
} }
paste_in_place={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":true,"shift":false,"control":true,"meta":false,"command":true,"pressed":false,"scancode":86,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
[locale] [locale]

View file

@ -8,7 +8,7 @@ enum ColorFrom { THEME, CUSTOM }
enum ButtonSize { SMALL, BIG } enum ButtonSize { SMALL, BIG }
enum FileMenu { NEW, OPEN, OPEN_LAST_PROJECT, RECENT, SAVE, SAVE_AS, EXPORT, EXPORT_AS, QUIT } enum FileMenu { NEW, OPEN, OPEN_LAST_PROJECT, RECENT, SAVE, SAVE_AS, EXPORT, EXPORT_AS, QUIT }
enum EditMenu { UNDO, REDO, COPY, CUT, PASTE, DELETE, NEW_BRUSH, PREFERENCES } enum EditMenu { UNDO, REDO, COPY, CUT, PASTE, PASTE_IN_PLACE, DELETE, NEW_BRUSH, PREFERENCES }
enum ViewMenu { enum ViewMenu {
TILE_MODE, TILE_MODE,
TILE_MODE_OFFSETS, TILE_MODE_OFFSETS,
@ -253,6 +253,8 @@ func _initialize_keychain() -> void:
"cut": Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.CUT), "cut": Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.CUT),
"copy": Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.COPY), "copy": Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.COPY),
"paste": Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.PASTE), "paste": Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.PASTE),
"paste_in_place":
Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.PASTE_IN_PLACE),
"delete": Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.DELETE), "delete": Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.DELETE),
"new_brush": "new_brush":
Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.NEW_BRUSH), Keychain.MenuInputAction.new("", "Edit menu", true, "EditMenu", EditMenu.NEW_BRUSH),

View file

@ -3,6 +3,7 @@ extends Node2D
enum SelectionOperation { ADD, SUBTRACT, INTERSECT } enum SelectionOperation { ADD, SUBTRACT, INTERSECT }
const KEY_MOVE_ACTION_NAMES := ["ui_up", "ui_down", "ui_left", "ui_right"] const KEY_MOVE_ACTION_NAMES := ["ui_up", "ui_down", "ui_left", "ui_right"]
const CLIPBOARD_FILE_PATH := "user://clipboard.txt"
var is_moving_content := false var is_moving_content := false
var arrow_key_move := false var arrow_key_move := false
@ -682,10 +683,10 @@ func copy() -> void:
to_copy = image.get_rect(big_bounding_rectangle) to_copy = image.get_rect(big_bounding_rectangle)
to_copy.lock() to_copy.lock()
# Remove unincluded pixels if the selection is not a single rectangle # Remove unincluded pixels if the selection is not a single rectangle
var offset_pos := big_bounding_rectangle.position
for x in to_copy.get_size().x: for x in to_copy.get_size().x:
for y in to_copy.get_size().y: for y in to_copy.get_size().y:
var pos := Vector2(x, y) var pos := Vector2(x, y)
var offset_pos = big_bounding_rectangle.position
if offset_pos.x < 0: if offset_pos.x < 0:
offset_pos.x = 0 offset_pos.x = 0
if offset_pos.y < 0: if offset_pos.y < 0:
@ -704,9 +705,9 @@ func copy() -> void:
"big_bounding_rectangle": cl_big_bounding_rectangle, "big_bounding_rectangle": cl_big_bounding_rectangle,
"selection_offset": cl_selection_offset, "selection_offset": cl_selection_offset,
} }
# Store to ".clipboard.txt" file
var clipboard_file := File.new() var clipboard_file := File.new()
clipboard_file.open("user://clipboard.txt", File.WRITE) clipboard_file.open(CLIPBOARD_FILE_PATH, File.WRITE)
clipboard_file.store_var(transfer_clipboard, true) clipboard_file.store_var(transfer_clipboard, true)
clipboard_file.close() clipboard_file.close()
@ -719,53 +720,66 @@ func copy() -> void:
container.get_child(0).get_child(0).texture = tex container.get_child(0).get_child(0).texture = tex
func paste() -> void: func paste(in_place := false) -> void:
# Read from the ".clipboard.txt" file
var clipboard_file := File.new() var clipboard_file := File.new()
if !clipboard_file.file_exists("user://clipboard.txt"): if !clipboard_file.file_exists(CLIPBOARD_FILE_PATH):
return return
clipboard_file.open("user://clipboard.txt", File.READ) clipboard_file.open(CLIPBOARD_FILE_PATH, File.READ)
var clipboard = clipboard_file.get_var(true) var clipboard = clipboard_file.get_var(true)
clipboard_file.close() clipboard_file.close()
if typeof(clipboard) == TYPE_DICTIONARY: # Sanity checks
# A sanity check if typeof(clipboard) != TYPE_DICTIONARY:
if not clipboard.has_all( return
["image", "selection_map", "big_bounding_rectangle", "selection_offset"] if !clipboard.has_all(["image", "selection_map", "big_bounding_rectangle", "selection_offset"]):
): return
return if clipboard.image.is_empty():
return
if clipboard.image.is_empty(): clear_selection()
return undo_data = get_undo_data(true)
clear_selection() var project: Project = Global.current_project
undo_data = get_undo_data(true)
var project: Project = Global.current_project
original_bitmap.copy_from(project.selection_map) original_bitmap.copy_from(project.selection_map)
original_big_bounding_rectangle = big_bounding_rectangle original_big_bounding_rectangle = big_bounding_rectangle
original_offset = project.selection_offset original_offset = project.selection_offset
var clip_map := SelectionMap.new() var clip_map := SelectionMap.new()
clip_map.data = clipboard.selection_map clip_map.data = clipboard.selection_map
var max_size := Vector2( var max_size := Vector2(
max(clip_map.get_size().x, project.selection_map.get_size().x), max(clip_map.get_size().x, project.selection_map.get_size().x),
max(clip_map.get_size().y, project.selection_map.get_size().y) max(clip_map.get_size().y, project.selection_map.get_size().y)
) )
project.selection_map = clip_map project.selection_map = clip_map
project.selection_map.crop(max_size.x, max_size.y) project.selection_map.crop(max_size.x, max_size.y)
self.big_bounding_rectangle = clipboard.big_bounding_rectangle project.selection_offset = clipboard.selection_offset
project.selection_offset = clipboard.selection_offset big_bounding_rectangle = clipboard.big_bounding_rectangle
if not in_place: # If "Paste" is selected, and not "Paste in Place"
var camera_center := Global.camera.get_camera_screen_center()
camera_center -= big_bounding_rectangle.size / 2
var max_pos := project.size - big_bounding_rectangle.size
if max_pos.x >= 0:
camera_center.x = clamp(camera_center.x, 0, max_pos.x)
else:
camera_center.x = 0
if max_pos.y >= 0:
camera_center.y = clamp(camera_center.y, 0, max_pos.y)
else:
camera_center.y = 0
big_bounding_rectangle.position = camera_center
project.selection_map.move_bitmap_values(Global.current_project, false)
temp_bitmap = project.selection_map self.big_bounding_rectangle = big_bounding_rectangle
temp_rect = big_bounding_rectangle temp_bitmap = project.selection_map
is_moving_content = true temp_rect = big_bounding_rectangle
is_pasting = true is_moving_content = true
original_preview_image = clipboard.image is_pasting = true
preview_image.copy_from(original_preview_image) original_preview_image = clipboard.image
preview_image_texture.create_from_image(preview_image, 0) preview_image.copy_from(original_preview_image)
preview_image_texture.create_from_image(preview_image, 0)
project.selection_map_changed() project.selection_map_changed()
func delete(selected_cels := true) -> void: func delete(selected_cels := true) -> void:

View file

@ -89,7 +89,15 @@ func update_recent_projects_submenu() -> void:
func _setup_edit_menu() -> void: func _setup_edit_menu() -> void:
# Order as in Global.EditMenu enum # Order as in Global.EditMenu enum
var edit_menu_items := [ var edit_menu_items := [
"Undo", "Redo", "Copy", "Cut", "Paste", "Delete", "New Brush", "Preferences" "Undo",
"Redo",
"Copy",
"Cut",
"Paste",
"Paste in Place",
"Delete",
"New Brush",
"Preferences"
] ]
var edit_menu: PopupMenu = edit_menu_button.get_popup() var edit_menu: PopupMenu = edit_menu_button.get_popup()
var i := 0 var i := 0
@ -401,6 +409,8 @@ func edit_menu_id_pressed(id: int) -> void:
Global.canvas.selection.cut() Global.canvas.selection.cut()
Global.EditMenu.PASTE: Global.EditMenu.PASTE:
Global.canvas.selection.paste() Global.canvas.selection.paste()
Global.EditMenu.PASTE_IN_PLACE:
Global.canvas.selection.paste(true)
Global.EditMenu.DELETE: Global.EditMenu.DELETE:
Global.canvas.selection.delete() Global.canvas.selection.delete()
Global.EditMenu.NEW_BRUSH: Global.EditMenu.NEW_BRUSH: