extends Container class_name TopicDraggable onready var topic_feed: VBoxContainer = get_node("..") onready var scroll_container: ScrollContainer = get_node("../..") onready var v_scroll: VScrollBar = get_node("../../_v_scroll") onready var editable = get_node("TopicEditable") onready var tween = get_node("Tween") var global_position setget _set_global_position var _in_fit_in_animation = false var _previous_position var _offset func _ready(): pass func _input(event): if event is InputEventMouseButton and event.button_index == BUTTON_LEFT: if event.is_pressed(): if _is_mouse_on_control(): if event.shift: topic_feed._toggle_selection_result = _set_selection(null) topic_feed._shift_hold = true else: _deselect_all() if not editable.edit_mode: if event.doubleclick: editable._enable_edit_mode() editable.text_edit.grab_focus() editable.text_edit.select_all() elif !_in_fit_in_animation: _set_as_grabbed() elif editable.edit_mode: editable.text_edit._confirm() else: _fit_in_animation() topic_feed._shift_hold = false if event is InputEventMouseMotion: if topic_feed.currently_grabbed_topic == self: _move_block(event) topic_feed.check_all_passings() if topic_feed._shift_hold and _is_mouse_on_control(): # warning-ignore:return_value_discarded _set_selection(topic_feed._toggle_selection_result) func _set_selection(to) -> bool: # If 'to' is null, selection is toggled. if topic_feed.selected_topics.has(self) and to != true: topic_feed.selected_topics.erase(self) editable._update_color() return false elif !topic_feed.selected_topics.has(self) and to != false: topic_feed.selected_topics.append(self) editable._update_color() return true else: return topic_feed.selected_topics.has(self) func _deselect_all(): topic_feed.selected_topics.clear() topic_feed.update_all_colors() func _set_as_grabbed(): var rect = editable.get_global_rect() rect_min_size.y = editable.rect_size.y editable.set_as_toplevel(true) editable.rect_position = rect.position topic_feed.currently_grabbed_topic = self _previous_position = editable.rect_global_position _offset = 0 func _fit_in_animation(): _in_fit_in_animation = true topic_feed.currently_grabbed_topic = null tween.stop_all() tween.interpolate_property(self, "global_position", editable.rect_global_position, rect_global_position, 0.12, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT ) tween.start() yield(tween, "tween_completed") editable.set_as_toplevel(false) rect_min_size.y = 0 editable.rect_position = Vector2.ZERO _in_fit_in_animation = false func _move_block(event): _offset += event.relative.y editable.set_global_position(_previous_position + Vector2(0.0, _offset)) func _is_mouse_on_control() -> bool: return get_global_rect().has_point(get_viewport().get_mouse_position()) func set_previous_position(): _previous_position = editable.rect_global_position func check_for_passing() -> bool: var dragged: TopicDraggable = topic_feed.currently_grabbed_topic if dragged == self or dragged == null: return false var dir = sign(dragged.get_index() - get_index()) var self_rect = get_global_rect() var self_half_size = self_rect.size.y * 0.5 # Center line. var self_coll_line = self_rect.position.y + self_half_size var dragged_rect = dragged.editable.get_global_rect() var dragged_half_size = dragged_rect.size.y * 0.5 var dragged_half_pos = dragged_rect.position.y + dragged_half_size # Top or bottom line, depending on if moved up or down. var dragged_coll_line = dragged_half_pos + dragged_half_size * -dir # +1 if dragged_coll_line is below; -1 if above. var coll_dir = sign(self_coll_line - dragged_coll_line) if coll_dir == dir: topic_feed.set_all_previous_positions() topic_feed.move_child( topic_feed.currently_grabbed_topic, get_index() ) return true return false func setup_tween(): if _previous_position != editable.rect_global_position: tween.stop_all() tween.interpolate_property(self, "global_position", _previous_position, rect_global_position, 0.15, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT ) tween.start() func _set_global_position(value): editable.set_global_position(value)