mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-30 23:19: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:
parent
7558c2c891
commit
a64f102b9a
|
@ -124,6 +124,9 @@ msgstr ""
|
||||||
msgid "Paste"
|
msgid "Paste"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Paste in Place"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue