From 3c85281610fc76346401a83adbd27c9afbe1801c Mon Sep 17 00:00:00 2001 From: dugramen Date: Mon, 10 Mar 2025 18:10:08 -0400 Subject: [PATCH] Scroll inspector while drag hovering near the edge --- editor/editor_inspector.cpp | 10 ++++++++ editor/editor_inspector.h | 1 + scene/gui/scroll_container.cpp | 45 ++++++++++++++++++++++++++++++++++ scene/gui/scroll_container.h | 5 ++++ 4 files changed, 61 insertions(+) diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 4990a415d6d..d18cf896e62 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1938,6 +1938,12 @@ void EditorInspectorSection::set_bg_color(const Color &p_bg_color) { queue_redraw(); } +void EditorInspectorSection::reset_timer() { + if (dropping_for_unfold && !dropping_unfold_timer->is_stopped()) { + dropping_unfold_timer->start(); + } +} + bool EditorInspectorSection::has_revertable_properties() const { return !revertable_properties.is_empty(); } @@ -3478,6 +3484,7 @@ void EditorInspector::update_tree() { if (!vbox_per_path[root_vbox].has(acc_path)) { // If the section does not exists, create it. EditorInspectorSection *section = memnew(EditorInspectorSection); + get_root_inspector()->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(section, &EditorInspectorSection::reset_timer).unbind(1)); current_vbox->add_child(section); sections.push_back(section); @@ -3878,6 +3885,7 @@ void EditorInspector::update_tree() { } EditorInspectorSection *section = memnew(EditorInspectorSection); + get_root_inspector()->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(section, &EditorInspectorSection::reset_timer).unbind(1)); favorites_groups_vbox->add_child(section); parent_vbox = section->get_vbox(); section->setup("", section_name, object, sscolor, false); @@ -3897,6 +3905,7 @@ void EditorInspector::update_tree() { } EditorInspectorSection *section = memnew(EditorInspectorSection); + get_root_inspector()->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(section, &EditorInspectorSection::reset_timer).unbind(1)); vbox->add_child(section); vbox = section->get_vbox(); section->setup("", section_name, object, sscolor, false); @@ -5001,4 +5010,5 @@ EditorInspector::EditorInspector() { set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style()); set_draw_focus_border(true); + set_scroll_on_drag_hover(true); } diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index ac7c3d03e76..a3974c1132a 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -357,6 +357,7 @@ public: void unfold(); void fold(); void set_bg_color(const Color &p_bg_color); + void reset_timer(); bool has_revertable_properties() const; void property_can_revert_changed(const String &p_path, bool p_can_revert); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index fdb134c5d0e..ca7b730e124 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -361,6 +361,10 @@ void ScrollContainer::_notification(int p_what) { case NOTIFICATION_TRANSLATION_CHANGED: { _updating_scrollbars = true; callable_mp(this, is_ready() ? &ScrollContainer::_reposition_children : &ScrollContainer::_update_scrollbar_position).call_deferred(); + if (p_what == NOTIFICATION_THEME_CHANGED) { + scroll_border = get_theme_constant(SNAME("scroll_border"), SNAME("Tree")); + scroll_speed = get_theme_constant(SNAME("scroll_speed"), SNAME("Tree")); + } } break; case NOTIFICATION_READY: { @@ -387,6 +391,43 @@ void ScrollContainer::_notification(int p_what) { } } break; + case NOTIFICATION_DRAG_BEGIN: { + if (scroll_on_drag_hover && is_visible_in_tree()) { + set_process_internal(true); + } + } break; + + case NOTIFICATION_DRAG_END: { + set_process_internal(false); + } break; + + case NOTIFICATION_INTERNAL_PROCESS: { + if (scroll_on_drag_hover && get_viewport()->gui_is_dragging()) { + Point2 mouse_position = get_viewport()->get_mouse_position() - get_global_position(); + Transform2D xform = get_transform(); + if (Rect2(Point2(), xform.get_scale() * get_size()).grow(scroll_border).has_point(mouse_position)) { + Point2 point; + + if ((Math::abs(mouse_position.x) < Math::abs(mouse_position.x - get_size().width)) && (Math::abs(mouse_position.x) < scroll_border)) { + point.x = mouse_position.x - scroll_border; + } else if (Math::abs(mouse_position.x - get_size().width) < scroll_border) { + point.x = mouse_position.x - (get_size().width - scroll_border); + } + + if ((Math::abs(mouse_position.y) < Math::abs(mouse_position.y - get_size().height)) && (Math::abs(mouse_position.y) < scroll_border)) { + point.y = mouse_position.y - scroll_border; + } else if (Math::abs(mouse_position.y - get_size().height) < scroll_border) { + point.y = mouse_position.y - (get_size().height - scroll_border); + } + + point *= scroll_speed * get_process_delta_time(); + point += Point2(get_h_scroll(), get_v_scroll()); + h_scroll->set_value(point.x); + v_scroll->set_value(point.y); + } + } + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (drag_touching) { if (drag_touching_deaccel) { @@ -584,6 +625,10 @@ PackedStringArray ScrollContainer::get_configuration_warnings() const { return warnings; } +void ScrollContainer::set_scroll_on_drag_hover(bool p_scroll) { + scroll_on_drag_hover = p_scroll; +} + HScrollBar *ScrollContainer::get_h_scroll_bar() { return h_scroll; } diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 887a8e3f1c3..7309c9ea613 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -62,12 +62,15 @@ private: bool drag_touching = false; bool drag_touching_deaccel = false; bool beyond_deadzone = false; + bool scroll_on_drag_hover = false; ScrollMode horizontal_scroll_mode = SCROLL_MODE_AUTO; ScrollMode vertical_scroll_mode = SCROLL_MODE_AUTO; int deadzone = 0; bool follow_focus = false; + int scroll_border = 20; + int scroll_speed = 12; struct ThemeCache { Ref panel_style; @@ -123,6 +126,8 @@ public: bool is_following_focus() const; void set_follow_focus(bool p_follow); + void set_scroll_on_drag_hover(bool p_scroll); + HScrollBar *get_h_scroll_bar(); VScrollBar *get_v_scroll_bar(); void ensure_control_visible(Control *p_control);