diff options
Diffstat (limited to 'scene/gui')
28 files changed, 361 insertions, 134 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index cf467ceafb..af6a99ca62 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -264,7 +264,7 @@ bool BaseButton::is_hovered() const { BaseButton::DrawMode BaseButton::get_draw_mode() const { if (status.disabled) { return DRAW_DISABLED; - }; + } if (!status.press_attempt && status.hovering) { if (status.pressed) { @@ -273,8 +273,7 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const { return DRAW_HOVER; } else { - /* determine if pressed or not */ - + // Determine if pressed or not. bool pressing; if (status.press_attempt) { pressing = (status.pressing_inside || keep_pressed_outside); @@ -291,8 +290,6 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const { return DRAW_NORMAL; } } - - return DRAW_NORMAL; } void BaseButton::set_toggle_mode(bool p_on) { @@ -469,7 +466,7 @@ void BaseButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "button_group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut_context", PROPERTY_HINT_RESOURCE_TYPE, "Node"), "set_shortcut_context", "get_shortcut_context"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut_context", PROPERTY_HINT_NODE_TYPE, "Node"), "set_shortcut_context", "get_shortcut_context"); BIND_ENUM_CONSTANT(DRAW_NORMAL); BIND_ENUM_CONSTANT(DRAW_PRESSED); diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index f6e0e4216d..8069ab465b 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -1216,30 +1216,39 @@ bool CodeEdit::is_drawing_executing_lines_gutter() const { } void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) { + bool shift_pressed = Input::get_singleton()->is_key_pressed(Key::SHIFT); + if (draw_breakpoints && breakpoint_icon.is_valid()) { bool hovering = p_region.has_point(get_local_mouse_pos()); bool breakpointed = is_line_breakpointed(p_line); - if (breakpointed || (hovering && !is_dragging_cursor())) { + if (breakpointed || (hovering && !is_dragging_cursor() && !shift_pressed)) { int padding = p_region.size.x / 6; Rect2 icon_region = p_region; icon_region.position += Point2(padding, padding); icon_region.size -= Point2(padding, padding) * 2; - // Darken icon when hovering & not yet breakpointed. - Color use_color = hovering && !breakpointed ? breakpoint_color.darkened(0.4) : breakpoint_color; + // Darken icon when hovering, shift not pressed & not yet breakpointed. + Color use_color = hovering && !breakpointed && !shift_pressed ? breakpoint_color.darkened(0.4) : breakpoint_color; breakpoint_icon->draw_rect(get_canvas_item(), icon_region, false, use_color); } } - if (draw_bookmarks && is_line_bookmarked(p_line) && bookmark_icon.is_valid()) { - int horizontal_padding = p_region.size.x / 2; - int vertical_padding = p_region.size.y / 4; + if (draw_bookmarks && bookmark_icon.is_valid()) { + bool hovering = p_region.has_point(get_local_mouse_pos()); + bool bookmarked = is_line_bookmarked(p_line); - Rect2 bookmark_region = p_region; - bookmark_region.position += Point2(horizontal_padding, 0); - bookmark_region.size -= Point2(horizontal_padding * 1.1, vertical_padding); - bookmark_icon->draw_rect(get_canvas_item(), bookmark_region, false, bookmark_color); + if (bookmarked || (hovering && !is_dragging_cursor() && shift_pressed)) { + int horizontal_padding = p_region.size.x / 2; + int vertical_padding = p_region.size.y / 4; + Rect2 icon_region = p_region; + icon_region.position += Point2(horizontal_padding, 0); + icon_region.size -= Point2(horizontal_padding * 1.1, vertical_padding); + + // Darken icon when hovering, shift pressed & not yet bookmarked. + Color use_color = hovering && !bookmarked && shift_pressed ? bookmark_color.darkened(0.4) : bookmark_color; + bookmark_icon->draw_rect(get_canvas_item(), icon_region, false, use_color); + } } if (draw_executing_lines && is_line_executing(p_line) && executing_line_icon.is_valid()) { @@ -2378,9 +2387,13 @@ int CodeEdit::_get_auto_brace_pair_close_at_pos(int p_line, int p_col) { /* Gutters */ void CodeEdit::_gutter_clicked(int p_line, int p_gutter) { + bool shift_pressed = Input::get_singleton()->is_key_pressed(Key::SHIFT); + if (p_gutter == main_gutter) { - if (draw_breakpoints) { + if (draw_breakpoints && !shift_pressed) { set_line_as_breakpoint(p_line, !is_line_breakpointed(p_line)); + } else if (draw_bookmarks && shift_pressed) { + set_line_as_bookmarked(p_line, !is_line_bookmarked(p_line)); } return; } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 4a1f2ab7c6..5751c54877 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -427,12 +427,15 @@ void ColorPicker::_html_submitted(const String &p_html) { return; } - float last_alpha = color.a; + Color previous_color = color; color = Color::html(p_html); if (!is_editing_alpha()) { - color.a = last_alpha; + color.a = previous_color.a; } + if (color == previous_color) { + return; + } if (!is_inside_tree()) { return; } diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 5512c0f1fd..3c29c37479 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -192,8 +192,8 @@ void Container::_notification(int p_what) { } } -TypedArray<String> Container::get_configuration_warnings() const { - TypedArray<String> warnings = Control::get_configuration_warnings(); +PackedStringArray Container::get_configuration_warnings() const { + PackedStringArray warnings = Control::get_configuration_warnings(); if (get_class() == "Container" && get_script().is_null()) { warnings.push_back(RTR("Container by itself serves no purpose unless a script configures its children placement behavior.\nIf you don't intend to add a script, use a plain Control node instead.")); diff --git a/scene/gui/container.h b/scene/gui/container.h index 9ec4ad3200..21bdb95186 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -63,7 +63,7 @@ public: virtual Vector<int> get_allowed_size_flags_horizontal() const; virtual Vector<int> get_allowed_size_flags_vertical() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; Container(); }; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 347fe9aa11..dc9294df6d 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -213,8 +213,8 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List } } -TypedArray<String> Control::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray Control::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (data.mouse_filter == MOUSE_FILTER_IGNORE && !data.tooltip.is_empty()) { warnings.push_back(RTR("The Hint Tooltip won't be displayed as the control's Mouse Filter is set to \"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\".")); @@ -2225,7 +2225,19 @@ void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, cons void Control::set_default_cursor_shape(CursorShape p_shape) { ERR_FAIL_INDEX(int(p_shape), CURSOR_MAX); + if (data.default_cursor == p_shape) { + return; + } data.default_cursor = p_shape; + + if (!is_inside_tree()) { + return; + } + if (!get_global_rect().has_point(get_global_mouse_position())) { + return; + } + + get_viewport()->get_base_window()->update_mouse_cursor_shape(); } Control::CursorShape Control::get_default_cursor_shape() const { diff --git a/scene/gui/control.h b/scene/gui/control.h index 38cafd835a..ee6443c81c 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -387,7 +387,7 @@ public: // Editor integration. virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; virtual bool is_text_field() const; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 57f27e299f..cf7f439aef 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -172,18 +172,20 @@ void FileDialog::shortcut_input(const Ref<InputEvent> &p_event) { void FileDialog::set_enable_multiple_selection(bool p_enable) { tree->set_select_mode(p_enable ? Tree::SELECT_MULTI : Tree::SELECT_SINGLE); -}; +} Vector<String> FileDialog::get_selected_files() const { Vector<String> list; TreeItem *item = tree->get_root(); - while ((item = tree->get_next_selected(item))) { + item = tree->get_next_selected(item); + while (item) { list.push_back(dir_access->get_current_dir().path_join(item->get_text(0))); - }; + item = tree->get_next_selected(item); + } return list; -}; +} void FileDialog::update_dir() { if (root_prefix.is_empty()) { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 5a0236268b..7295ab9e9d 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -190,8 +190,8 @@ void GraphEditMinimap::_adjust_graph_scroll(const Vector2 &p_offset) { ge->set_scroll_ofs(p_offset + graph_offset - camera_size / 2); } -TypedArray<String> GraphEdit::get_configuration_warnings() const { - TypedArray<String> warnings = Control::get_configuration_warnings(); +PackedStringArray GraphEdit::get_configuration_warnings() const { + PackedStringArray warnings = Control::get_configuration_warnings(); warnings.push_back(RTR("Please be aware that GraphEdit and GraphNode will undergo extensive refactoring in a future beta version involving compatibility-breaking API changes.")); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 0fe9e7c555..101087bdbd 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -287,7 +287,7 @@ protected: GDVIRTUAL4R(bool, _is_node_hover_valid, StringName, int, StringName, int); public: - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; Error connect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); bool is_node_connected(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 008109da65..357f2480bd 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -662,19 +662,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { pos.x = get_size().width - pos.x; } - int closest = -1; - - for (int i = 0; i < items.size(); i++) { - Rect2 rc = items[i].rect_cache; - if (i % current_columns == current_columns - 1) { - rc.size.width = get_size().width; //not right but works - } - - if (rc.has_point(pos)) { - closest = i; - break; - } - } + int closest = get_item_at_position(mb->get_position(), true); if (closest != -1 && (mb->get_button_index() == MouseButton::LEFT || (allow_rmb_select && mb->get_button_index() == MouseButton::RIGHT))) { int i = closest; @@ -1467,7 +1455,7 @@ int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const { for (int i = 0; i < items.size(); i++) { Rect2 rc = items[i].rect_cache; if (i % current_columns == current_columns - 1) { - rc.size.width = get_size().width - rc.position.x; //make sure you can still select the last item when clicking past the column + rc.size.width = get_size().width - rc.position.x; // Make sure you can still select the last item when clicking past the column. } if (rc.has_point(pos)) { diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp index d6bf84ea5a..75592a1b99 100644 --- a/scene/gui/menu_bar.cpp +++ b/scene/gui/menu_bar.cpp @@ -703,7 +703,7 @@ void MenuBar::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "start_index"), "set_start_index", "get_start_index"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "switch_on_hover"), "set_switch_on_hover", "is_switch_on_hover"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "prefer_global_menu"), "set_prefer_global_menu", "is_prefer_global_menu"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut_context", PROPERTY_HINT_RESOURCE_TYPE, "Node"), "set_shortcut_context", "get_shortcut_context"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut_context", PROPERTY_HINT_NODE_TYPE, "Node"), "set_shortcut_context", "get_shortcut_context"); ADD_GROUP("BiDi", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index d4a4efd578..10e13042a7 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1762,7 +1762,7 @@ void PopupMenu::clear() { void PopupMenu::_ref_shortcut(Ref<Shortcut> p_sc) { if (!shortcut_refcount.has(p_sc)) { shortcut_refcount[p_sc] = 1; - p_sc->connect("changed", callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw)); + p_sc->connect("changed", callable_mp(this, &PopupMenu::_shortcut_changed)); } else { shortcut_refcount[p_sc] += 1; } @@ -1772,11 +1772,18 @@ void PopupMenu::_unref_shortcut(Ref<Shortcut> p_sc) { ERR_FAIL_COND(!shortcut_refcount.has(p_sc)); shortcut_refcount[p_sc]--; if (shortcut_refcount[p_sc] == 0) { - p_sc->disconnect("changed", callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw)); + p_sc->disconnect("changed", callable_mp(this, &PopupMenu::_shortcut_changed)); shortcut_refcount.erase(p_sc); } } +void PopupMenu::_shortcut_changed() { + for (int i = 0; i < items.size(); i++) { + items.write[i].dirty = true; + } + control->queue_redraw(); +} + // Hide on item selection determines whether or not the popup will close after item selection void PopupMenu::set_hide_on_item_selection(bool p_enabled) { hide_on_item_selection = p_enabled; diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index ad7909842e..89d3904456 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -121,6 +121,8 @@ class PopupMenu : public Popup { void _ref_shortcut(Ref<Shortcut> p_sc); void _unref_shortcut(Ref<Shortcut> p_sc); + void _shortcut_changed(); + bool allow_search = true; uint64_t search_time_msec = 0; String search_string = ""; diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index 1eb412abaf..2d2b3e413d 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -30,8 +30,8 @@ #include "range.h" -TypedArray<String> Range::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray Range::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (shared->exp_ratio && shared->min <= 0) { warnings.push_back(RTR("If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0.")); diff --git a/scene/gui/range.h b/scene/gui/range.h index 87bd0d88af..19452243cf 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -100,7 +100,7 @@ public: void share(Range *p_range); void unshare(); - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; Range(); ~Range(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 3a238e9edd..7ea46a0b4f 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -52,7 +52,7 @@ RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) co } else if (p_item->E->next()) { return p_item->E->next()->get(); } else { - //go up until something with a next is found + // Go up until something with a next is found. while (p_item->parent && !p_item->E->next()) { p_item = p_item->parent; } @@ -72,7 +72,7 @@ RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) co } else if (p_item->E->next()) { return p_item->E->next()->get(); } else { - //go up until something with a next is found + // Go up until something with a next is found. while (p_item->type != ITEM_FRAME && !p_item->E->next()) { p_item = p_item->parent; } @@ -84,8 +84,6 @@ RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) co } } } - - return nullptr; } RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) const { @@ -97,7 +95,7 @@ RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) co } else if (p_item->E->prev()) { return p_item->E->prev()->get(); } else { - //go back until something with a prev is found + // Go back until something with a prev is found. while (p_item->parent && !p_item->E->prev()) { p_item = p_item->parent; } @@ -117,7 +115,7 @@ RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) co } else if (p_item->E->prev()) { return p_item->E->prev()->get(); } else { - //go back until something with a prev is found + // Go back until something with a prev is found. while (p_item->type != ITEM_FRAME && !p_item->E->prev()) { p_item = p_item->parent; } @@ -129,8 +127,6 @@ RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) co } } } - - return nullptr; } Rect2 RichTextLabel::_get_text_rect() { @@ -965,17 +961,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o uint32_t gl = glyphs[i].index; uint16_t gl_fl = glyphs[i].flags; uint8_t gl_cn = glyphs[i].count; - bool cprev = false; + bool cprev_cluster = false; + bool cprev_conn = false; if (gl_cn == 0) { // Parts of the same cluster, always connected. - cprev = true; + cprev_cluster = true; } if (gl_fl & TextServer::GRAPHEME_IS_RTL) { // Check if previous grapheme cluster is connected. if (i > 0 && (glyphs[i - 1].flags & TextServer::GRAPHEME_IS_CONNECTED)) { - cprev = true; + cprev_conn = true; } } else { if (glyphs[i].flags & TextServer::GRAPHEME_IS_CONNECTED) { - cprev = true; + cprev_conn = true; } } @@ -994,6 +991,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o for (int j = 0; j < fx_stack.size(); j++) { ItemFX *item_fx = fx_stack[j]; + bool cn = cprev_cluster || (cprev_conn && item_fx->connected); + if (item_fx->type == ITEM_CUSTOMFX && custom_fx_ok) { ItemCustomFX *item_custom = static_cast<ItemCustomFX *>(item_fx); @@ -1024,7 +1023,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } else if (item_fx->type == ITEM_SHAKE) { ItemShake *item_shake = static_cast<ItemShake *>(item_fx); - if (!cprev) { + if (!cn) { uint64_t char_current_rand = item_shake->offset_random(glyphs[i].start); uint64_t char_previous_rand = item_shake->offset_previous_random(glyphs[i].start); uint64_t max_rand = 2147483647; @@ -1038,7 +1037,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } else if (item_fx->type == ITEM_WAVE) { ItemWave *item_wave = static_cast<ItemWave *>(item_fx); - if (!cprev) { + if (!cn) { double value = Math::sin(item_wave->frequency * item_wave->elapsed_time + ((p_ofs.x + gloff.x) / 50)) * (item_wave->amplitude / 10.0f); item_wave->prev_off = Point2(0, 1) * value; } @@ -1046,7 +1045,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } else if (item_fx->type == ITEM_TORNADO) { ItemTornado *item_tornado = static_cast<ItemTornado *>(item_fx); - if (!cprev) { + if (!cn) { double torn_x = Math::sin(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + gloff.x) / 50)) * (item_tornado->radius); double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + gloff.x) / 50)) * (item_tornado->radius); item_tornado->prev_off = Point2(torn_x, torn_y); @@ -1181,17 +1180,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o uint32_t gl = glyphs[i].index; uint16_t gl_fl = glyphs[i].flags; uint8_t gl_cn = glyphs[i].count; - bool cprev = false; + bool cprev_cluster = false; + bool cprev_conn = false; if (gl_cn == 0) { // Parts of the same grapheme cluster, always connected. - cprev = true; + cprev_cluster = true; } if (gl_fl & TextServer::GRAPHEME_IS_RTL) { // Check if previous grapheme cluster is connected. if (i > 0 && (glyphs[i - 1].flags & TextServer::GRAPHEME_IS_CONNECTED)) { - cprev = true; + cprev_conn = true; } } else { if (glyphs[i].flags & TextServer::GRAPHEME_IS_CONNECTED) { - cprev = true; + cprev_conn = true; } } @@ -1209,6 +1209,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o for (int j = 0; j < fx_stack.size(); j++) { ItemFX *item_fx = fx_stack[j]; + bool cn = cprev_cluster || (cprev_conn && item_fx->connected); + if (item_fx->type == ITEM_CUSTOMFX && custom_fx_ok) { ItemCustomFX *item_custom = static_cast<ItemCustomFX *>(item_fx); @@ -1239,7 +1241,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } else if (item_fx->type == ITEM_SHAKE) { ItemShake *item_shake = static_cast<ItemShake *>(item_fx); - if (!cprev) { + if (!cn) { uint64_t char_current_rand = item_shake->offset_random(glyphs[i].start); uint64_t char_previous_rand = item_shake->offset_previous_random(glyphs[i].start); uint64_t max_rand = 2147483647; @@ -1253,7 +1255,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } else if (item_fx->type == ITEM_WAVE) { ItemWave *item_wave = static_cast<ItemWave *>(item_fx); - if (!cprev) { + if (!cn) { double value = Math::sin(item_wave->frequency * item_wave->elapsed_time + ((p_ofs.x + off.x) / 50)) * (item_wave->amplitude / 10.0f); item_wave->prev_off = Point2(0, 1) * value; } @@ -1261,7 +1263,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } else if (item_fx->type == ITEM_TORNADO) { ItemTornado *item_tornado = static_cast<ItemTornado *>(item_fx); - if (!cprev) { + if (!cn) { double torn_x = Math::sin(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + off.x) / 50)) * (item_tornado->radius); double torn_y = Math::cos(item_tornado->frequency * item_tornado->elapsed_time + ((p_ofs.x + off.x) / 50)) * (item_tornado->radius); item_tornado->prev_off = Point2(torn_x, torn_y); @@ -2190,24 +2192,69 @@ RichTextLabel::ItemFont *RichTextLabel::_find_font(Item *p_item) { ItemFont *fi = static_cast<ItemFont *>(fontitem); switch (fi->def_font) { case NORMAL_FONT: { - fi->font = theme_cache.normal_font; - fi->font_size = theme_cache.normal_font_size; + if (fi->variation) { + Ref<FontVariation> fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.normal_font); + } + } else { + fi->font = theme_cache.normal_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.normal_font_size; + } } break; case BOLD_FONT: { - fi->font = theme_cache.bold_font; - fi->font_size = theme_cache.bold_font_size; + if (fi->variation) { + Ref<FontVariation> fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.bold_font); + } + } else { + fi->font = theme_cache.bold_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.bold_font_size; + } } break; case ITALICS_FONT: { - fi->font = theme_cache.italics_font; - fi->font_size = theme_cache.italics_font_size; + if (fi->variation) { + Ref<FontVariation> fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.italics_font); + } + } else { + fi->font = theme_cache.italics_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.italics_font_size; + } } break; case BOLD_ITALICS_FONT: { - fi->font = theme_cache.bold_italics_font; - fi->font_size = theme_cache.bold_italics_font_size; + if (fi->variation) { + Ref<FontVariation> fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.bold_italics_font); + } + } else { + fi->font = theme_cache.bold_italics_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.bold_italics_font_size; + } } break; case MONO_FONT: { - fi->font = theme_cache.mono_font; - fi->font_size = theme_cache.mono_font_size; + if (fi->variation) { + Ref<FontVariation> fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.mono_font); + } + } else { + fi->font = theme_cache.mono_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.mono_font_size; + } } break; default: { } break; @@ -3028,14 +3075,30 @@ void RichTextLabel::push_dropcap(const String &p_string, const Ref<Font> &p_font _add_item(item, false); } -void RichTextLabel::_push_def_font(DefaultFont p_font) { +void RichTextLabel::_push_def_font_var(DefaultFont p_def_font, const Ref<Font> &p_font, int p_size) { + _stop_thread(); + MutexLock data_lock(data_mutex); + + ERR_FAIL_COND(current->type == ITEM_TABLE); + ItemFont *item = memnew(ItemFont); + + item->def_font = p_def_font; + item->variation = true; + item->font = p_font; + item->font_size = p_size; + item->def_size = (p_size <= 0); + _add_item(item, true); +} + +void RichTextLabel::_push_def_font(DefaultFont p_def_font) { _stop_thread(); MutexLock data_lock(data_mutex); ERR_FAIL_COND(current->type == ITEM_TABLE); ItemFont *item = memnew(ItemFont); - item->def_font = p_font; + item->def_font = p_def_font; + item->def_size = true; _add_item(item, true); } @@ -3236,33 +3299,36 @@ void RichTextLabel::push_fade(int p_start_index, int p_length) { _add_item(item, true); } -void RichTextLabel::push_shake(int p_strength = 10, float p_rate = 24.0f) { +void RichTextLabel::push_shake(int p_strength = 10, float p_rate = 24.0f, bool p_connected = true) { _stop_thread(); MutexLock data_lock(data_mutex); ItemShake *item = memnew(ItemShake); item->strength = p_strength; item->rate = p_rate; + item->connected = p_connected; _add_item(item, true); } -void RichTextLabel::push_wave(float p_frequency = 1.0f, float p_amplitude = 10.0f) { +void RichTextLabel::push_wave(float p_frequency = 1.0f, float p_amplitude = 10.0f, bool p_connected = true) { _stop_thread(); MutexLock data_lock(data_mutex); ItemWave *item = memnew(ItemWave); item->frequency = p_frequency; item->amplitude = p_amplitude; + item->connected = p_connected; _add_item(item, true); } -void RichTextLabel::push_tornado(float p_frequency = 1.0f, float p_radius = 10.0f) { +void RichTextLabel::push_tornado(float p_frequency = 1.0f, float p_radius = 10.0f, bool p_connected = true) { _stop_thread(); MutexLock data_lock(data_mutex); ItemTornado *item = memnew(ItemTornado); item->frequency = p_frequency; item->radius = p_radius; + item->connected = p_connected; _add_item(item, true); } @@ -4113,24 +4179,21 @@ void RichTextLabel::append_text(const String &p_bbcode) { pos = brk_end + 1; tag_stack.push_front("font_size"); - } else if (tag.begins_with("opentype_features=")) { - String fnt_ftr = tag.substr(18, tag.length()); + } else if (tag.begins_with("opentype_features=") || tag.begins_with("otf=")) { + int value_pos = tag.find("="); + String fnt_ftr = tag.substr(value_pos + 1); Vector<String> subtag = fnt_ftr.split(","); if (subtag.size() > 0) { Ref<Font> font = theme_cache.normal_font; - int font_size = 0; + DefaultFont def_font = NORMAL_FONT; + ItemFont *font_it = _find_font(current); if (font_it) { if (font_it->font.is_valid()) { font = font_it->font; - } - if (font_it->font_size > 0) { - font_size = font_it->font_size; + def_font = font_it->def_font; } } - Ref<FontVariation> fc; - fc.instantiate(); - fc->set_base_font(font); Dictionary features; for (int i = 0; i < subtag.size(); i++) { Vector<String> subtag_a = subtag[i].split("="); @@ -4140,11 +4203,21 @@ void RichTextLabel::append_text(const String &p_bbcode) { features[TS->name_to_tag(subtag_a[0])] = 1; } } + + Ref<FontVariation> fc; + fc.instantiate(); + + fc->set_base_font(font); fc->set_opentype_features(features); - push_font(fc, font_size); + + if (def_font != CUSTOM_FONT) { + _push_def_font_var(def_font, fc); + } else { + push_font(fc); + } } pos = brk_end + 1; - tag_stack.push_front("opentype_features"); + tag_stack.push_front(tag.substr(0, value_pos)); } else if (tag.begins_with("font=")) { String fnt = tag.substr(5, tag.length()); @@ -4160,9 +4233,21 @@ void RichTextLabel::append_text(const String &p_bbcode) { } else if (tag.begins_with("font ")) { Vector<String> subtag = tag.substr(2, tag.length()).split(" "); + Ref<Font> font = theme_cache.normal_font; + DefaultFont def_font = NORMAL_FONT; + + ItemFont *font_it = _find_font(current); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + def_font = font_it->def_font; + } + } + Ref<FontVariation> fc; fc.instantiate(); - int fnt_size = 0; + + int fnt_size = -1; for (int i = 1; i < subtag.size(); i++) { Vector<String> subtag_a = subtag[i].split("=", true, 2); if (subtag_a.size() == 2) { @@ -4170,7 +4255,8 @@ void RichTextLabel::append_text(const String &p_bbcode) { String fnt = subtag_a[1]; Ref<Font> font_data = ResourceLoader::load(fnt, "Font"); if (font_data.is_valid()) { - fc->set_base_font(font_data); + font = font_data; + def_font = CUSTOM_FONT; } } else if (subtag_a[0] == "size" || subtag_a[0] == "s") { fnt_size = subtag_a[1].to_int(); @@ -4224,7 +4310,14 @@ void RichTextLabel::append_text(const String &p_bbcode) { } } } - push_font(fc, fnt_size); + fc->set_base_font(font); + + if (def_font != CUSTOM_FONT) { + _push_def_font_var(def_font, fc, fnt_size); + } else { + push_font(fc, fnt_size); + } + pos = brk_end + 1; tag_stack.push_front("font"); @@ -4265,7 +4358,13 @@ void RichTextLabel::append_text(const String &p_bbcode) { rate = rate_option->value.to_float(); } - push_shake(strength, rate); + bool connected = true; + OptionMap::Iterator connected_option = bbcode_options.find("connected"); + if (connected_option) { + connected = connected_option->value.to_int(); + } + + push_shake(strength, rate, connected); pos = brk_end + 1; tag_stack.push_front("shake"); set_process_internal(true); @@ -4282,7 +4381,13 @@ void RichTextLabel::append_text(const String &p_bbcode) { period = period_option->value.to_float(); } - push_wave(period, amplitude); + bool connected = true; + OptionMap::Iterator connected_option = bbcode_options.find("connected"); + if (connected_option) { + connected = connected_option->value.to_int(); + } + + push_wave(period, amplitude, connected); pos = brk_end + 1; tag_stack.push_front("wave"); set_process_internal(true); @@ -4299,7 +4404,13 @@ void RichTextLabel::append_text(const String &p_bbcode) { frequency = frequency_option->value.to_float(); } - push_tornado(frequency, radius); + bool connected = true; + OptionMap::Iterator connected_option = bbcode_options.find("connected"); + if (connected_option) { + connected = connected_option->value.to_int(); + } + + push_tornado(frequency, radius, connected); pos = brk_end + 1; tag_stack.push_front("tornado"); set_process_internal(true); @@ -4676,7 +4787,10 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p queue_redraw(); return true; } - p_search_previous ? current_line-- : current_line++; + + if (current_line != ending_line) { + p_search_previous ? current_line-- : current_line++; + } } if (p_from_selection && selection.active) { diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 2a5ec4b5d5..71123602ad 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -189,6 +189,8 @@ private: struct ItemFont : public Item { DefaultFont def_font = CUSTOM_FONT; Ref<Font> font; + bool variation = false; + bool def_size = false; int font_size = 0; ItemFont() { type = ITEM_FONT; } }; @@ -282,6 +284,7 @@ private: struct ItemFX : public Item { double elapsed_time = 0.f; + bool connected = true; }; struct ItemShake : public ItemFX { @@ -570,7 +573,8 @@ public: void add_newline(); bool remove_line(const int p_line); void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0)); - void _push_def_font(DefaultFont p_font); + void _push_def_font(DefaultFont p_def_font); + void _push_def_font_var(DefaultFont p_def_font, const Ref<Font> &p_font, int p_size = -1); void push_font(const Ref<Font> &p_font, int p_size = 0); void push_font_size(int p_font_size); void push_outline_size(int p_font_size); @@ -590,9 +594,9 @@ public: void push_hint(const String &p_string); void push_table(int p_columns, InlineAlignment p_alignment = INLINE_ALIGNMENT_TOP); void push_fade(int p_start_index, int p_length); - void push_shake(int p_strength, float p_rate); - void push_wave(float p_frequency, float p_amplitude); - void push_tornado(float p_frequency, float p_radius); + void push_shake(int p_strength, float p_rate, bool p_connected); + void push_wave(float p_frequency, float p_amplitude, bool p_connected); + void push_tornado(float p_frequency, float p_radius, bool p_connected); void push_rainbow(float p_saturation, float p_value, float p_frequency); void push_bgcolor(const Color &p_color); void push_fgcolor(const Color &p_color); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index c12ac115b7..761072c5bc 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -501,8 +501,8 @@ void ScrollContainer::set_follow_focus(bool p_follow) { follow_focus = p_follow; } -TypedArray<String> ScrollContainer::get_configuration_warnings() const { - TypedArray<String> warnings = Container::get_configuration_warnings(); +PackedStringArray ScrollContainer::get_configuration_warnings() const { + PackedStringArray warnings = Container::get_configuration_warnings(); int found = 0; diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index f4899846f4..0079358ef7 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -114,7 +114,7 @@ public: VScrollBar *get_v_scroll_bar(); void ensure_control_visible(Control *p_control); - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; ScrollContainer(); }; diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp index 88e68ec763..3ad84cbc6d 100644 --- a/scene/gui/subviewport_container.cpp +++ b/scene/gui/subviewport_container.cpp @@ -227,8 +227,8 @@ void SubViewportContainer::unhandled_input(const Ref<InputEvent> &p_event) { } } -TypedArray<String> SubViewportContainer::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray SubViewportContainer::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); bool has_viewport = false; for (int i = 0; i < get_child_count(); i++) { diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h index 5b488fb79e..63a58b5f07 100644 --- a/scene/gui/subviewport_container.h +++ b/scene/gui/subviewport_container.h @@ -58,7 +58,7 @@ public: virtual Vector<int> get_allowed_size_flags_horizontal() const override; virtual Vector<int> get_allowed_size_flags_vertical() const override; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; SubViewportContainer(); }; diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 1df698a108..ab4808d312 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -519,12 +519,12 @@ void TabContainer::_refresh_tab_names() { } void TabContainer::add_child_notify(Node *p_child) { + Container::add_child_notify(p_child); + if (p_child == tab_bar) { return; } - Container::add_child_notify(p_child); - Control *c = Object::cast_to<Control>(p_child); if (!c || c->is_set_as_top_level()) { return; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 318447ecd8..38302136d6 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1201,13 +1201,14 @@ void TextEdit::_notification(int p_what) { current_color.a = font_readonly_color.a; } } + Color gl_color = current_color; if (selection.active && line >= selection.from_line && line <= selection.to_line) { // Selection int sel_from = (line > selection.from_line) ? TS->shaped_text_get_range(rid).x : selection.from_column; int sel_to = (line < selection.to_line) ? TS->shaped_text_get_range(rid).y : selection.to_column; if (glyphs[j].start >= sel_from && glyphs[j].end <= sel_to && override_selected_font_color) { - current_color = font_selected_color; + gl_color = font_selected_color; } } @@ -1217,29 +1218,29 @@ void TextEdit::_notification(int p_what) { if ((brace_open_match_line == line && brace_open_match_column == glyphs[j].start) || (caret.column == glyphs[j].start && caret.line == line && caret_wrap_index == line_wrap_index && (brace_open_matching || brace_open_mismatch))) { if (brace_open_mismatch) { - current_color = brace_mismatch_color; + gl_color = brace_mismatch_color; } Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, MAX(font->get_underline_thickness(font_size) * get_theme_default_base_scale(), 1)); - draw_rect(rect, current_color); + draw_rect(rect, gl_color); } if ((brace_close_match_line == line && brace_close_match_column == glyphs[j].start) || (caret.column == glyphs[j].start + 1 && caret.line == line && caret_wrap_index == line_wrap_index && (brace_close_matching || brace_close_mismatch))) { if (brace_close_mismatch) { - current_color = brace_mismatch_color; + gl_color = brace_mismatch_color; } Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, MAX(font->get_underline_thickness(font_size) * get_theme_default_base_scale(), 1)); - draw_rect(rect, current_color); + draw_rect(rect, gl_color); } } if (draw_tabs && ((glyphs[j].flags & TextServer::GRAPHEME_IS_TAB) == TextServer::GRAPHEME_IS_TAB)) { int yofs = (text_height - tab_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); - tab_icon->draw(ci, Point2(char_pos, ofs_y + yofs), current_color); + tab_icon->draw(ci, Point2(char_pos, ofs_y + yofs), gl_color); } else if (draw_spaces && ((glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE)) { int yofs = (text_height - space_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); int xofs = (glyphs[j].advance * glyphs[j].repeat - space_icon->get_width()) / 2; - space_icon->draw(ci, Point2(char_pos + xofs, ofs_y + yofs), current_color); + space_icon->draw(ci, Point2(char_pos + xofs, ofs_y + yofs), gl_color); } } @@ -1247,10 +1248,10 @@ void TextEdit::_notification(int p_what) { for (int k = 0; k < glyphs[j].repeat; k++) { if (!clipped && (char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) { if (glyphs[j].font_rid != RID()) { - TS->font_draw_glyph(glyphs[j].font_rid, ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, current_color); + TS->font_draw_glyph(glyphs[j].font_rid, ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, gl_color); had_glyphs_drawn = true; } else if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { - TS->draw_hex_code_box(ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, current_color); + TS->draw_hex_code_box(ci, glyphs[j].font_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, gl_color); had_glyphs_drawn = true; } } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 237c78407b..f82a853e56 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -563,6 +563,57 @@ bool TreeItem::is_collapsed() { return collapsed; } +void TreeItem::set_collapsed_recursive(bool p_collapsed) { + if (!tree) { + return; + } + + set_collapsed(p_collapsed); + + TreeItem *child = get_first_child(); + while (child) { + child->set_collapsed_recursive(p_collapsed); + child = child->get_next(); + } +} + +bool TreeItem::_is_any_collapsed(bool p_only_visible) { + TreeItem *child = get_first_child(); + + // Check on children directly first (avoid recursing if possible). + while (child) { + if (child->get_first_child() && child->is_collapsed() && (!p_only_visible || (child->is_visible() && child->get_visible_child_count()))) { + return true; + } + child = child->get_next(); + } + + child = get_first_child(); + + // Otherwise recurse on children. + while (child) { + if (child->get_first_child() && (!p_only_visible || (child->is_visible() && child->get_visible_child_count())) && child->_is_any_collapsed(p_only_visible)) { + return true; + } + child = child->get_next(); + } + + return false; +} + +bool TreeItem::is_any_collapsed(bool p_only_visible) { + if (p_only_visible && !is_visible()) { + return false; + } + + // Collapsed if this is collapsed and it has children (only considers visible if only visible is set). + if (is_collapsed() && get_first_child() && (!p_only_visible || get_visible_child_count())) { + return true; + } + + return _is_any_collapsed(p_only_visible); +} + void TreeItem::set_visible(bool p_visible) { if (visible == p_visible) { return; @@ -1406,6 +1457,9 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collapsed", "enable"), &TreeItem::set_collapsed); ClassDB::bind_method(D_METHOD("is_collapsed"), &TreeItem::is_collapsed); + ClassDB::bind_method(D_METHOD("set_collapsed_recursive", "enable"), &TreeItem::set_collapsed_recursive); + ClassDB::bind_method(D_METHOD("is_any_collapsed", "only_visible"), &TreeItem::is_any_collapsed, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("set_visible", "enable"), &TreeItem::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &TreeItem::is_visible); @@ -2572,7 +2626,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int } if (!p_item->disable_folding && !hide_folding && p_item->first_child && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + theme_cache.item_margin))) { - p_item->set_collapsed(!p_item->is_collapsed()); + if (enable_recursive_folding && p_mod->is_shift_pressed()) { + p_item->set_collapsed_recursive(!p_item->is_collapsed()); + } else { + p_item->set_collapsed(!p_item->is_collapsed()); + } return -1; } @@ -2623,7 +2681,11 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int } if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_first_child()) { - p_item->set_collapsed(!p_item->is_collapsed()); + if (enable_recursive_folding && p_mod->is_shift_pressed()) { + p_item->set_collapsed_recursive(!p_item->is_collapsed()); + } else { + p_item->set_collapsed(!p_item->is_collapsed()); + } return -1; //collapse/uncollapse because nothing can be done with item } @@ -5026,6 +5088,14 @@ bool Tree::is_folding_hidden() const { return hide_folding; } +void Tree::set_enable_recursive_folding(bool p_enable) { + enable_recursive_folding = p_enable; +} + +bool Tree::is_recursive_folding_enabled() const { + return enable_recursive_folding; +} + void Tree::set_drop_mode_flags(int p_flags) { if (drop_mode_flags == p_flags) { return; @@ -5129,6 +5199,9 @@ void Tree::_bind_methods() { 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); + 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_drop_mode_flags", "flags"), &Tree::set_drop_mode_flags); ClassDB::bind_method(D_METHOD("get_drop_mode_flags"), &Tree::get_drop_mode_flags); @@ -5143,6 +5216,7 @@ void Tree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select"); 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, "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"); diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 450943c048..f994a5cec1 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -173,6 +173,8 @@ private: } } + bool _is_any_collapsed(bool p_only_visible); + protected: static void _bind_methods(); @@ -272,6 +274,9 @@ public: void set_collapsed(bool p_collapsed); bool is_collapsed(); + void set_collapsed_recursive(bool p_collapsed); + bool is_any_collapsed(bool p_only_visible = false); + void set_visible(bool p_visible); bool is_visible(); @@ -613,6 +618,8 @@ private: bool hide_folding = false; + bool enable_recursive_folding = true; + int _count_selected_items(TreeItem *p_from) const; bool _is_branch_selected(TreeItem *p_from) const; bool _is_sibling_branch_selected(TreeItem *p_from) const; @@ -712,6 +719,9 @@ public: void set_hide_folding(bool p_hide); bool is_folding_hidden() const; + void set_enable_recursive_folding(bool p_enable); + bool is_recursive_folding_enabled() const; + void set_drop_mode_flags(int p_flags); int get_drop_mode_flags() const; diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 1e03ed6e76..0ea49b1645 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -381,14 +381,14 @@ String VideoStreamPlayer::get_stream_name() const { return stream->get_name(); } -float VideoStreamPlayer::get_stream_position() const { +double VideoStreamPlayer::get_stream_position() const { if (playback.is_null()) { return 0; } return playback->get_playback_position(); } -void VideoStreamPlayer::set_stream_position(float p_position) { +void VideoStreamPlayer::set_stream_position(double p_position) { if (playback.is_valid()) { playback->seek(p_position); } diff --git a/scene/gui/video_stream_player.h b/scene/gui/video_stream_player.h index 9974eb8488..b1ba8a65d7 100644 --- a/scene/gui/video_stream_player.h +++ b/scene/gui/video_stream_player.h @@ -105,8 +105,8 @@ public: float get_volume_db() const; String get_stream_name() const; - float get_stream_position() const; - void set_stream_position(float p_position); + double get_stream_position() const; + void set_stream_position(double p_position); void set_autoplay(bool p_enable); bool has_autoplay() const; |