diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index de1af96a370..a400224afeb 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -824,6 +824,9 @@ Tab style of editor docks. + + During a drag-and-drop, this is how long to wait over a section before the section unfolds to show nested items. + The language to use for the editor interface. Translations are provided by the community. If you spot a mistake, [url=$DOCS_URL/contributing/documentation/editor_and_docs_localization.html]contribute to editor translations on Weblate![/url] diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index 9fad1ca9a85..cb26afe2a5b 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -355,6 +355,9 @@ The drop mode as an OR combination of flags. See [enum DropModeFlags] constants. Once dropping is done, reverts to [constant DROP_MODE_DISABLED]. Setting this during [method Control._can_drop_data] is recommended. This controls the drop sections, i.e. the decision and drawing of possible drop locations based on the mouse position. + + If [code]true[/code], tree items will unfold when hovered over during a drag-and-drop. + If [code]true[/code], recursive folding is enabled for this [Tree]. Holding down [kbd]Shift[/kbd] while clicking the fold arrow or using [code]ui_right[/code]/[code]ui_left[/code] shortcuts collapses or uncollapses the [TreeItem] and all its descendants. @@ -542,6 +545,9 @@ The width of the relationship lines between the selected [TreeItem] and its children. + + During a drag-and-drop, this is how many milliseconds to wait over a section before the section unfolds. + Draws the guidelines if not zero, this acts as a boolean. The guideline is a horizontal line drawn at the bottom of each item. diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 58b02ed2b8a..a5d3134366e 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1801,6 +1801,12 @@ void EditorInspectorSection::_notification(int p_what) { } queue_redraw(); } break; + + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor")) { + dropping_unfold_timer->set_wait_time(EDITOR_GET("interface/editor/dragging_unfold_wait_seconds")); + } + } } } @@ -1953,7 +1959,7 @@ EditorInspectorSection::EditorInspectorSection() { vbox = memnew(VBoxContainer); dropping_unfold_timer = memnew(Timer); - dropping_unfold_timer->set_wait_time(0.6); + dropping_unfold_timer->set_wait_time(EDITOR_GET("interface/editor/dragging_unfold_wait_seconds")); dropping_unfold_timer->set_one_shot(true); add_child(dropping_unfold_timer); dropping_unfold_timer->connect("timeout", callable_mp(this, &EditorInspectorSection::unfold)); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 6b725240f9e..984c1098dc9 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -821,6 +821,10 @@ void EditorNode::_notification(int p_what) { recent_scenes->reset_size(); } + if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor")) { + theme->set_constant("dragging_unfold_wait_msec", "Tree", (float)EDITOR_GET("interface/editor/dragging_unfold_wait_seconds") * 1000); + } + if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/dock_tab_style")) { editor_dock_manager->update_tab_styles(); } diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index a246249cfe3..e7ebc9d59cc 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -467,6 +467,9 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font", "", "*.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm") EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/main_font_bold", "", "*.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm") EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/editor/code_font", "", "*.ttf,*.otf,*.woff,*.woff2,*.pfb,*.pfm") + + EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/dragging_unfold_wait_seconds", 0.5, "0.01,10,0.01,or_greater,suffix:s"); + _initial_set("interface/editor/separate_distraction_mode", false, true); _initial_set("interface/editor/automatically_open_screenshots", true, true); EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/single_window_mode", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED | PROPERTY_USAGE_EDITOR_BASIC_SETTING) diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp index 1793418c2a2..cfb7f0d37ba 100644 --- a/editor/themes/editor_theme_manager.cpp +++ b/editor/themes/editor_theme_manager.cpp @@ -972,6 +972,7 @@ void EditorThemeManager::_populate_standard_styles(const Ref &p_the p_theme->set_constant("inner_item_margin_left", "Tree", p_config.increased_margin * EDSCALE); p_theme->set_constant("inner_item_margin_right", "Tree", p_config.increased_margin * EDSCALE); p_theme->set_constant("button_margin", "Tree", p_config.base_margin * EDSCALE); + p_theme->set_constant("dragging_unfold_wait_msec", "Tree", (float)EDITOR_GET("interface/editor/dragging_unfold_wait_seconds") * 1000); p_theme->set_constant("scroll_border", "Tree", 40 * EDSCALE); p_theme->set_constant("scroll_speed", "Tree", 12); p_theme->set_constant("outline_size", "Tree", 0); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index cd6c51de4b2..11d9e443234 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -133,7 +133,7 @@ void TreeItem::_change_tree(Tree *p_tree) { } if (tree->drop_mode_over == this) { - tree->drop_mode_over = nullptr; + tree->_reset_drop_mode_over(); } if (tree->single_select_defer == this) { @@ -4011,6 +4011,11 @@ void Tree::_determine_hovered_item() { if (drop_mode_flags) { if (it != drop_mode_over) { drop_mode_over = it; + if (enable_drag_unfolding) { + dropping_unfold_timer->start(theme_cache.dragging_unfold_wait_msec * 0.001); + } else if (!dropping_unfold_timer->is_stopped()) { + dropping_unfold_timer->stop(); + } queue_redraw(); } if (it && section != drop_mode_section) { @@ -4055,6 +4060,19 @@ void Tree::_determine_hovered_item() { } } +void Tree::_on_dropping_unfold_timer_timeout() { + if (enable_drag_unfolding && drop_mode_over && drop_mode_section == 0) { + drop_mode_over->set_collapsed(false); + } +} + +void Tree::_reset_drop_mode_over() { + drop_mode_over = nullptr; + if (!dropping_unfold_timer->is_stopped()) { + dropping_unfold_timer->stop(); + } +} + bool Tree::edit_selected(bool p_force_edit) { TreeItem *s = get_selected(); ERR_FAIL_NULL_V_MSG(s, false, "No item selected."); @@ -5723,13 +5741,24 @@ bool Tree::is_recursive_folding_enabled() const { return enable_recursive_folding; } +void Tree::set_enable_drag_unfolding(bool p_enable) { + enable_drag_unfolding = p_enable; + if (!dropping_unfold_timer->is_stopped()) { + dropping_unfold_timer->stop(); + } +} + +bool Tree::is_drag_unfolding_enabled() const { + return enable_drag_unfolding; +} + void Tree::set_drop_mode_flags(int p_flags) { if (drop_mode_flags == p_flags) { return; } drop_mode_flags = p_flags; if (drop_mode_flags == 0) { - drop_mode_over = nullptr; + _reset_drop_mode_over(); } queue_redraw(); @@ -5850,6 +5879,9 @@ void Tree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enable_recursive_folding", "enable"), &Tree::set_enable_recursive_folding); ClassDB::bind_method(D_METHOD("is_recursive_folding_enabled"), &Tree::is_recursive_folding_enabled); + ClassDB::bind_method(D_METHOD("set_enable_drag_unfolding", "enable"), &Tree::set_enable_drag_unfolding); + ClassDB::bind_method(D_METHOD("is_drag_unfolding_enabled"), &Tree::is_drag_unfolding_enabled); + ClassDB::bind_method(D_METHOD("set_drop_mode_flags", "flags"), &Tree::set_drop_mode_flags); ClassDB::bind_method(D_METHOD("get_drop_mode_flags"), &Tree::get_drop_mode_flags); @@ -5872,6 +5904,7 @@ void Tree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_folding"), "set_hide_folding", "is_folding_hidden"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_recursive_folding"), "set_enable_recursive_folding", "is_recursive_folding_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_drag_unfolding"), "set_enable_drag_unfolding", "is_drag_unfolding_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_root"), "set_hide_root", "is_root_hidden"); ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In Between"), "set_drop_mode_flags", "get_drop_mode_flags"); ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Row,Multi"), "set_select_mode", "get_select_mode"); @@ -5967,6 +6000,8 @@ void Tree::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, parent_hl_line_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Tree, children_hl_line_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, dragging_unfold_wait_msec); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scroll_border); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Tree, scroll_speed); @@ -6025,6 +6060,11 @@ Tree::Tree() { range_click_timer->connect("timeout", callable_mp(this, &Tree::_range_click_timeout)); add_child(range_click_timer, false, INTERNAL_MODE_FRONT); + dropping_unfold_timer = memnew(Timer); + dropping_unfold_timer->set_one_shot(true); + dropping_unfold_timer->connect("timeout", callable_mp(this, &Tree::_on_dropping_unfold_timer_timeout)); + add_child(dropping_unfold_timer); + h_scroll->connect(SceneStringName(value_changed), callable_mp(this, &Tree::_scroll_moved)); v_scroll->connect(SceneStringName(value_changed), callable_mp(this, &Tree::_scroll_moved)); line_editor->connect(SceneStringName(text_submitted), callable_mp(this, &Tree::_line_editor_submit)); diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 9d3324bd3db..3ecda6dcfeb 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -612,6 +612,8 @@ private: int parent_hl_line_margin = 0; int draw_guides = 0; + int dragging_unfold_wait_msec = 500; + int scroll_border = 0; int scroll_speed = 0; @@ -709,6 +711,11 @@ private: bool enable_recursive_folding = true; + bool enable_drag_unfolding = true; + Timer *dropping_unfold_timer = nullptr; + void _on_dropping_unfold_timer_timeout(); + void _reset_drop_mode_over(); + bool enable_auto_tooltip = true; void _determine_hovered_item(); @@ -828,6 +835,9 @@ public: void set_enable_recursive_folding(bool p_enable); bool is_recursive_folding_enabled() const; + void set_enable_drag_unfolding(bool p_enable); + bool is_drag_unfolding_enabled() const; + void set_drop_mode_flags(int p_flags); int get_drop_mode_flags() const; diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp index 5ae1e9baa37..c72c33afb9f 100644 --- a/scene/theme/default_theme.cpp +++ b/scene/theme/default_theme.cpp @@ -904,6 +904,7 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const theme->set_constant("children_hl_line_width", "Tree", 1); theme->set_constant("parent_hl_line_margin", "Tree", 0); theme->set_constant("draw_guides", "Tree", 1); + theme->set_constant("dragging_unfold_wait_msec", "Tree", 500); theme->set_constant("scroll_border", "Tree", Math::round(4 * scale)); theme->set_constant("scroll_speed", "Tree", 12); theme->set_constant("outline_size", "Tree", 0);