1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

Move all selected frames - implements #743

This only works for frames at the moment, not layers and cels. Layers may be harder to support because they also have children. Supports both the "move left/right" options and drag and dropping. Frame swapping (with control) only works when one frame is selected, because I am unsure how they should be handled, especially when the selected frames are not continuous.

Didn't encounter any issues on my testing, but more testing is always welcome.
This commit is contained in:
Emmanouil Papadeas 2024-04-11 18:03:43 +03:00
parent 529962f91f
commit 7507206726
3 changed files with 81 additions and 58 deletions

View file

@ -630,14 +630,18 @@ func remove_frames(indices: Array) -> void: # indices should be in ascending or
_update_frame_ui()
func move_frame(from_index: int, to_index: int) -> void:
# from_indices and to_indicies should be in ascending order
func move_frames(from_indices: PackedInt32Array, to_indices: PackedInt32Array) -> void:
Global.canvas.selection.transform_content_confirm()
selected_cels.clear()
var frame := frames[from_index]
frames.remove_at(from_index)
Global.animation_timeline.project_frame_removed(from_index)
frames.insert(to_index, frame)
Global.animation_timeline.project_frame_added(to_index)
var removed_frames := []
for i in from_indices.size():
# With each removed index, future indices need to be lowered, so subtract by i
removed_frames.append(frames.pop_at(from_indices[i] - i))
Global.animation_timeline.project_frame_removed(from_indices[i] - i)
for i in to_indices.size():
frames.insert(to_indices[i], removed_frames[i])
Global.animation_timeline.project_frame_added(to_indices[i])
_update_frame_ui()

View file

@ -509,13 +509,46 @@ func _on_FrameTagButton_pressed() -> void:
func _on_MoveLeft_pressed() -> void:
if Global.current_project.current_frame == 0:
return
Global.frame_hbox.get_child(Global.current_project.current_frame).change_frame_order(-1)
move_frames(Global.current_project.current_frame, -1)
func _on_MoveRight_pressed() -> void:
if Global.current_project.current_frame == Global.current_project.frames.size() - 1:
return
Global.frame_hbox.get_child(Global.current_project.current_frame).change_frame_order(1)
move_frames(Global.current_project.current_frame, 1)
func move_frames(frame: int, rate: int) -> void:
var project := Global.current_project
var frame_indices: PackedInt32Array = []
var moved_frame_indices: PackedInt32Array = []
for cel in project.selected_cels:
var frame_index: int = cel[0]
if not frame_indices.has(frame_index):
frame_indices.append(frame_index)
moved_frame_indices.append(frame_index + rate)
frame_indices.sort()
moved_frame_indices.sort()
if not frame in frame_indices:
frame_indices = [frame]
moved_frame_indices = [frame + rate]
for moved_index in moved_frame_indices:
# Don't allow frames to be moved if they are out of bounds
if moved_index < 0 or moved_index >= project.frames.size():
return
project.undo_redo.create_action("Change Frame Order")
project.undo_redo.add_do_method(project.move_frames.bind(frame_indices, moved_frame_indices))
project.undo_redo.add_undo_method(project.move_frames.bind(moved_frame_indices, frame_indices))
if project.current_frame in frame_indices:
project.undo_redo.add_do_method(project.change_cel.bind(frame + rate))
else:
project.undo_redo.add_do_method(project.change_cel.bind(project.current_frame))
project.undo_redo.add_undo_method(project.change_cel.bind(project.current_frame))
project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true))
project.undo_redo.add_do_method(Global.undo_or_redo.bind(false))
project.undo_redo.commit_action()
func reverse_frames(indices := []) -> void:

View file

