From e3ee931059c5c219b1efdc0acf29a9337aadadf4 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Wed, 8 May 2024 03:44:26 +0300 Subject: [PATCH] Move and resize tags by dragging their edges --- src/Classes/AnimationTag.gd | 6 +++ src/UI/Timeline/AnimationTagUI.gd | 80 +++++++++++++++++++++++++++-- src/UI/Timeline/AnimationTagUI.tscn | 26 ++++++++++ src/UI/Timeline/TagProperties.gd | 4 +- 4 files changed, 110 insertions(+), 6 deletions(-) diff --git a/src/Classes/AnimationTag.gd b/src/Classes/AnimationTag.gd index bb5f2b834..b5a57cbd9 100644 --- a/src/Classes/AnimationTag.gd +++ b/src/Classes/AnimationTag.gd @@ -67,6 +67,12 @@ func serialize() -> Dictionary: return dict +func duplicate() -> AnimationTag: + var new_tag := AnimationTag.new(name, color, from, to) + new_tag.user_data = user_data + return new_tag + + func get_size() -> int: return to - from + 1 diff --git a/src/UI/Timeline/AnimationTagUI.gd b/src/UI/Timeline/AnimationTagUI.gd index 728afc039..60cafe755 100644 --- a/src/UI/Timeline/AnimationTagUI.gd +++ b/src/UI/Timeline/AnimationTagUI.gd @@ -1,6 +1,11 @@ extends Control +enum Drag { NONE, FROM, TO } + var tag: AnimationTag +var dragging_tag: AnimationTag +var dragged_initial := 0 +var is_dragging := Drag.NONE @onready var tag_properties := Global.control.find_child("TagProperties") as ConfirmationDialog @@ -13,9 +18,9 @@ func _ready() -> void: update_position_and_size() -func update_position_and_size() -> void: - position = tag.get_position() - custom_minimum_size.x = tag.get_minimum_size() +func update_position_and_size(from_tag := tag) -> void: + position = from_tag.get_position() + custom_minimum_size.x = from_tag.get_minimum_size() size.x = custom_minimum_size.x $Line2D.points[2].x = custom_minimum_size.x $Line2D.points[3].x = custom_minimum_size.x @@ -24,3 +29,72 @@ func update_position_and_size() -> void: func _on_button_pressed() -> void: var tag_id := Global.current_project.animation_tags.find(tag) tag_properties.show_dialog(Rect2i(), tag_id, true) + + +func _resize_tag(resize: Drag, value: int) -> void: + var new_animation_tags: Array[AnimationTag] = [] + # Loop through the tags to create new classes for them, so that they won't be the same + # as Global.current_project.animation_tags's classes. Needed for undo/redo to work properly. + for frame_tag in Global.current_project.animation_tags: + new_animation_tags.append(frame_tag.duplicate()) + + var tag_id := Global.current_project.animation_tags.find(tag) + if resize == Drag.FROM: + if new_animation_tags[tag_id].from == value: + return + new_animation_tags[tag_id].from = value + elif resize == Drag.TO: + if new_animation_tags[tag_id].to == value: + return + new_animation_tags[tag_id].to = value + + # Handle Undo/Redo + Global.current_project.undos += 1 + Global.current_project.undo_redo.create_action("Resize Frame Tag") + Global.current_project.undo_redo.add_do_method(Global.general_redo) + Global.current_project.undo_redo.add_undo_method(Global.general_undo) + Global.current_project.undo_redo.add_do_property( + Global.current_project, &"animation_tags", new_animation_tags + ) + Global.current_project.undo_redo.add_undo_property( + Global.current_project, &"animation_tags", Global.current_project.animation_tags + ) + Global.current_project.undo_redo.commit_action() + + +func _on_resize_from_gui_input(event: InputEvent) -> void: + var cel_size: int = Global.animation_timeline.cel_size + if event is InputEventMouseButton: + if event.pressed: + is_dragging = Drag.FROM + dragging_tag = tag.duplicate() + dragged_initial = global_position.x + else: + _resize_tag(is_dragging, dragging_tag.from) + is_dragging = Drag.NONE + dragging_tag = null + elif event is InputEventMouseMotion: + if is_dragging == Drag.FROM: + var dragged_offset := snappedi(event.global_position.x, cel_size) + var diff := roundi(float(dragged_offset - dragged_initial) / cel_size) + dragging_tag.from = clampi(tag.from + diff, 1, tag.to) + update_position_and_size(dragging_tag) + + +func _on_resize_to_gui_input(event: InputEvent) -> void: + var cel_size: int = Global.animation_timeline.cel_size + if event is InputEventMouseButton: + if event.pressed: + is_dragging = Drag.TO + dragging_tag = tag.duplicate() + dragged_initial = global_position.x + size.x + else: + _resize_tag(is_dragging, dragging_tag.to) + is_dragging = Drag.NONE + dragging_tag = null + elif event is InputEventMouseMotion: + if is_dragging == Drag.TO: + var dragged_offset := snappedi(event.global_position.x, cel_size) + var diff := roundi(float(dragged_offset - dragged_initial) / cel_size) + dragging_tag.to = clampi(tag.to + diff, tag.from, Global.current_project.frames.size()) + update_position_and_size(dragging_tag) diff --git a/src/UI/Timeline/AnimationTagUI.tscn b/src/UI/Timeline/AnimationTagUI.tscn index 7923c6998..e7eeb3de3 100644 --- a/src/UI/Timeline/AnimationTagUI.tscn +++ b/src/UI/Timeline/AnimationTagUI.tscn @@ -38,4 +38,30 @@ mouse_default_cursor_shape = 2 text = "Idle" flat = true +[node name="ResizeFrom" type="Button" parent="."] +modulate = Color(1, 1, 1, 0) +layout_mode = 0 +offset_left = -4.0 +offset_right = 4.0 +offset_bottom = 32.0 +mouse_default_cursor_shape = 10 +keep_pressed_outside = true +flat = true + +[node name="ResizeTo" type="Button" parent="."] +modulate = Color(1, 1, 1, 0) +layout_mode = 1 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -4.0 +offset_right = 4.0 +offset_bottom = 32.0 +grow_horizontal = 0 +mouse_default_cursor_shape = 10 +keep_pressed_outside = true +flat = true + [connection signal="pressed" from="Button" to="." method="_on_button_pressed"] +[connection signal="gui_input" from="ResizeFrom" to="." method="_on_resize_from_gui_input"] +[connection signal="gui_input" from="ResizeTo" to="." method="_on_resize_to_gui_input"] diff --git a/src/UI/Timeline/TagProperties.gd b/src/UI/Timeline/TagProperties.gd index cf41f4784..e0604bd8d 100644 --- a/src/UI/Timeline/TagProperties.gd +++ b/src/UI/Timeline/TagProperties.gd @@ -47,9 +47,7 @@ func _on_confirmed() -> void: # Loop through the tags to create new classes for them, so that they won't be the same # as Global.current_project.animation_tags's classes. Needed for undo/redo to work properly. for tag in Global.current_project.animation_tags: - var new_tag := AnimationTag.new(tag.name, tag.color, tag.from, tag.to) - new_tag.user_data = tag.user_data - new_animation_tags.append(new_tag) + new_animation_tags.append(tag.duplicate()) if current_tag_id == Global.current_project.animation_tags.size(): var new_tag := AnimationTag.new(tag_name, tag_color, tag_from, tag_to)