diff --git a/src/UI/Nodes/CollapsibleContainer.gd b/src/UI/Nodes/CollapsibleContainer.gd index b1d8dabdd..9c9cfbe1f 100644 --- a/src/UI/Nodes/CollapsibleContainer.gd +++ b/src/UI/Nodes/CollapsibleContainer.gd @@ -68,6 +68,11 @@ func set_visible_children(pressed: bool) -> void: child.visible = pressed +## Returns [member _button]. +func get_button() -> Button: + return _button + + ## Checks if a child becomes visible from another sure and ensures ## it remains invisible if the button is not pressed func _child_visibility_changed(child: CanvasItem) -> void: diff --git a/src/UI/Timeline/LayerEffects/LayerEffectButton.gd b/src/UI/Timeline/LayerEffects/LayerEffectButton.gd new file mode 100644 index 000000000..6d159f045 --- /dev/null +++ b/src/UI/Timeline/LayerEffects/LayerEffectButton.gd @@ -0,0 +1,64 @@ +extends Button + +var layer_effects_settings: AcceptDialog +var layer: BaseLayer + +@onready var panel := get_parent().get_parent() + + +func _get_drag_data(_position: Vector2) -> Variant: + return ["LayerEffect", panel.get_index()] + + +func _can_drop_data(_pos: Vector2, data) -> bool: + if typeof(data) != TYPE_ARRAY: + layer_effects_settings.drag_highlight.visible = false + return false + if data[0] != "LayerEffect": + layer_effects_settings.drag_highlight.visible = false + return false + var drop_index: int = data[1] + if panel.get_index() == drop_index: + layer_effects_settings.drag_highlight.visible = false + return false + var region: Rect2 + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Top region + region = _get_region_rect(-0.1, 0.15) + else: # Bottom region + region = _get_region_rect(0.85, 1.1) + layer_effects_settings.drag_highlight.visible = true + layer_effects_settings.drag_highlight.set_deferred(&"global_position", region.position) + layer_effects_settings.drag_highlight.set_deferred(&"size", region.size) + return true + + +func _drop_data(_pos: Vector2, data) -> void: + var drop_index: int = data[1] + var to_index: int # the index where the LOWEST moved layer effect should end up + if _get_region_rect(0, 0.5).has_point(get_global_mouse_position()): # Top region + to_index = panel.get_index() + else: # Bottom region + to_index = panel.get_index() + 1 + if drop_index < panel.get_index(): + to_index -= 1 + Global.current_project.undos += 1 + Global.current_project.undo_redo.create_action("Re-arrange layer effect") + Global.current_project.undo_redo.add_do_method( + layer_effects_settings.move_effect.bind(layer, drop_index, to_index) + ) + Global.current_project.undo_redo.add_do_method(Global.canvas.queue_redraw) + Global.current_project.undo_redo.add_do_method(Global.undo_or_redo.bind(false)) + Global.current_project.undo_redo.add_undo_method( + layer_effects_settings.move_effect.bind(layer, to_index, drop_index) + ) + Global.current_project.undo_redo.add_undo_method(Global.canvas.queue_redraw) + Global.current_project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true)) + Global.current_project.undo_redo.commit_action() + panel.get_parent().move_child(panel.get_parent().get_child(drop_index), to_index) + + +func _get_region_rect(y_begin: float, y_end: float) -> Rect2: + var rect := get_global_rect() + rect.position.y += rect.size.y * y_begin + rect.size.y *= y_end - y_begin + return rect diff --git a/src/UI/Timeline/LayerEffects/LayerEffectsSettings.gd b/src/UI/Timeline/LayerEffects/LayerEffectsSettings.gd index eed168ec8..8690d8f13 100644 --- a/src/UI/Timeline/LayerEffects/LayerEffectsSettings.gd +++ b/src/UI/Timeline/LayerEffects/LayerEffectsSettings.gd @@ -1,8 +1,7 @@ extends AcceptDialog +const LAYER_EFFECT_BUTTON = preload("res://src/UI/Timeline/LayerEffects/LayerEffectButton.gd") const DELETE_TEXTURE := preload("res://assets/graphics/misc/close.svg") -const MOVE_UP_TEXTURE := preload("res://assets/graphics/misc/move_up_arrow.svg") -const MOVE_DOWN_TEXTURE := preload("res://assets/graphics/misc/move_down_arrow.svg") var effects: Array[LayerEffect] = [ LayerEffect.new("Offset", preload("res://src/Shaders/Effects/OffsetPixels.gdshader")), @@ -22,6 +21,7 @@ var effects: Array[LayerEffect] = [ @onready var enabled_button: CheckButton = $VBoxContainer/HBoxContainer/EnabledButton @onready var effect_list: MenuButton = $VBoxContainer/HBoxContainer/EffectList @onready var effect_container: VBoxContainer = $VBoxContainer/ScrollContainer/EffectContainer +@onready var drag_highlight: ColorRect = $DragHighlight func _ready() -> void: @@ -30,6 +30,11 @@ func _ready() -> void: effect_list.get_popup().id_pressed.connect(_on_effect_list_id_pressed) +func _notification(what: int) -> void: + if what == NOTIFICATION_DRAG_END: + drag_highlight.hide() + + func _on_about_to_popup() -> void: var layer := Global.current_project.layers[Global.current_project.current_layer] enabled_button.button_pressed = layer.effects_enabled @@ -61,7 +66,6 @@ func _on_effect_list_id_pressed(index: int) -> void: func _create_effect_ui(layer: BaseLayer, effect: LayerEffect) -> void: var panel_container := PanelContainer.new() - var vbox := VBoxContainer.new() var hbox := HBoxContainer.new() var enable_checkbox := CheckButton.new() enable_checkbox.button_pressed = effect.enabled @@ -70,21 +74,10 @@ func _create_effect_ui(layer: BaseLayer, effect: LayerEffect) -> void: var label := Label.new() label.text = effect.name label.size_flags_horizontal = Control.SIZE_EXPAND_FILL - var move_up_button := TextureButton.new() - move_up_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND - move_up_button.texture_normal = MOVE_UP_TEXTURE - move_up_button.add_to_group(&"UIButtons") - move_up_button.modulate = Global.modulate_icon_color - move_up_button.pressed.connect(_re_order_effect.bind(effect, layer, panel_container, -1)) - var move_down_button := TextureButton.new() - move_down_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND - move_down_button.texture_normal = MOVE_DOWN_TEXTURE - move_down_button.add_to_group(&"UIButtons") - move_down_button.modulate = Global.modulate_icon_color - move_down_button.pressed.connect(_re_order_effect.bind(effect, layer, panel_container, 1)) var delete_button := TextureButton.new() delete_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND delete_button.texture_normal = DELETE_TEXTURE + delete_button.size_flags_vertical = Control.SIZE_SHRINK_CENTER delete_button.add_to_group(&"UIButtons") delete_button.modulate = Global.modulate_icon_color delete_button.pressed.connect(_delete_effect.bind(effect)) @@ -93,13 +86,11 @@ func _create_effect_ui(layer: BaseLayer, effect: LayerEffect) -> void: if layer is PixelLayer: var apply_button := Button.new() apply_button.text = "Apply" + apply_button.size_flags_vertical = Control.SIZE_SHRINK_CENTER apply_button.pressed.connect(_apply_effect.bind(layer, effect)) hbox.add_child(apply_button) - hbox.add_child(move_up_button) - hbox.add_child(move_down_button) hbox.add_child(delete_button) var parameter_vbox := CollapsibleContainer.new() - parameter_vbox.text = "Options" Global.create_ui_for_shader_uniforms( effect.shader, effect.params, @@ -107,11 +98,19 @@ func _create_effect_ui(layer: BaseLayer, effect: LayerEffect) -> void: _set_parameter.bind(effect), _load_parameter_texture.bind(effect) ) - vbox.add_child(hbox) - vbox.add_child(parameter_vbox) - panel_container.add_child(vbox) + var collapsible_button := parameter_vbox.get_button() + collapsible_button.set_script(LAYER_EFFECT_BUTTON) + collapsible_button.layer = layer + collapsible_button.layer_effects_settings = self + collapsible_button.add_child(hbox) + hbox.anchor_left = 0.05 + hbox.anchor_top = 0 + hbox.anchor_right = 0.99 + hbox.anchor_bottom = 1 + panel_container.add_child(parameter_vbox) effect_container.add_child(panel_container) parameter_vbox.set_visible_children(false) + collapsible_button.custom_minimum_size.y = collapsible_button.size.y + 4 func _enable_effect(button_pressed: bool, effect: LayerEffect) -> void: @@ -119,36 +118,10 @@ func _enable_effect(button_pressed: bool, effect: LayerEffect) -> void: Global.canvas.queue_redraw() -func _re_order_effect( - effect: LayerEffect, layer: BaseLayer, container: Container, direction: int -) -> void: - assert(layer.effects.size() == effect_container.get_child_count()) - var effect_index := container.get_index() - var new_index := effect_index + direction - if new_index < 0: - return - if new_index >= effect_container.get_child_count(): - return - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action("Re-arrange layer effect") - Global.current_project.undo_redo.add_do_method( - swap_array.bind(layer.effects, effect_index, new_index, effect) - ) - Global.current_project.undo_redo.add_do_method(Global.canvas.queue_redraw) - Global.current_project.undo_redo.add_do_method(Global.undo_or_redo.bind(false)) - Global.current_project.undo_redo.add_undo_method( - swap_array.bind(layer.effects, new_index, effect_index, effect) - ) - Global.current_project.undo_redo.add_undo_method(Global.canvas.queue_redraw) - Global.current_project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true)) - Global.current_project.undo_redo.commit_action() - effect_container.move_child(container, new_index) - - -func swap_array(array: Array, old_index: int, new_index: int, new_item: Variant) -> void: - var temp = array[new_index] - array[new_index] = new_item - array[old_index] = temp +func move_effect(layer: BaseLayer, from_index: int, to_index: int) -> void: + var layer_effect := layer.effects[from_index] + layer.effects.remove_at(from_index) + layer.effects.insert(to_index, layer_effect) func _delete_effect(effect: LayerEffect) -> void: diff --git a/src/UI/Timeline/LayerEffects/LayerEffectsSettings.tscn b/src/UI/Timeline/LayerEffects/LayerEffectsSettings.tscn index 9dcf291d8..6d0f1432f 100644 --- a/src/UI/Timeline/LayerEffects/LayerEffectsSettings.tscn +++ b/src/UI/Timeline/LayerEffects/LayerEffectsSettings.tscn @@ -6,6 +6,7 @@ title = "Layer effects" size = Vector2i(400, 400) exclusive = false +popup_window = true script = ExtResource("1_h6h7b") [node name="VBoxContainer" type="VBoxContainer" parent="."] @@ -38,6 +39,11 @@ layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 +[node name="DragHighlight" type="ColorRect" parent="."] +visible = false +mouse_filter = 2 +color = Color(0, 0.741176, 1, 0.501961) + [connection signal="about_to_popup" from="." to="." method="_on_about_to_popup"] [connection signal="visibility_changed" from="." to="." method="_on_visibility_changed"] [connection signal="toggled" from="VBoxContainer/HBoxContainer/EnabledButton" to="." method="_on_enabled_button_toggled"]