@ -84,9 +84,9 @@ func _on_PopupMenu_id_pressed(id: int) -> void:
CLONE:
Global.animation_timeline.copy_frames(indices)
MOVE_LEFT:
change_frame_order(-1)
Global.animation_timeline.move_frames(frame, -1)
MOVE_RIGHT:
change_frame_order(1)
Global.animation_timeline.move_frames(frame, 1)
PROPERTIES:
frame_properties.frame_indices = indices
frame_properties.popup_centered()
@ -97,25 +97,6 @@ func _on_PopupMenu_id_pressed(id: int) -> void:
DrawingAlgos.center(indices)
func change_frame_order(rate: int) -> void:
var change := frame + rate
var project := Global.current_project
project.undo_redo.create_action("Change Frame Order")
project.undo_redo.add_do_method(project.move_frame.bind(frame, change))
project.undo_redo.add_undo_method(project.move_frame.bind(change, frame))
if project.current_frame == frame:
project.undo_redo.add_do_method(project.change_cel.bind(change))
else:
project.undo_redo.add_do_method(project.change_cel.bind(project.current_frame))
project.undo_redo.add_undo_method(project.change_cel.bind(project.current_frame))
project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true))
project.undo_redo.add_do_method(Global.undo_or_redo.bind(false))
project.undo_redo.commit_action()
func _get_drag_data(_position: Vector2) -> Variant:
var button := Button.new()
button.size = size
@ -123,50 +104,55 @@ func _get_drag_data(_position: Vector2) -> Variant:
button.text = text
set_drag_preview(button)
return ["Frame", frame]
return ["Frame", _get_frame_indices()]
func _can_drop_data(_pos: Vector2, data) -> bool:
if typeof(data) == TYPE_ARRAY:
if data[0] == "Frame":
if data[1] != frame: # Can't move to same frame
var region: Rect2
if Input.is_action_pressed("ctrl"): # Swap frames
region = get_global_rect()
else: # Move frames
if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()):
region = _get_region_rect(-0.125, 0.125)
region.position.x -= 2 # Container spacing
else:
region = _get_region_rect(0.875, 1.125)
region.position.x += 2 # Container spacing
Global.animation_timeline.drag_highlight.global_position = region.position
Global.animation_timeline.drag_highlight.size = region.size
Global.animation_timeline.drag_highlight.visible = true
return true
Global.animation_timeline.drag_highlight.visible = false
return false
if typeof(data) != TYPE_ARRAY:
Global.animation_timeline.drag_highlight.visible = false
return false
if data[0] != "Frame":
Global.animation_timeline.drag_highlight.visible = false
return false
var drop_frames: PackedInt32Array = data[1]
# Can't move to same frame
if drop_frames[-1] == frame:
Global.animation_timeline.drag_highlight.visible = false
return false
var region: Rect2
if Input.is_action_pressed("ctrl") and drop_frames.size() == 1: # Swap frames
region = get_global_rect()
else: # Move frames
if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()):
region = _get_region_rect(-0.125, 0.125)
else:
region = _get_region_rect(0.875, 1.125)
Global.animation_timeline.drag_highlight.global_position = region.position
Global.animation_timeline.drag_highlight.size = region.size
Global.animation_timeline.drag_highlight.visible = true
return true
func _drop_data(_pos: Vector2, data) -> void:
var drop_frame: int = data[1]
var drop_frames: PackedInt32Array = data[1]
var project := Global.current_project
project.undo_redo.create_action("Change Frame Order")
if Input.is_action_pressed("ctrl"): # Swap frames
project.undo_redo.add_do_method(project.swap_frame.bind(frame, drop_frame))
project.undo_redo.add_undo_method(project.swap_frame.bind(frame, drop_frame))
if Input.is_action_pressed("ctrl") and drop_frames.size() == 1: # Swap frames
project.undo_redo.add_do_method(project.swap_frame.bind(frame, drop_frames[0]))
project.undo_redo.add_undo_method(project.swap_frame.bind(frame, drop_frames[0]))
else: # Move frames
var to_frame: int
if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Left
to_frame = frame
else: # Right
to_frame = frame + 1
if drop_frame < frame:
to_frame -= 1
project.undo_redo.add_do_method(project.move_frame.bind(drop_frame, to_frame))
project.undo_redo.add_undo_method(project.move_frame.bind(to_frame, drop_frame))
if drop_frames[-1] < frame:
to_frame -= drop_frames.size()
var to_frames := range(to_frame, to_frame + drop_frames.size())
project.undo_redo.add_do_method(project.move_frames.bind(drop_frames, to_frames))
project.undo_redo.add_undo_method(project.move_frames.bind(to_frames, drop_frames))
if project.current_frame == drop_frame:
if project.current_frame in drop_frames:
project.undo_redo.add_do_method(project.change_cel.bind(frame))
else:
project.undo_redo.add_do_method(project.change_cel.bind(project.current_frame))