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:
parent
529962f91f
commit
7507206726
|
@ -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()
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue