1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-31 18:41:20 +00:00

Add scroll hints to ScrollContainer and Tree

This commit is contained in:
Michael Alexsander
2025-11-06 23:01:16 -03:00
parent 9dd6c4dbac
commit 639e396d98
10 changed files with 282 additions and 16 deletions

View File

@@ -32,12 +32,13 @@
#include "core/config/project_settings.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/main/window.h"
#include "scene/theme/theme_db.h"
Size2 ScrollContainer::get_minimum_size() const {
// Calculated in this function, as it needs to traverse all child controls once to calculate;
// and needs to be calculated before being used by update_scrollbars().
// and needs to be calculated before being used by `_update_scrollbars()`.
largest_child_min_size = Size2();
for (int i = 0; i < get_child_count(); i++) {
@@ -342,7 +343,8 @@ void ScrollContainer::ensure_control_visible(Control *p_control) {
}
void ScrollContainer::_reposition_children() {
update_scrollbars();
_update_scrollbars();
_update_scroll_hints();
Rect2 margins = _get_margins();
Size2 size = get_size();
@@ -362,10 +364,7 @@ void ScrollContainer::_reposition_children() {
for (int i = 0; i < get_child_count(); i++) {
Control *c = as_sortable_control(get_child(i));
if (!c) {
continue;
}
if (c == h_scroll || c == v_scroll || c == focus_panel) {
if (!c || c->is_internal()) {
continue;
}
Size2 minsize = c->get_combined_minimum_size();
@@ -445,7 +444,10 @@ void ScrollContainer::_notification(int p_what) {
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SET_SCROLL_OFFSET, callable_mp(this, &ScrollContainer::_accessibility_action_scroll_set));
} break;
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
_update_scroll_hints();
[[fallthrough]];
}
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED: {
_updating_scrollbars = true;
@@ -579,7 +581,7 @@ void ScrollContainer::_notification(int p_what) {
}
}
void ScrollContainer::update_scrollbars() {
void ScrollContainer::_update_scrollbars() {
Rect2 margins = _get_margins();
Size2 size = get_size();
@@ -602,6 +604,55 @@ void ScrollContainer::update_scrollbars() {
callable_mp(this, &ScrollContainer::_update_scrollbar_position).call_deferred();
}
void ScrollContainer::_update_scroll_hints() {
Size2 size = get_size();
Rect2 margins = _get_margins();
Size2 scroll_size = size - margins.position + margins.size;
float v_scroll_value = v_scroll->get_value();
bool v_scroll_below_max = v_scroll_value < (largest_child_min_size.height - scroll_size.height - 1);
bool show_vertical_hints = v_scroll_value > 1 || v_scroll_below_max;
float h_scroll_value = h_scroll->get_value();
bool h_scroll_below_max = h_scroll_value < (largest_child_min_size.width - scroll_size.width - 1);
bool show_horizontal_hints = h_scroll_value > 1 || h_scroll_below_max;
bool rtl = is_layout_rtl();
if (show_vertical_hints) {
scroll_hint_top_left->set_texture(theme_cache.scroll_hint_vertical);
scroll_hint_top_left->set_visible(!show_horizontal_hints && (scroll_hint_mode == SCROLL_HINT_MODE_ALL || scroll_hint_mode == SCROLL_HINT_MODE_TOP_AND_LEFT) && v_scroll_value > 1);
scroll_hint_top_left->set_anchor_and_offset(SIDE_LEFT, ANCHOR_BEGIN, rtl ? -size.x : 0);
scroll_hint_top_left->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, rtl ? 0 : size.x);
scroll_hint_top_left->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 0);
scroll_hint_top_left->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_BEGIN, theme_cache.scroll_hint_vertical->get_height());
scroll_hint_bottom_right->set_flip_h(false);
scroll_hint_bottom_right->set_flip_v(true);
scroll_hint_bottom_right->set_texture(theme_cache.scroll_hint_vertical);
scroll_hint_bottom_right->set_visible(!show_horizontal_hints && (scroll_hint_mode == SCROLL_HINT_MODE_ALL || scroll_hint_mode == SCROLL_HINT_MODE_BOTTOM_AND_RIGHT) && v_scroll_below_max);
scroll_hint_bottom_right->set_anchor_and_offset(SIDE_LEFT, ANCHOR_BEGIN, rtl ? -size.x : 0);
scroll_hint_bottom_right->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, rtl ? 0 : size.x);
scroll_hint_bottom_right->set_anchor_and_offset(SIDE_TOP, ANCHOR_END, -theme_cache.scroll_hint_vertical->get_height());
scroll_hint_bottom_right->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0);
} else {
scroll_hint_top_left->set_texture(theme_cache.scroll_hint_horizontal);
scroll_hint_top_left->set_visible(!show_vertical_hints && (scroll_hint_mode == SCROLL_HINT_MODE_ALL || (rtl ? scroll_hint_mode == SCROLL_HINT_MODE_BOTTOM_AND_RIGHT : scroll_hint_mode == SCROLL_HINT_MODE_TOP_AND_LEFT)) && h_scroll_value > 1);
scroll_hint_top_left->set_anchor_and_offset(SIDE_LEFT, ANCHOR_BEGIN, rtl ? (size.x - theme_cache.scroll_hint_horizontal->get_width()) : 0);
scroll_hint_top_left->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_BEGIN, rtl ? size.x : theme_cache.scroll_hint_horizontal->get_width());
scroll_hint_top_left->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 0);
scroll_hint_top_left->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0);
scroll_hint_bottom_right->set_flip_h(true);
scroll_hint_bottom_right->set_flip_v(false);
scroll_hint_bottom_right->set_texture(theme_cache.scroll_hint_horizontal);
scroll_hint_bottom_right->set_visible(!show_vertical_hints && (scroll_hint_mode == SCROLL_HINT_MODE_ALL || (rtl ? scroll_hint_mode == SCROLL_HINT_MODE_TOP_AND_LEFT : scroll_hint_mode == SCROLL_HINT_MODE_BOTTOM_AND_RIGHT)) && h_scroll_below_max);
scroll_hint_bottom_right->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, rtl ? -size.x : -theme_cache.scroll_hint_horizontal->get_width());
scroll_hint_bottom_right->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, rtl ? (-size.x + theme_cache.scroll_hint_horizontal->get_width()) : 0);
scroll_hint_bottom_right->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, 0);
scroll_hint_bottom_right->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, 0);
}
}
void ScrollContainer::_scroll_moved(float) {
queue_sort();
}
@@ -676,6 +727,34 @@ void ScrollContainer::set_deadzone(int p_deadzone) {
deadzone = p_deadzone;
}
void ScrollContainer::set_scroll_hint_mode(ScrollHintMode p_mode) {
if (scroll_hint_mode == p_mode) {
return;
}
scroll_hint_mode = p_mode;
_update_scroll_hints();
}
ScrollContainer::ScrollHintMode ScrollContainer::get_scroll_hint_mode() const {
return scroll_hint_mode;
}
void ScrollContainer::set_tile_scroll_hint(bool p_enable) {
if (tile_scroll_hint == p_enable) {
return;
}
scroll_hint_top_left->set_stretch_mode(p_enable ? TextureRect::STRETCH_TILE : TextureRect::STRETCH_SCALE);
scroll_hint_bottom_right->set_stretch_mode(p_enable ? TextureRect::STRETCH_TILE : TextureRect::STRETCH_SCALE);
tile_scroll_hint = p_enable;
}
bool ScrollContainer::is_scroll_hint_tiled() {
return tile_scroll_hint;
}
bool ScrollContainer::is_following_focus() const {
return follow_focus;
}
@@ -691,10 +770,7 @@ PackedStringArray ScrollContainer::get_configuration_warnings() const {
for (int i = 0; i < get_child_count(); i++) {
Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE);
if (!c) {
continue;
}
if (c == h_scroll || c == v_scroll || c == focus_panel) {
if (!c || c->is_internal()) {
continue;
}
@@ -742,6 +818,12 @@ void ScrollContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_deadzone", "deadzone"), &ScrollContainer::set_deadzone);
ClassDB::bind_method(D_METHOD("get_deadzone"), &ScrollContainer::get_deadzone);
ClassDB::bind_method(D_METHOD("set_scroll_hint_mode", "scroll_hint_mode"), &ScrollContainer::set_scroll_hint_mode);
ClassDB::bind_method(D_METHOD("get_scroll_hint_mode"), &ScrollContainer::get_scroll_hint_mode);
ClassDB::bind_method(D_METHOD("set_tile_scroll_hint", "tile_scroll_hint"), &ScrollContainer::set_tile_scroll_hint);
ClassDB::bind_method(D_METHOD("is_scroll_hint_tiled"), &ScrollContainer::is_scroll_hint_tiled);
ClassDB::bind_method(D_METHOD("set_follow_focus", "enabled"), &ScrollContainer::set_follow_focus);
ClassDB::bind_method(D_METHOD("is_following_focus"), &ScrollContainer::is_following_focus);
@@ -758,7 +840,7 @@ void ScrollContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_focus"), "set_follow_focus", "is_following_focus");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_focus_border"), "set_draw_focus_border", "get_draw_focus_border");
ADD_GROUP("Scroll", "scroll_");
ADD_GROUP("Scrollbar", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal", PROPERTY_HINT_NONE, "suffix:px"), "set_h_scroll", "get_h_scroll");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_horizontal_custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_horizontal_custom_step", "get_horizontal_custom_step");
@@ -767,18 +849,30 @@ void ScrollContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show,Reserve"), "set_vertical_scroll_mode", "get_vertical_scroll_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_deadzone"), "set_deadzone", "get_deadzone");
ADD_GROUP("Scroll Hint", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_hint_mode", PROPERTY_HINT_ENUM, "Disabled,All,Top and Left,Bottom and Right"), "set_scroll_hint_mode", "get_scroll_hint_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tile_scroll_hint"), "set_tile_scroll_hint", "is_scroll_hint_tiled");
BIND_ENUM_CONSTANT(SCROLL_MODE_DISABLED);
BIND_ENUM_CONSTANT(SCROLL_MODE_AUTO);
BIND_ENUM_CONSTANT(SCROLL_MODE_SHOW_ALWAYS);
BIND_ENUM_CONSTANT(SCROLL_MODE_SHOW_NEVER);
BIND_ENUM_CONSTANT(SCROLL_MODE_RESERVE);
BIND_ENUM_CONSTANT(SCROLL_HINT_MODE_DISABLED);
BIND_ENUM_CONSTANT(SCROLL_HINT_MODE_ALL);
BIND_ENUM_CONSTANT(SCROLL_HINT_MODE_TOP_AND_LEFT);
BIND_ENUM_CONSTANT(SCROLL_HINT_MODE_BOTTOM_AND_RIGHT);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ScrollContainer, scrollbar_h_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, ScrollContainer, scrollbar_v_separation);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollContainer, panel_style, "panel");
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollContainer, focus_style, "focus");
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ScrollContainer, scroll_hint_vertical);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ScrollContainer, scroll_hint_horizontal);
GLOBAL_DEF("gui/common/default_scroll_deadzone", 0);
}
@@ -802,6 +896,18 @@ bool ScrollContainer::child_has_focus() {
}
ScrollContainer::ScrollContainer() {
scroll_hint_top_left = memnew(TextureRect);
scroll_hint_top_left->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE);
scroll_hint_top_left->set_mouse_filter(MOUSE_FILTER_IGNORE);
scroll_hint_top_left->hide();
add_child(scroll_hint_top_left, false, INTERNAL_MODE_BACK);
scroll_hint_bottom_right = memnew(TextureRect);
scroll_hint_bottom_right->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE);
scroll_hint_bottom_right->set_mouse_filter(MOUSE_FILTER_IGNORE);
scroll_hint_bottom_right->hide();
add_child(scroll_hint_bottom_right, false, INTERNAL_MODE_BACK);
h_scroll = memnew(HScrollBar);
h_scroll->set_name("_h_scroll");
add_child(h_scroll, false, INTERNAL_MODE_BACK);

View File

@@ -35,6 +35,7 @@
#include "scroll_bar.h"
class PanelContainer;
class TextureRect;
class ScrollContainer : public Container {
GDCLASS(ScrollContainer, Container);
@@ -48,6 +49,13 @@ public:
SCROLL_MODE_RESERVE,
};
enum ScrollHintMode {
SCROLL_HINT_MODE_DISABLED,
SCROLL_HINT_MODE_ALL,
SCROLL_HINT_MODE_TOP_AND_LEFT,
SCROLL_HINT_MODE_BOTTOM_AND_RIGHT,
};
private:
HScrollBar *h_scroll = nullptr;
VScrollBar *v_scroll = nullptr;
@@ -55,7 +63,7 @@ private:
mutable Size2 largest_child_min_size; // The largest one among the min sizes of all available child controls.
void update_scrollbars();
void _update_scrollbars();
Vector2 drag_speed;
Vector2 drag_accum;
@@ -67,18 +75,29 @@ private:
bool beyond_deadzone = false;
bool scroll_on_drag_hover = false;
TextureRect *scroll_hint_top_left = nullptr;
TextureRect *scroll_hint_bottom_right = nullptr;
ScrollMode horizontal_scroll_mode = SCROLL_MODE_AUTO;
ScrollMode vertical_scroll_mode = SCROLL_MODE_AUTO;
void _update_scroll_hints();
int deadzone = 0;
bool follow_focus = false;
int scroll_border = 20;
int scroll_speed = 12;
ScrollHintMode scroll_hint_mode = SCROLL_HINT_MODE_DISABLED;
bool tile_scroll_hint = false;
struct ThemeCache {
Ref<StyleBox> panel_style;
Ref<StyleBox> focus_style;
Ref<Texture2D> scroll_hint_vertical;
Ref<Texture2D> scroll_hint_horizontal;
int scrollbar_h_separation = 0;
int scrollbar_v_separation = 0;
} theme_cache;
@@ -134,8 +153,14 @@ public:
void set_vertical_scroll_mode(ScrollMode p_mode);
ScrollMode get_vertical_scroll_mode() const;
int get_deadzone() const;
void set_deadzone(int p_deadzone);
int get_deadzone() const;
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();
bool is_following_focus() const;
void set_follow_focus(bool p_follow);
@@ -155,3 +180,4 @@ public:
};
VARIANT_ENUM_CAST(ScrollContainer::ScrollMode);
VARIANT_ENUM_CAST(ScrollContainer::ScrollHintMode);

View File

@@ -5127,6 +5127,21 @@ 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);
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(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, size.height - hint_height), Size2(size.width, -hint_height)), tile_scroll_hint);
}
}
}
// Draw the focus outline last, so that it is drawn in front of the section headings.
// Otherwise, section heading backgrounds can appear to be in front of the focus outline when scrolling.
if (has_focus(true)) {
@@ -5995,6 +6010,32 @@ bool Tree::is_v_scroll_enabled() const {
return v_scroll_enabled;
}
void Tree::set_scroll_hint_mode(ScrollHintMode p_mode) {
if (scroll_hint_mode == p_mode) {
return;
}
scroll_hint_mode = p_mode;
queue_redraw();
}
Tree::ScrollHintMode Tree::get_scroll_hint_mode() const {
return scroll_hint_mode;
}
void Tree::set_tile_scroll_hint(bool p_enable) {
if (tile_scroll_hint == p_enable) {
return;
}
tile_scroll_hint = p_enable;
queue_redraw();
}
bool Tree::is_scroll_hint_tiled() {
return tile_scroll_hint;
}
TreeItem *Tree::_search_item_text(TreeItem *p_at, const String &p_find, int *r_col, bool p_selectable, bool p_backwards) {
TreeItem *from = p_at;
TreeItem *loop = nullptr; // Safe-guard against infinite loop.
@@ -6656,6 +6697,12 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_v_scroll_enabled", "h_scroll"), &Tree::set_v_scroll_enabled);
ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"), &Tree::is_v_scroll_enabled);
ClassDB::bind_method(D_METHOD("set_scroll_hint_mode", "scroll_hint_mode"), &Tree::set_scroll_hint_mode);
ClassDB::bind_method(D_METHOD("get_scroll_hint_mode"), &Tree::get_scroll_hint_mode);
ClassDB::bind_method(D_METHOD("set_tile_scroll_hint", "tile_scroll_hint"), &Tree::set_tile_scroll_hint);
ClassDB::bind_method(D_METHOD("is_scroll_hint_tiled"), &Tree::is_scroll_hint_tiled);
ClassDB::bind_method(D_METHOD("set_hide_folding", "hide"), &Tree::set_hide_folding);
ClassDB::bind_method(D_METHOD("is_folding_hidden"), &Tree::is_folding_hidden);
@@ -6691,9 +6738,12 @@ void Tree::_bind_methods() {
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");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_tooltip"), "set_auto_tooltip", "is_auto_tooltip_enabled");
ADD_GROUP("Scroll", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_horizontal_enabled"), "set_h_scroll_enabled", "is_h_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_vertical_enabled"), "set_v_scroll_enabled", "is_v_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_tooltip"), "set_auto_tooltip", "is_auto_tooltip_enabled");
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_SIGNAL(MethodInfo("item_selected"));
ADD_SIGNAL(MethodInfo("cell_selected"));
@@ -6719,6 +6769,11 @@ void Tree::_bind_methods() {
BIND_ENUM_CONSTANT(DROP_MODE_ON_ITEM);
BIND_ENUM_CONSTANT(DROP_MODE_INBETWEEN);
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);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Tree, panel_style, "panel");
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, Tree, focus_style, "focus");
@@ -6749,6 +6804,7 @@ void Tree::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, arrow_collapsed_mirrored);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, select_arrow);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, updown);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Tree, scroll_hint);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, custom_button);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Tree, custom_button_hover);

View File

@@ -466,6 +466,13 @@ public:
DROP_MODE_INBETWEEN = 2
};
enum ScrollHintMode {
SCROLL_HINT_MODE_DISABLED,
SCROLL_HINT_MODE_BOTH,
SCROLL_HINT_MODE_TOP,
SCROLL_HINT_MODE_BOTTOM,
};
private:
friend class TreeItem;
@@ -622,6 +629,7 @@ private:
Ref<Texture2D> arrow_collapsed_mirrored;
Ref<Texture2D> select_arrow;
Ref<Texture2D> updown;
Ref<Texture2D> scroll_hint;
Color font_color;
Color font_hovered_color;
@@ -738,6 +746,9 @@ private:
bool allow_rmb_select = false;
bool scrolling = false;
ScrollHintMode scroll_hint_mode = SCROLL_HINT_MODE_DISABLED;
bool tile_scroll_hint = false;
bool allow_reselect = false;
bool allow_search = true;
@@ -893,6 +904,12 @@ public:
void set_v_scroll_enabled(bool p_enable);
bool is_v_scroll_enabled() const;
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();
void set_cursor_can_exit_tree(bool p_enable);
VScrollBar *get_vscroll_bar() { return v_scroll; }
@@ -932,3 +949,4 @@ public:
VARIANT_ENUM_CAST(Tree::SelectMode);
VARIANT_ENUM_CAST(Tree::DropModeFlags);
VARIANT_ENUM_CAST(Tree::ScrollHintMode);

View File

@@ -664,6 +664,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
focus_style->set_border_color(style_focus_color);
theme->set_stylebox("focus", "ScrollContainer", focus_style);
theme->set_icon("scroll_hint_vertical", "ScrollContainer", icons["scroll_hint_vertical"]);
theme->set_icon("scroll_hint_horizontal", "ScrollContainer", icons["scroll_hint_horizontal"]);
// Window
theme->set_stylebox("embedded_border", "Window", sb_expand(make_flat_stylebox(style_popup_color, 10, 28, 10, 8), 8, 32, 8, 6));
@@ -883,6 +886,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_icon("arrow", "Tree", icons["arrow_down"]);
theme->set_icon("arrow_collapsed", "Tree", icons["arrow_right"]);
theme->set_icon("arrow_collapsed_mirrored", "Tree", icons["arrow_left"]);
theme->set_icon("scroll_hint", "Tree", icons["scroll_hint_vertical"]);
theme->set_font("title_button_font", "Tree", Ref<Font>());
theme->set_font(SceneStringName(font), "Tree", Ref<Font>());

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="32" viewBox="0 0 6.35 8.467"><defs><linearGradient id="a"><stop offset="0" stop-opacity=".3"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="4.233" x2="4.233" y1="0" y2="6.35" gradientTransform="translate(-8.467)" gradientUnits="userSpaceOnUse"/></defs><path fill="url(#b)" d="M-8.467 0H0V6.35H-8.467z" paint-order="fill markers stroke" transform="rotate(-90)"/></svg>

After

Width:  |  Height:  |  Size: 519 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="24" viewBox="0 0 8.467 6.35"><defs><linearGradient id="a"><stop offset="0" stop-opacity=".3"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="4.233" x2="4.233" y1="0" y2="6.35" gradientUnits="userSpaceOnUse"/></defs><path fill="url(#b)" d="M0 0H8.467V6.35H0z" paint-order="fill markers stroke"/></svg>

After

Width:  |  Height:  |  Size: 451 B