diff --git a/doc/classes/EditorDock.xml b/doc/classes/EditorDock.xml index e8926c96fd3..d0ab092fc8d 100644 --- a/doc/classes/EditorDock.xml +++ b/doc/classes/EditorDock.xml @@ -85,7 +85,6 @@ The available layouts for this dock, as a bitmask. By default, the dock allows vertical and floating layouts. - If [code]true[/code], the dock can be closed with the Close button in the context popup. Docks with [member global] enabled are always closable. diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index b6b3f8f324b..47f715ba48b 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -421,12 +421,18 @@ Whether all columns will have the same width. If [code]true[/code], the width is equal to the largest column width of all columns. + + The way which scroll hints (indicators that show that the content can still be scrolled in a certain direction) will be shown. + Allows single or multiple item selection. See the [enum SelectMode] constants. The clipping behavior when the text exceeds an item's bounding rectangle. + + If [code]true[/code], the scroll hint texture will be tiled instead of stretched. See [member scroll_hint_mode]. + If [code]true[/code], the control will automatically move items into a new row to fit its content. See also [HFlowContainer] for this behavior. If [code]false[/code], the control will add a horizontal scrollbar to make all items visible. @@ -487,6 +493,18 @@ Allows selecting multiple items by toggling them on and off. + + Scroll hints will never be shown. + + + Scroll hints will be shown at the top and bottom. + + + Only the top scroll hint will be shown. + + + Only the bottom scroll hint will be shown. + @@ -529,6 +547,9 @@ Font size of the item's text. + + The indicator that will be shown when the content can still be scrolled. See [member scroll_hint_mode]. + [StyleBox] used for the cursor, when the [ItemList] is being focused. diff --git a/editor/animation/animation_track_editor.cpp b/editor/animation/animation_track_editor.cpp index 44ded4d0f1c..b70e47befb1 100644 --- a/editor/animation/animation_track_editor.cpp +++ b/editor/animation/animation_track_editor.cpp @@ -7879,6 +7879,16 @@ float AnimationTrackEditor::get_snap_unit() { return snap_unit; } +void AnimationTrackEditor::_update_timeline_rtl_spacer() { + if (scroll->get_v_scroll_bar()->is_visible() && is_layout_rtl()) { + int spacer_width = scroll->get_v_scroll_bar()->get_minimum_size().width; + timeline_rtl_spacer->set_custom_minimum_size(Size2(spacer_width, 0)); + timeline_rtl_spacer->show(); + } else { + timeline_rtl_spacer->hide(); + } +} + void AnimationTrackEditor::_add_animation_player() { EditorData &editor_data = EditorNode::get_editor_data(); Node *scene = editor_data.get_edited_scene_root(); @@ -8016,10 +8026,14 @@ void AnimationTrackEditor::popup_read_only_dialog() { } AnimationTrackEditor::AnimationTrackEditor() { + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderAnimation"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(mc); + main_panel = memnew(PanelContainer); main_panel->set_focus_mode(FOCUS_ALL); // Allow panel to have focus so that shortcuts work as expected. - add_child(main_panel); - main_panel->set_v_size_flags(SIZE_EXPAND_FILL); + mc->add_child(main_panel); HBoxContainer *timeline_scroll = memnew(HBoxContainer); main_panel->add_child(timeline_scroll); timeline_scroll->set_v_size_flags(SIZE_EXPAND_FILL); @@ -8052,8 +8066,13 @@ AnimationTrackEditor::AnimationTrackEditor() { add_animation_player->set_h_size_flags(SIZE_SHRINK_CENTER); add_animation_player->connect(SceneStringName(pressed), callable_mp(this, &AnimationTrackEditor::_add_animation_player)); + HBoxContainer *hbox = memnew(HBoxContainer); + hbox->add_theme_constant_override(SNAME("separation"), 0); + timeline_vbox->add_child(hbox); + timeline = memnew(AnimationTimelineEdit); - timeline_vbox->add_child(timeline); + timeline->set_h_size_flags(SIZE_EXPAND_FILL); + hbox->add_child(timeline); timeline->set_editor(this); timeline->connect("timeline_changed", callable_mp(this, &AnimationTrackEditor::_timeline_changed)); timeline->connect("name_limit_changed", callable_mp(this, &AnimationTrackEditor::_name_limit_changed)); @@ -8062,6 +8081,11 @@ AnimationTrackEditor::AnimationTrackEditor() { timeline->connect("length_changed", callable_mp(this, &AnimationTrackEditor::_update_length)); timeline->connect("filter_changed", callable_mp(this, &AnimationTrackEditor::_update_tracks)); + // If the animation editor is changed to take right-to-left into account, this won't be needed anymore. + timeline_rtl_spacer = memnew(Control); + timeline_rtl_spacer->hide(); + hbox->add_child(timeline_rtl_spacer); + panner.instantiate(); panner->set_scroll_zoom_factor(AnimationTimelineEdit::SCROLL_ZOOM_FACTOR_IN); panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback)); @@ -8090,16 +8114,17 @@ AnimationTrackEditor::AnimationTrackEditor() { marker_edit->connect(SceneStringName(draw), callable_mp((CanvasItem *)bezier_edit, &CanvasItem::queue_redraw)); scroll = memnew(ScrollContainer); + scroll->set_scroll_hint_mode(ScrollContainer::SCROLL_HINT_MODE_ALL); box_selection_container->add_child(scroll); scroll->set_anchors_and_offsets_preset(PRESET_FULL_RECT); - VScrollBar *sb = scroll->get_v_scroll_bar(); - scroll->remove_child(sb); - timeline_scroll->add_child(sb); // Move here so timeline and tracks are always aligned. scroll->set_focus_mode(FOCUS_CLICK); scroll->connect(SceneStringName(gui_input), callable_mp(this, &AnimationTrackEditor::_scroll_input)); scroll->connect(SceneStringName(focus_exited), callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); + // Must be updated from here, so it guarantees that the scrollbar theme has already changed. + scroll->connect(SceneStringName(theme_changed), callable_mp(this, &AnimationTrackEditor::_update_timeline_rtl_spacer), CONNECT_DEFERRED); + scroll->get_v_scroll_bar()->connect(SceneStringName(visibility_changed), callable_mp(this, &AnimationTrackEditor::_update_timeline_rtl_spacer)); scroll->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(this, &AnimationTrackEditor::_v_scroll_changed)); scroll->get_h_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(this, &AnimationTrackEditor::_h_scroll_changed)); diff --git a/editor/animation/animation_track_editor.h b/editor/animation/animation_track_editor.h index 2dd16b0383f..9af1cdb69fd 100644 --- a/editor/animation/animation_track_editor.h +++ b/editor/animation/animation_track_editor.h @@ -617,6 +617,9 @@ class AnimationTrackEditor : public VBoxContainer { AnimationBezierTrackEdit *bezier_edit = nullptr; VBoxContainer *timeline_vbox = nullptr; + Control *timeline_rtl_spacer = nullptr; + void _update_timeline_rtl_spacer(); + VBoxContainer *info_message_vbox = nullptr; Label *info_message = nullptr; Button *add_animation_player = nullptr; diff --git a/editor/audio/editor_audio_buses.cpp b/editor/audio/editor_audio_buses.cpp index 68a1e002eb5..3ab45a32680 100644 --- a/editor/audio/editor_audio_buses.cpp +++ b/editor/audio/editor_audio_buses.cpp @@ -1387,10 +1387,16 @@ EditorAudioBuses::EditorAudioBuses() { top_hb->add_child(_new); _new->connect(SceneStringName(pressed), callable_mp(this, &EditorAudioBuses::_new_layout)); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontal"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + main_vb->add_child(mc); + bus_scroll = memnew(ScrollContainer); - bus_scroll->set_v_size_flags(SIZE_EXPAND_FILL); + bus_scroll->set_scroll_hint_mode(ScrollContainer::SCROLL_HINT_MODE_ALL); bus_scroll->set_custom_minimum_size(Size2(0, 40 * EDSCALE)); - main_vb->add_child(bus_scroll); + mc->add_child(bus_scroll); + bus_hb = memnew(HBoxContainer); bus_hb->set_v_size_flags(SIZE_EXPAND_FILL); bus_scroll->add_child(bus_hb); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index c07331dadba..45fc84ad672 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -70,7 +70,6 @@ EditorDebuggerNode::EditorDebuggerNode() { set_global(false); set_transient(true); - set_clip_contents(false); _update_margins(); if (!singleton) { diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 60c4e7e5e54..7c4fe707c85 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -2352,14 +2352,12 @@ Instead, use the monitors tab to obtain more precise VRAM usage. vmem_refresh->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::_video_mem_request)); vmem_export->connect(SceneStringName(pressed), callable_mp(this, &ScriptEditorDebugger::_video_mem_export)); - VBoxContainer *vmmc = memnew(VBoxContainer); - vmem_tree = memnew(Tree); - vmem_tree->set_v_size_flags(SIZE_EXPAND_FILL); - vmem_tree->set_h_size_flags(SIZE_EXPAND_FILL); - vmmc->add_child(vmem_tree); - vmmc->set_v_size_flags(SIZE_EXPAND_FILL); - vmem_vb->add_child(vmmc); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontalWindow"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + vmem_vb->add_child(mc); + vmem_tree = memnew(Tree); vmem_vb->set_name(TTRC("Video RAM")); vmem_tree->set_columns(4); vmem_tree->set_column_titles_visible(true); @@ -2375,6 +2373,8 @@ Instead, use the monitors tab to obtain more precise VRAM usage. vmem_tree->set_column_title(3, TTRC("Usage")); vmem_tree->set_column_custom_minimum_width(3, 80 * EDSCALE); vmem_tree->set_hide_root(true); + vmem_tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_TOP); + mc->add_child(vmem_tree); vmem_tree->connect("item_activated", callable_mp(this, &ScriptEditorDebugger::_vmem_item_activated)); tabs->add_child(vmem_vb); diff --git a/editor/doc/editor_help_search.cpp b/editor/doc/editor_help_search.cpp index ba792a80ebe..f63c9dc6f3e 100644 --- a/editor/doc/editor_help_search.cpp +++ b/editor/doc/editor_help_search.cpp @@ -38,6 +38,7 @@ #include "editor/themes/editor_scale.h" #include "editor/themes/editor_theme_manager.h" #include "scene/gui/line_edit.h" +#include "scene/gui/margin_container.h" bool EditorHelpSearch::_all_terms_in_name(const Vector &p_terms, const String &p_name) const { for (int i = 0; i < p_terms.size(); i++) { @@ -373,11 +374,15 @@ EditorHelpSearch::EditorHelpSearch() { filter_combo->connect(SceneStringName(item_selected), callable_mp(this, &EditorHelpSearch::_filter_combo_item_selected)); hbox->add_child(filter_combo); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontalWindow"); + mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); + vbox->add_child(mc); + // Create the results tree. results_tree = memnew(Tree); results_tree->set_accessibility_name(TTRC("Search Results")); results_tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); - results_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); results_tree->set_columns(2); results_tree->set_column_title(0, TTR("Name")); results_tree->set_column_clip_content(0, true); @@ -388,9 +393,10 @@ EditorHelpSearch::EditorHelpSearch() { results_tree->set_custom_minimum_size(Size2(0, 100) * EDSCALE); results_tree->set_hide_root(true); results_tree->set_select_mode(Tree::SELECT_ROW); + results_tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTH); results_tree->connect("item_activated", callable_mp(this, &EditorHelpSearch::_confirmed)); results_tree->connect(SceneStringName(item_selected), callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled).bind(false)); - vbox->add_child(results_tree, true); + mc->add_child(results_tree, true); } void EditorHelpSearch::TreeCache::clear() { diff --git a/editor/docks/editor_dock.cpp b/editor/docks/editor_dock.cpp index 149b768c6bf..10326f93b69 100644 --- a/editor/docks/editor_dock.cpp +++ b/editor/docks/editor_dock.cpp @@ -105,7 +105,6 @@ void EditorDock::_bind_methods() { } EditorDock::EditorDock() { - set_clip_contents(true); add_user_signal(MethodInfo("tab_style_changed")); } diff --git a/editor/docks/filesystem_dock.cpp b/editor/docks/filesystem_dock.cpp index f3b9fa88568..f6392ac909b 100644 --- a/editor/docks/filesystem_dock.cpp +++ b/editor/docks/filesystem_dock.cpp @@ -484,10 +484,13 @@ void FileSystemDock::_update_display_mode(bool p_force) { // Compute the new display mode. if (p_force || old_display_mode != display_mode) { switch (display_mode) { - case DISPLAY_MODE_TREE_ONLY: + case DISPLAY_MODE_TREE_ONLY: { button_toggle_display_mode->set_button_icon(get_editor_theme_icon(SNAME("Panels1"))); tree->show(); tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_TOP); + tree->set_theme_type_variation(""); + tree_mc->set_theme_type_variation("NoBorderHorizontalBottom"); if (horizontal) { toolbar2_hbc->hide(); } else { @@ -497,10 +500,10 @@ void FileSystemDock::_update_display_mode(bool p_force) { _update_tree(get_uncollapsed_paths()); file_list_vb->hide(); - break; + } break; case DISPLAY_MODE_HSPLIT: - case DISPLAY_MODE_VSPLIT: + case DISPLAY_MODE_VSPLIT: { const bool is_vertical = display_mode == DISPLAY_MODE_VSPLIT; split_box->set_vertical(is_vertical); @@ -511,15 +514,26 @@ void FileSystemDock::_update_display_mode(bool p_force) { tree->show(); tree->set_v_size_flags(SIZE_EXPAND_FILL); + if (is_vertical) { + tree->set_theme_type_variation(""); + tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTH); + tree_mc->set_theme_type_variation("NoBorderHorizontal"); + } else { + tree->set_theme_type_variation("TreeSecondary"); + tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_DISABLED); + tree_mc->set_theme_type_variation(""); + } tree->ensure_cursor_is_visible(); + toolbar2_hbc->hide(); button_file_list_display_mode->show(); _update_tree(get_uncollapsed_paths()); file_list_vb->show(); _update_file_list(true); - break; + } break; } + old_display_mode = display_mode; } } @@ -4322,18 +4336,22 @@ FileSystemDock::FileSystemDock() { split_box_offset_h = 240 * EDSCALE; main_vb->add_child(split_box); + tree_mc = memnew(MarginContainer); + split_box->add_child(tree_mc); + tree_mc->set_theme_type_variation("NoBorderHorizontalBottom"); + tree_mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); + tree = memnew(FileSystemTree); tree->set_accessibility_name(TTRC("Directories")); - tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); - tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tree->set_hide_root(true); + tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_TOP); SET_DRAG_FORWARDING_GCD(tree, FileSystemDock); tree->set_allow_rmb_select(true); tree->set_select_mode(Tree::SELECT_MULTI); tree->set_custom_minimum_size(Size2(40 * EDSCALE, 15 * EDSCALE)); tree->set_column_clip_content(0, true); - split_box->add_child(tree); + tree_mc->add_child(tree); tree->connect("item_activated", callable_mp(this, &FileSystemDock::_tree_activate_file)); tree->connect("multi_selected", callable_mp(this, &FileSystemDock::_tree_multi_selected)); diff --git a/editor/docks/filesystem_dock.h b/editor/docks/filesystem_dock.h index ad0dcb99bb1..1af4867fe0f 100644 --- a/editor/docks/filesystem_dock.h +++ b/editor/docks/filesystem_dock.h @@ -153,6 +153,7 @@ private: VBoxContainer *scanning_vb = nullptr; ProgressBar *scanning_progress = nullptr; SplitContainer *split_box = nullptr; + MarginContainer *tree_mc = nullptr; VBoxContainer *file_list_vb = nullptr; int split_box_offset_h = 0; diff --git a/editor/docks/groups_dock.cpp b/editor/docks/groups_dock.cpp index d82e5be7cf9..6faf105a11a 100644 --- a/editor/docks/groups_dock.cpp +++ b/editor/docks/groups_dock.cpp @@ -31,7 +31,6 @@ #include "groups_dock.h" #include "editor/settings/editor_command_palette.h" -#include "editor/themes/editor_scale.h" void GroupsDock::set_selection(const Vector &p_nodes) { groups->set_selection(p_nodes); @@ -44,12 +43,9 @@ GroupsDock::GroupsDock() { set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_groups", TTRC("Open Groups Dock"))); set_default_slot(DockConstants::DOCK_SLOT_RIGHT_UL); - VBoxContainer *main_vb = memnew(VBoxContainer); - add_child(main_vb); - groups = memnew(GroupsEditor); - main_vb->add_child(groups); groups->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(groups); } GroupsDock::~GroupsDock() { diff --git a/editor/docks/groups_editor.cpp b/editor/docks/groups_editor.cpp index d412c114b38..6a26f5f592d 100644 --- a/editor/docks/groups_editor.cpp +++ b/editor/docks/groups_editor.cpp @@ -911,16 +911,21 @@ GroupsEditor::GroupsEditor() { filter->connect(SceneStringName(text_changed), callable_mp(this, &GroupsEditor::_update_tree).unbind(1)); hbc->add_child(filter); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontalBottom"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + holder->add_child(mc); + tree = memnew(Tree); tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tree->set_hide_root(true); - tree->set_v_size_flags(SIZE_EXPAND_FILL); tree->set_allow_rmb_select(true); tree->set_select_mode(Tree::SelectMode::SELECT_SINGLE); + tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_TOP); + mc->add_child(tree); tree->connect("button_clicked", callable_mp(this, &GroupsEditor::_modify_group)); tree->connect("item_mouse_selected", callable_mp(this, &GroupsEditor::_item_mouse_selected)); tree->connect(SceneStringName(gui_input), callable_mp(this, &GroupsEditor::_groups_gui_input)); - holder->add_child(tree); menu = memnew(PopupMenu); menu->connect(SceneStringName(id_pressed), callable_mp(this, &GroupsEditor::_menu_id_pressed)); diff --git a/editor/docks/history_dock.cpp b/editor/docks/history_dock.cpp index 37eb006ac27..0a8b6fa7854 100644 --- a/editor/docks/history_dock.cpp +++ b/editor/docks/history_dock.cpp @@ -269,9 +269,15 @@ HistoryDock::HistoryDock() { global_history_checkbox->set_pressed(true); global_history_checkbox->connect(SceneStringName(toggled), callable_mp(this, &HistoryDock::refresh_history).unbind(1)); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontalBottom"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + main_vb->add_child(mc); + action_list = memnew(ItemList); + action_list->set_scroll_hint_mode(ItemList::SCROLL_HINT_MODE_TOP); action_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); - main_vb->add_child(action_list); + mc->add_child(action_list); action_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); action_list->connect(SceneStringName(item_selected), callable_mp(this, &HistoryDock::seek_history)); } diff --git a/editor/docks/import_dock.cpp b/editor/docks/import_dock.cpp index 8b3bf1612be..89728cc3734 100644 --- a/editor/docks/import_dock.cpp +++ b/editor/docks/import_dock.cpp @@ -779,9 +779,14 @@ ImportDock::ImportDock() { preset->get_popup()->connect("index_pressed", callable_mp(this, &ImportDock::_preset_selected)); hb->add_child(preset); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontal"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + content->add_child(mc); + import_opts = memnew(EditorInspector); - content->add_child(import_opts); - import_opts->set_v_size_flags(SIZE_EXPAND_FILL); + mc->add_child(import_opts); + import_opts->set_scroll_hint_mode(ScrollContainer::SCROLL_HINT_MODE_ALL); import_opts->connect("property_edited", callable_mp(this, &ImportDock::_property_edited)); import_opts->connect("property_toggled", callable_mp(this, &ImportDock::_property_toggled)); // Make it possible to display tooltips stored in the XML class reference. diff --git a/editor/docks/inspector_dock.cpp b/editor/docks/inspector_dock.cpp index 4f99d64e99d..ce71305bee9 100644 --- a/editor/docks/inspector_dock.cpp +++ b/editor/docks/inspector_dock.cpp @@ -871,11 +871,15 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { load_resource_dialog->set_current_dir("res://"); load_resource_dialog->connect("file_selected", callable_mp(this, &InspectorDock::_resource_file_selected)); + MarginContainer *mc = memnew(MarginContainer); + main_vb->add_child(mc); + mc->set_theme_type_variation("NoBorderHorizontalBottom"); + mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); + inspector = memnew(EditorInspector); - main_vb->add_child(inspector); + mc->add_child(inspector); inspector->set_autoclear(true); inspector->set_show_categories(true, true); - inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); inspector->set_use_doc_hints(true); inspector->set_hide_script(false); inspector->set_hide_metadata(false); @@ -883,6 +887,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { inspector->set_property_name_style(property_name_style); inspector->set_use_folding(!bool(EDITOR_GET("interface/inspector/disable_folding"))); inspector->register_text_enter(search); + inspector->set_scroll_hint_mode(ScrollContainer::SCROLL_HINT_MODE_TOP_AND_LEFT); inspector->set_use_filter(true); diff --git a/editor/docks/scene_tree_dock.cpp b/editor/docks/scene_tree_dock.cpp index 3963e009489..17b4bf4a999 100644 --- a/editor/docks/scene_tree_dock.cpp +++ b/editor/docks/scene_tree_dock.cpp @@ -4421,10 +4421,11 @@ List SceneTreeDock::get_node_clipboard() const { return node_clipboard; } -void SceneTreeDock::add_remote_tree_editor(Control *p_remote) { +void SceneTreeDock::add_remote_tree_editor(Tree *p_remote) { ERR_FAIL_COND(remote_tree != nullptr); - main_vbox->add_child(p_remote); + main_mc->add_child(p_remote); remote_tree = p_remote; + remote_tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_TOP); remote_tree->hide(); remote_tree->connect("open", callable_mp(this, &SceneTreeDock::_load_request)); } @@ -4744,7 +4745,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec editor_selection = p_editor_selection; scene_root = p_scene_root; - main_vbox = memnew(VBoxContainer); + VBoxContainer *main_vbox = memnew(VBoxContainer); add_child(main_vbox); HBoxContainer *filter_hbc = memnew(HBoxContainer); @@ -4872,10 +4873,14 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec create_root_dialog->set_v_size_flags(SIZE_EXPAND_FILL); create_root_dialog->hide(); - scene_tree = memnew(SceneTreeEditor(false, true, true)); + main_mc = memnew(MarginContainer); + main_vbox->add_child(main_mc); + main_mc->set_theme_type_variation("NoBorderHorizontalBottom"); + main_mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); - main_vbox->add_child(scene_tree); - scene_tree->set_v_size_flags(SIZE_EXPAND | SIZE_FILL); + scene_tree = memnew(SceneTreeEditor(false, true, true)); + main_mc->add_child(scene_tree); + scene_tree->get_scene_tree()->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_TOP); scene_tree->connect("rmb_pressed", callable_mp(this, &SceneTreeDock::_tree_rmb)); scene_tree->connect("node_selected", callable_mp(this, &SceneTreeDock::_node_selected), CONNECT_DEFERRED); diff --git a/editor/docks/scene_tree_dock.h b/editor/docks/scene_tree_dock.h index fb5d5256943..36832b95dca 100644 --- a/editor/docks/scene_tree_dock.h +++ b/editor/docks/scene_tree_dock.h @@ -103,7 +103,7 @@ class SceneTreeDock : public EditorDock { int current_option = 0; - VBoxContainer *main_vbox = nullptr; + MarginContainer *main_mc = nullptr; CreateDialog *create_dialog = nullptr; RenameDialog *rename_dialog = nullptr; @@ -128,7 +128,7 @@ class SceneTreeDock : public EditorDock { HBoxContainer *button_hb = nullptr; Button *edit_local, *edit_remote; SceneTreeEditor *scene_tree = nullptr; - Control *remote_tree = nullptr; + Tree *remote_tree = nullptr; void _tool_selected(int p_tool, bool p_confirm_override = false); void _property_selected(int p_idx); @@ -336,7 +336,7 @@ public: SceneTreeEditor *get_tree_editor() { return scene_tree; } EditorData *get_editor_data() { return editor_data; } - void add_remote_tree_editor(Control *p_remote); + void add_remote_tree_editor(Tree *p_remote); void show_remote_tree(); void hide_remote_tree(); void show_tab_buttons(); diff --git a/editor/docks/signals_dock.cpp b/editor/docks/signals_dock.cpp index 28fb078f9f2..e7ae0e566c9 100644 --- a/editor/docks/signals_dock.cpp +++ b/editor/docks/signals_dock.cpp @@ -32,7 +32,6 @@ #include "editor/scene/connections_dialog.h" #include "editor/settings/editor_command_palette.h" -#include "editor/themes/editor_scale.h" void SignalsDock::update_lists() { connections->update_tree(); @@ -49,12 +48,9 @@ SignalsDock::SignalsDock() { set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_signals", TTRC("Open Signals Dock"))); set_default_slot(DockConstants::DOCK_SLOT_RIGHT_UL); - VBoxContainer *main_vb = memnew(VBoxContainer); - add_child(main_vb); - connections = memnew(ConnectionsDock); - main_vb->add_child(connections); connections->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(connections); } SignalsDock::~SignalsDock() { diff --git a/editor/import/import_defaults_editor.cpp b/editor/import/import_defaults_editor.cpp index d9422744c8a..2cebe0c9823 100644 --- a/editor/import/import_defaults_editor.cpp +++ b/editor/import/import_defaults_editor.cpp @@ -37,6 +37,7 @@ #include "editor/settings/action_map_editor.h" #include "scene/gui/center_container.h" #include "scene/gui/label.h" +#include "scene/gui/margin_container.h" class ImportDefaultsEditorSettings : public Object { GDCLASS(ImportDefaultsEditorSettings, Object) @@ -213,12 +214,17 @@ ImportDefaultsEditor::ImportDefaultsEditor() { hb->add_child(reset_defaults); add_child(hb); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontal"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(mc); + inspector = memnew(EditorInspector); - add_child(inspector); - inspector->set_v_size_flags(SIZE_EXPAND_FILL); + inspector->set_scroll_hint_mode(ScrollContainer::SCROLL_HINT_MODE_ALL); // Make it possible to display tooltips stored in the XML class reference. // The object name is set when the importer changes in `_update_importer()`. inspector->set_use_doc_hints(true); + mc->add_child(inspector); CenterContainer *cc = memnew(CenterContainer); save_defaults = memnew(Button); diff --git a/editor/scene/connections_dialog.cpp b/editor/scene/connections_dialog.cpp index a4e6272c4b1..60e5a6791de 100644 --- a/editor/scene/connections_dialog.cpp +++ b/editor/scene/connections_dialog.cpp @@ -1719,16 +1719,21 @@ ConnectionsDock::ConnectionsDock() { search_box->connect(SceneStringName(text_changed), callable_mp(this, &ConnectionsDock::_filter_changed)); holder->add_child(search_box); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontal"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + holder->add_child(mc); + tree = memnew(ConnectionsDockTree); tree->set_accessibility_name(TTRC("Connections")); tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tree->set_columns(1); tree->set_select_mode(Tree::SELECT_ROW); tree->set_hide_root(true); - tree->set_column_clip_content(0, true); - holder->add_child(tree); - tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->set_allow_rmb_select(true); + tree->set_column_clip_content(0, true); + tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTH); + mc->add_child(tree); connect_button = memnew(Button); connect_button->set_accessibility_name(TTRC("Connect")); diff --git a/editor/scene/resource_preloader_editor_plugin.cpp b/editor/scene/resource_preloader_editor_plugin.cpp index 97a51092c88..5a905e9f0ea 100644 --- a/editor/scene/resource_preloader_editor_plugin.cpp +++ b/editor/scene/resource_preloader_editor_plugin.cpp @@ -339,6 +339,22 @@ void ResourcePreloaderEditor::drop_data_fw(const Point2 &p_point, const Variant } } +void ResourcePreloaderEditor::update_layout(EditorDock::DockLayout p_layout) { + bool new_horizontal = (p_layout == EditorDock::DOCK_LAYOUT_HORIZONTAL); + if (horizontal == new_horizontal) { + return; + } + horizontal = new_horizontal; + + if (horizontal) { + mc->set_theme_type_variation("NoBorderHorizontal"); + tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTH); + } else { + mc->set_theme_type_variation("NoBorderHorizontalBottom"); + tree->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_TOP); + } +} + void ResourcePreloaderEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_library"), &ResourcePreloaderEditor::_update_library); ClassDB::bind_method(D_METHOD("_remove_resource", "to_remove"), &ResourcePreloaderEditor::_remove_resource); @@ -372,6 +388,10 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { file = memnew(EditorFileDialog); add_child(file); + mc = memnew(MarginContainer); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + vbc->add_child(mc); + tree = memnew(Tree); tree->connect("button_clicked", callable_mp(this, &ResourcePreloaderEditor::_cell_button_pressed)); tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); @@ -381,10 +401,9 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { tree->set_column_clip_content(0, true); tree->set_column_expand_ratio(1, 3); tree->set_column_clip_content(1, true); - tree->set_v_size_flags(SIZE_EXPAND_FILL); SET_DRAG_FORWARDING_GCD(tree, ResourcePreloaderEditor); - vbc->add_child(tree); + mc->add_child(tree); dialog = memnew(AcceptDialog); dialog->set_title(TTRC("Error!")); diff --git a/editor/scene/resource_preloader_editor_plugin.h b/editor/scene/resource_preloader_editor_plugin.h index 5db79e8c9a2..a6fe3694115 100644 --- a/editor/scene/resource_preloader_editor_plugin.h +++ b/editor/scene/resource_preloader_editor_plugin.h @@ -50,8 +50,11 @@ class ResourcePreloaderEditor : public EditorDock { Button *load = nullptr; Button *paste = nullptr; + MarginContainer *mc = nullptr; Tree *tree = nullptr; - bool loading_scene; + + bool horizontal = false; + bool loading_scene = false; EditorFileDialog *file = nullptr; @@ -73,9 +76,10 @@ class ResourcePreloaderEditor : public EditorDock { protected: void _notification(int p_what); - static void _bind_methods(); + virtual void update_layout(EditorDock::DockLayout p_layout) override; + public: void edit(ResourcePreloader *p_preloader); ResourcePreloaderEditor(); diff --git a/editor/script/find_in_files.cpp b/editor/script/find_in_files.cpp index 21708e3f1c4..334d1eef03f 100644 --- a/editor/script/find_in_files.cpp +++ b/editor/script/find_in_files.cpp @@ -1307,7 +1307,6 @@ FindInFilesContainer::FindInFilesContainer() { set_transient(true); set_closable(true); set_custom_minimum_size(Size2(0, 200 * EDSCALE)); - set_clip_contents(false); _tabs = memnew(TabContainer); _tabs->set_tabs_visible(false); diff --git a/editor/settings/editor_command_palette.cpp b/editor/settings/editor_command_palette.cpp index ad70973e107..3c06b0ad533 100644 --- a/editor/settings/editor_command_palette.cpp +++ b/editor/settings/editor_command_palette.cpp @@ -356,6 +356,12 @@ EditorCommandPalette::EditorCommandPalette() { vbc->add_child(margin_container_csb); register_text_enter(command_search_box); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontalWindow"); + mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); + mc->set_h_size_flags(Control::SIZE_EXPAND_FILL); + vbc->add_child(mc); + search_options = memnew(Tree); search_options->connect("item_activated", callable_mp(this, &EditorCommandPalette::_confirmed)); search_options->connect(SceneStringName(item_selected), callable_mp((BaseButton *)get_ok_button(), &BaseButton::set_disabled).bind(false)); @@ -363,10 +369,9 @@ EditorCommandPalette::EditorCommandPalette() { search_options->create_item(); search_options->set_hide_root(true); search_options->set_columns(2); - search_options->set_v_size_flags(Control::SIZE_EXPAND_FILL); - search_options->set_h_size_flags(Control::SIZE_EXPAND_FILL); search_options->set_column_custom_minimum_width(0, int(8 * EDSCALE)); - vbc->add_child(search_options, true); + search_options->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTH); + mc->add_child(search_options, true); } Ref ED_SHORTCUT_AND_COMMAND(const String &p_path, const String &p_name, Key p_keycode, String p_command_name) { diff --git a/editor/shader/shader_globals_editor.cpp b/editor/shader/shader_globals_editor.cpp index c8c96ace501..73266d4e0ae 100644 --- a/editor/shader/shader_globals_editor.cpp +++ b/editor/shader/shader_globals_editor.cpp @@ -36,6 +36,7 @@ #include "editor/inspector/editor_inspector.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" +#include "scene/gui/margin_container.h" #include "servers/rendering/shader_language.h" static const char *global_var_type_names[RS::GLOBAL_VAR_TYPE_MAX] = { @@ -487,12 +488,17 @@ ShaderGlobalsEditor::ShaderGlobalsEditor() { add_menu_hb->add_child(variable_add); variable_add->connect(SceneStringName(pressed), callable_mp(this, &ShaderGlobalsEditor::_variable_added)); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontalBottom"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(mc); + inspector = memnew(EditorInspector); - inspector->set_v_size_flags(SIZE_EXPAND_FILL); - add_child(inspector); inspector->set_use_wide_editors(true); inspector->set_property_name_style(EditorPropertyNameProcessor::STYLE_RAW); inspector->set_use_deletable_properties(true); + inspector->set_scroll_hint_mode(ScrollContainer::SCROLL_HINT_MODE_TOP_AND_LEFT); + mc->add_child(inspector); inspector->connect("property_deleted", callable_mp(this, &ShaderGlobalsEditor::_variable_deleted), CONNECT_DEFERRED); interface = memnew(ShaderGlobalsEditorInterface); diff --git a/editor/themes/theme_classic.cpp b/editor/themes/theme_classic.cpp index e570bfc5a6c..4a6ffa6acc4 100644 --- a/editor/themes/theme_classic.cpp +++ b/editor/themes/theme_classic.cpp @@ -1588,6 +1588,7 @@ void ThemeClassic::populate_editor_styles(const Ref &p_theme, Edito p_theme->set_icon("scroll_hint_vertical", "ScrollContainer", empty_texture); p_theme->set_icon("scroll_hint_horizontal", "ScrollContainer", empty_texture); p_theme->set_icon("scroll_hint", "Tree", empty_texture); + p_theme->set_icon("scroll_hint", "ItemList", empty_texture); // This stylebox is used in 3d and 2d viewports (no borders). Ref style_content_panel_vp = p_config.content_panel_style->duplicate(); diff --git a/editor/themes/theme_modern.cpp b/editor/themes/theme_modern.cpp index 11e698685ac..312ddd940bb 100644 --- a/editor/themes/theme_modern.cpp +++ b/editor/themes/theme_modern.cpp @@ -1861,6 +1861,33 @@ void ThemeModern::populate_editor_styles(const Ref &p_theme, Editor p_theme->set_stylebox(SceneStringName(panel), "EditorAbout", p_config.window_complex_style); p_theme->set_stylebox(SceneStringName(panel), "ThemeItemEditorDialog", p_config.window_complex_style); + // MarginContainers with negative margins, to negate borders. Used with scroll hints. + { + int margin = -p_theme->get_stylebox(SceneStringName(panel), SNAME("PanelContainer"))->get_content_margin(SIDE_LEFT); + + p_theme->set_type_variation("NoBorderHorizontal", "MarginContainer"); + p_theme->set_constant("margin_left", "NoBorderHorizontal", margin); + p_theme->set_constant("margin_right", "NoBorderHorizontal", margin); + + p_theme->set_type_variation("NoBorderHorizontalBottom", "MarginContainer"); + p_theme->set_constant("margin_left", "NoBorderHorizontalBottom", margin); + p_theme->set_constant("margin_right", "NoBorderHorizontalBottom", margin); + p_theme->set_constant("margin_bottom", "NoBorderHorizontalBottom", margin); + + margin = margin - p_theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles))->get_content_margin(SIDE_LEFT); + + // Used in the animation track editor. + p_theme->set_type_variation("NoBorderAnimation", "MarginContainer"); + p_theme->set_constant("margin_left", "NoBorderAnimation", margin); + p_theme->set_constant("margin_right", "NoBorderAnimation", margin); + + margin = -p_theme->get_stylebox(SceneStringName(panel), SNAME("AcceptDialog"))->get_content_margin(SIDE_LEFT); + + p_theme->set_type_variation("NoBorderHorizontalWindow", "MarginContainer"); + p_theme->set_constant("margin_left", "NoBorderHorizontalWindow", margin); + p_theme->set_constant("margin_right", "NoBorderHorizontalWindow", margin); + } + // Buttons in material previews. { const Color dim_light_color = p_config.icon_normal_color.darkened(0.24); diff --git a/editor/translations/localization_editor.cpp b/editor/translations/localization_editor.cpp index 4785eeacf19..9a6d8850d33 100644 --- a/editor/translations/localization_editor.cpp +++ b/editor/translations/localization_editor.cpp @@ -751,13 +751,14 @@ LocalizationEditor::LocalizationEditor() { addtr->connect(SceneStringName(pressed), callable_mp(this, &LocalizationEditor::_translation_file_open)); thb->add_child(addtr); - VBoxContainer *tmc = memnew(VBoxContainer); - tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); - tvb->add_child(tmc); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontalBottom"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + tvb->add_child(mc); translation_list = memnew(Tree); - translation_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); - tmc->add_child(translation_list); + translation_list->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_TOP); + mc->add_child(translation_list); trees.push_back(translation_list); tree_data_types[translation_list] = "localization_editor_translation_item"; tree_settings[translation_list] = "internationalization/locale/translations"; @@ -788,15 +789,16 @@ LocalizationEditor::LocalizationEditor() { addtr->connect(SceneStringName(pressed), callable_mp(this, &LocalizationEditor::_translation_res_file_open)); thb->add_child(addtr); - VBoxContainer *tmc = memnew(VBoxContainer); - tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); - tvb->add_child(tmc); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontal"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + tvb->add_child(mc); translation_remap = memnew(Tree); - translation_remap->set_v_size_flags(Control::SIZE_EXPAND_FILL); + translation_remap->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTH); translation_remap->connect("cell_selected", callable_mp(this, &LocalizationEditor::_translation_res_select)); translation_remap->connect("button_clicked", callable_mp(this, &LocalizationEditor::_translation_res_delete)); - tmc->add_child(translation_remap); + mc->add_child(translation_remap); translation_res_file_open_dialog = memnew(EditorFileDialog); translation_res_file_open_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); @@ -815,10 +817,6 @@ LocalizationEditor::LocalizationEditor() { translation_res_option_add_button = addtr; thb->add_child(addtr); - tmc = memnew(VBoxContainer); - tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); - tvb->add_child(tmc); - translation_remap_options = memnew(Tree); translation_remap_options->set_v_size_flags(Control::SIZE_EXPAND_FILL); translation_remap_options->set_columns(2); @@ -833,7 +831,7 @@ LocalizationEditor::LocalizationEditor() { translation_remap_options->connect("item_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_changed)); translation_remap_options->connect("button_clicked", callable_mp(this, &LocalizationEditor::_translation_res_option_delete)); translation_remap_options->connect("custom_popup_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_popup)); - tmc->add_child(translation_remap_options); + mc->add_child(translation_remap_options); translation_res_option_file_open_dialog = memnew(EditorFileDialog); translation_res_option_file_open_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); @@ -861,9 +859,14 @@ LocalizationEditor::LocalizationEditor() { template_generate_button->connect(SceneStringName(pressed), callable_mp(this, &LocalizationEditor::_template_generate_open)); thb->add_child(template_generate_button); + MarginContainer *mc = memnew(MarginContainer); + mc->set_theme_type_variation("NoBorderHorizontal"); + mc->set_v_size_flags(SIZE_EXPAND_FILL); + tvb->add_child(mc); + template_source_list = memnew(Tree); - template_source_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); - tvb->add_child(template_source_list); + template_source_list->set_scroll_hint_mode(Tree::SCROLL_HINT_MODE_BOTH); + mc->add_child(template_source_list); trees.push_back(template_source_list); tree_data_types[template_source_list] = "localization_editor_pot_item"; tree_settings[template_source_list] = "internationalization/locale/translations_pot_files"; diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs index 9421ee73559..854cdde6063 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs @@ -208,7 +208,6 @@ namespace GodotTools.Build AvailableLayouts = DockLayout.Horizontal | DockLayout.Floating; Global = false; Transient = true; - ClipContents = false; } public override void _Ready() diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 6f2ebd71fd1..ba114225a23 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -1705,6 +1705,21 @@ void ItemList::_notification(int p_what) { draw_style_box(cursor, cursor_rcache); } + if (scroll_hint_mode != SCROLL_HINT_MODE_DISABLED) { + Size2 control_size = get_size(); + float v_scroll_value = scroll_bar_v->get_value(); + bool v_scroll_below_max = v_scroll_value < (scroll_bar_v->get_max() - scroll_bar_v->get_page() - 1); + if (v_scroll_value > 1 || v_scroll_below_max) { + int hint_height = theme_cache.scroll_hint->get_height(); + if ((scroll_hint_mode == SCROLL_HINT_MODE_BOTH || scroll_hint_mode == SCROLL_HINT_MODE_TOP) && v_scroll_value > 1) { + draw_texture_rect(theme_cache.scroll_hint, Rect2(Point2(), Size2(control_size.width, hint_height)), tile_scroll_hint); + } + if ((scroll_hint_mode == SCROLL_HINT_MODE_BOTH || scroll_hint_mode == SCROLL_HINT_MODE_BOTTOM) && v_scroll_below_max) { + draw_texture_rect(theme_cache.scroll_hint, Rect2(Point2(0, control_size.height - hint_height), Size2(control_size.width, -hint_height)), tile_scroll_hint); + } + } + } + if (has_focus(true)) { RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true); size.x -= (scroll_bar_h->get_max() - scroll_bar_h->get_page()); @@ -2193,6 +2208,32 @@ bool ItemList::has_wraparound_items() const { return wraparound_items; } +void ItemList::set_scroll_hint_mode(ScrollHintMode p_mode) { + if (scroll_hint_mode == p_mode) { + return; + } + + scroll_hint_mode = p_mode; + queue_redraw(); +} + +ItemList::ScrollHintMode ItemList::get_scroll_hint_mode() const { + return scroll_hint_mode; +} + +void ItemList::set_tile_scroll_hint(bool p_enable) { + if (tile_scroll_hint == p_enable) { + return; + } + + tile_scroll_hint = p_enable; + queue_redraw(); +} + +bool ItemList::is_scroll_hint_tiled() { + return tile_scroll_hint; +} + bool ItemList::_set(const StringName &p_name, const Variant &p_value) { if (property_helper.property_set_value(p_name, p_value)) { return true; @@ -2334,6 +2375,12 @@ void ItemList::_bind_methods() { ClassDB::bind_method(D_METHOD("get_v_scroll_bar"), &ItemList::get_v_scroll_bar); ClassDB::bind_method(D_METHOD("get_h_scroll_bar"), &ItemList::get_h_scroll_bar); + ClassDB::bind_method(D_METHOD("set_scroll_hint_mode", "scroll_hint_mode"), &ItemList::set_scroll_hint_mode); + ClassDB::bind_method(D_METHOD("get_scroll_hint_mode"), &ItemList::get_scroll_hint_mode); + + ClassDB::bind_method(D_METHOD("set_tile_scroll_hint", "tile_scroll_hint"), &ItemList::set_tile_scroll_hint); + ClassDB::bind_method(D_METHOD("is_scroll_hint_tiled"), &ItemList::is_scroll_hint_tiled); + ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &ItemList::set_text_overrun_behavior); ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &ItemList::get_text_overrun_behavior); @@ -2351,6 +2398,8 @@ void ItemList::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_height"), "set_auto_height", "has_auto_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis (6+ Characters),Word Ellipsis (6+ Characters),Ellipsis (Always),Word Ellipsis (Always)"), "set_text_overrun_behavior", "get_text_overrun_behavior"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wraparound_items"), "set_wraparound_items", "has_wraparound_items"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_hint_mode", PROPERTY_HINT_ENUM, "Disabled,Both,Top,Bottom"), "set_scroll_hint_mode", "get_scroll_hint_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tile_scroll_hint"), "set_tile_scroll_hint", "is_scroll_hint_tiled"); ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "item_"); ADD_GROUP("Columns", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_columns", PROPERTY_HINT_RANGE, "0,10,1,or_greater"), "set_max_columns", "get_max_columns"); @@ -2368,6 +2417,11 @@ void ItemList::_bind_methods() { BIND_ENUM_CONSTANT(SELECT_MULTI); BIND_ENUM_CONSTANT(SELECT_TOGGLE); + BIND_ENUM_CONSTANT(SCROLL_HINT_MODE_DISABLED); + BIND_ENUM_CONSTANT(SCROLL_HINT_MODE_BOTH); + BIND_ENUM_CONSTANT(SCROLL_HINT_MODE_TOP); + BIND_ENUM_CONSTANT(SCROLL_HINT_MODE_BOTTOM); + ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index"))); ADD_SIGNAL(MethodInfo("empty_clicked", PropertyInfo(Variant::VECTOR2, "at_position"), PropertyInfo(Variant::INT, "mouse_button_index"))); ADD_SIGNAL(MethodInfo("item_clicked", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "at_position"), PropertyInfo(Variant::INT, "mouse_button_index"))); @@ -2388,6 +2442,7 @@ void ItemList::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_selected_color); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, ItemList, font_outline_size, "outline_size"); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_outline_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ItemList, scroll_hint); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ItemList, line_separation); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ItemList, icon_margin); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 05410df88fe..2a06e5c306f 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -50,6 +50,13 @@ public: SELECT_TOGGLE, }; + enum ScrollHintMode { + SCROLL_HINT_MODE_DISABLED, + SCROLL_HINT_MODE_BOTH, + SCROLL_HINT_MODE_TOP, + SCROLL_HINT_MODE_BOTTOM, + }; + private: struct Item { mutable RID accessibility_item_element; @@ -123,6 +130,9 @@ private: HScrollBar *scroll_bar_h = nullptr; TextServer::OverrunBehavior text_overrun_behavior = TextServer::OVERRUN_TRIM_ELLIPSIS; + ScrollHintMode scroll_hint_mode = SCROLL_HINT_MODE_DISABLED; + bool tile_scroll_hint = false; + uint64_t search_time_msec = 0; String search_string; @@ -176,6 +186,8 @@ protected: Ref cursor_style; Ref cursor_focus_style; Color guide_color; + + Ref scroll_hint; } theme_cache; void _notification(int p_what); @@ -335,9 +347,16 @@ public: VScrollBar *get_v_scroll_bar() { return scroll_bar_v; } HScrollBar *get_h_scroll_bar() { return scroll_bar_h; } + void set_scroll_hint_mode(ScrollHintMode p_mode); + ScrollHintMode get_scroll_hint_mode() const; + + void set_tile_scroll_hint(bool p_enable); + bool is_scroll_hint_tiled(); + ItemList(); ~ItemList(); }; VARIANT_ENUM_CAST(ItemList::SelectMode); VARIANT_ENUM_CAST(ItemList::IconMode); +VARIANT_ENUM_CAST(ItemList::ScrollHintMode); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 0f153c96b4d..b7f20be2190 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -43,16 +43,11 @@ Size2 ScrollContainer::get_minimum_size() const { for (int i = 0; i < get_child_count(); i++) { Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE); - if (!c) { - continue; - } - // Ignore the scroll hints. - if (c == h_scroll || c == v_scroll || c == focus_panel) { + if (!c || c == h_scroll || c == v_scroll || c == focus_panel || c == scroll_hint_top_left || c == scroll_hint_bottom_right) { continue; } Size2 child_min_size = c->get_combined_minimum_size(); - largest_child_min_size = largest_child_min_size.max(child_min_size); } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index e47c6753801..5e2260169c2 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -4556,6 +4556,7 @@ void Tree::update_scrollbars() { theme_cache.offset.y = v_scroll->get_value(); } else { v_scroll->hide(); + v_scroll->set_value(0); theme_cache.offset.y = 0; } @@ -4566,6 +4567,7 @@ void Tree::update_scrollbars() { theme_cache.offset.x = h_scroll->get_value(); } else { h_scroll->hide(); + h_scroll->set_value(0); theme_cache.offset.x = 0; } @@ -5131,7 +5133,7 @@ void Tree::_notification(int p_what) { if (scroll_hint_mode != SCROLL_HINT_MODE_DISABLED) { Size2 size = get_size(); float v_scroll_value = v_scroll->get_value(); - bool v_scroll_below_max = v_scroll_value < (get_internal_min_size().height - size.height - 1); + bool v_scroll_below_max = v_scroll_value < (get_internal_min_size().height - (content_rect.get_size().height - _get_title_button_height()) - 1); if (v_scroll_value > 1 || v_scroll_below_max) { int hint_height = theme_cache.scroll_hint->get_height(); if ((scroll_hint_mode == SCROLL_HINT_MODE_BOTH || scroll_hint_mode == SCROLL_HINT_MODE_TOP) && v_scroll_value > 1) { diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp index e338a5e594b..aae90f29f92 100644 --- a/scene/theme/default_theme.cpp +++ b/scene/theme/default_theme.cpp @@ -959,6 +959,7 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const theme->set_stylebox("selected_focus", "ItemList", make_flat_stylebox(style_selected_color)); theme->set_stylebox("cursor", "ItemList", focus); theme->set_stylebox("cursor_unfocused", "ItemList", focus); + theme->set_icon("scroll_hint", "ItemList", icons["scroll_hint_vertical"]); theme->set_constant("outline_size", "ItemList", 0);