diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/base_button.cpp | 1 | ||||
-rw-r--r-- | scene/gui/button.cpp | 27 | ||||
-rw-r--r-- | scene/gui/button.h | 5 | ||||
-rw-r--r-- | scene/gui/code_edit.cpp | 2 | ||||
-rw-r--r-- | scene/gui/code_edit.h | 6 | ||||
-rw-r--r-- | scene/gui/color_mode.h | 4 | ||||
-rw-r--r-- | scene/gui/color_picker.cpp | 36 | ||||
-rw-r--r-- | scene/gui/color_picker.h | 1 | ||||
-rw-r--r-- | scene/gui/control.cpp | 50 | ||||
-rw-r--r-- | scene/gui/control.h | 18 | ||||
-rw-r--r-- | scene/gui/file_dialog.cpp | 46 | ||||
-rw-r--r-- | scene/gui/file_dialog.h | 4 | ||||
-rw-r--r-- | scene/gui/graph_edit.cpp | 18 | ||||
-rw-r--r-- | scene/gui/label.cpp | 344 | ||||
-rw-r--r-- | scene/gui/label.h | 5 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 2 | ||||
-rw-r--r-- | scene/gui/option_button.cpp | 6 | ||||
-rw-r--r-- | scene/gui/range.h | 2 | ||||
-rw-r--r-- | scene/gui/rich_text_effect.h | 20 | ||||
-rw-r--r-- | scene/gui/scroll_container.cpp | 6 | ||||
-rw-r--r-- | scene/gui/spin_box.cpp | 38 | ||||
-rw-r--r-- | scene/gui/spin_box.h | 2 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 6 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 8 | ||||
-rw-r--r-- | scene/gui/texture_button.cpp | 4 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 83 | ||||
-rw-r--r-- | scene/gui/video_stream_player.cpp | 8 |
27 files changed, 362 insertions, 390 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 34f5095493..bd4770bcc3 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -205,6 +205,7 @@ void BaseButton::set_disabled(bool p_disabled) { status.pressing_inside = false; } queue_redraw(); + update_minimum_size(); } bool BaseButton::is_disabled() const { diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 0a5f2ec6c7..3e593a8372 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -296,19 +296,12 @@ void Button::_notification(int p_what) { } } break; case DRAW_HOVER_PRESSED: { - // Edge case for CheckButton and CheckBox. - if (has_theme_stylebox("hover_pressed")) { - if (has_theme_color(SNAME("font_hover_pressed_color"))) { - font_color = theme_cache.font_hover_pressed_color; - } - if (has_theme_color(SNAME("icon_hover_pressed_color"))) { - icon_modulate_color = theme_cache.icon_hover_pressed_color; - } - - break; + font_color = theme_cache.font_hover_pressed_color; + if (has_theme_color(SNAME("icon_hover_pressed_color"))) { + icon_modulate_color = theme_cache.icon_hover_pressed_color; } - } - [[fallthrough]]; + + } break; case DRAW_PRESSED: { if (has_theme_color(SNAME("font_pressed_color"))) { font_color = theme_cache.font_pressed_color; @@ -568,6 +561,7 @@ void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) { } autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES; p_paragraph->set_break_flags(autowrap_flags); + p_paragraph->set_line_spacing(theme_cache.line_spacing); if (text_direction == Control::TEXT_DIRECTION_INHERITED) { p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); @@ -649,7 +643,7 @@ String Button::get_language() const { return language; } -void Button::set_icon(const Ref<Texture2D> &p_icon) { +void Button::set_button_icon(const Ref<Texture2D> &p_icon) { if (icon == p_icon) { return; } @@ -673,7 +667,7 @@ void Button::_texture_changed() { update_minimum_size(); } -Ref<Texture2D> Button::get_icon() const { +Ref<Texture2D> Button::get_button_icon() const { return icon; } @@ -769,8 +763,8 @@ void Button::_bind_methods() { ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction); ClassDB::bind_method(D_METHOD("set_language", "language"), &Button::set_language); ClassDB::bind_method(D_METHOD("get_language"), &Button::get_language); - ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon); - ClassDB::bind_method(D_METHOD("get_button_icon"), &Button::get_icon); + ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_button_icon); + ClassDB::bind_method(D_METHOD("get_button_icon"), &Button::get_button_icon); ClassDB::bind_method(D_METHOD("set_flat", "enabled"), &Button::set_flat); ClassDB::bind_method(D_METHOD("is_flat"), &Button::is_flat); ClassDB::bind_method(D_METHOD("set_clip_text", "enabled"), &Button::set_clip_text); @@ -840,6 +834,7 @@ void Button::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, icon_max_width); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, align_to_largest_stylebox); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, line_spacing); } Button::Button(const String &p_text) { diff --git a/scene/gui/button.h b/scene/gui/button.h index 5f4429bc1d..686d4806db 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -100,6 +100,7 @@ private: int h_separation = 0; int icon_max_width = 0; + int line_spacing = 0; } theme_cache; void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = ""); @@ -137,8 +138,8 @@ public: void set_language(const String &p_language); String get_language() const; - void set_icon(const Ref<Texture2D> &p_icon); - Ref<Texture2D> get_icon() const; + void set_button_icon(const Ref<Texture2D> &p_icon); + Ref<Texture2D> get_button_icon() const; void set_expand_icon(bool p_enabled); bool is_expand_icon() const; diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 7346c9dcd3..9d7e2496a2 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -1481,7 +1481,7 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 if (E) { text_rid = E->value; } else { - String fc = String::num(p_line + 1).lpad(line_number_digits, line_number_padding); + String fc = String::num_int64(p_line + 1).lpad(line_number_digits, line_number_padding); if (is_localizing_numeral_system()) { fc = TS->format_number(fc); } diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h index ab443e95e1..2cd34ec99f 100644 --- a/scene/gui/code_edit.h +++ b/scene/gui/code_edit.h @@ -251,13 +251,13 @@ private: Ref<Texture2D> completion_color_bg; Color breakpoint_color = Color(1, 1, 1); - Ref<Texture2D> breakpoint_icon = Ref<Texture2D>(); + Ref<Texture2D> breakpoint_icon; Color bookmark_color = Color(1, 1, 1); - Ref<Texture2D> bookmark_icon = Ref<Texture2D>(); + Ref<Texture2D> bookmark_icon; Color executing_line_color = Color(1, 1, 1); - Ref<Texture2D> executing_line_icon = Ref<Texture2D>(); + Ref<Texture2D> executing_line_icon; Color line_number_color = Color(1, 1, 1); diff --git a/scene/gui/color_mode.h b/scene/gui/color_mode.h index 94193ccf74..0abc90bb44 100644 --- a/scene/gui/color_mode.h +++ b/scene/gui/color_mode.h @@ -41,9 +41,9 @@ public: virtual String get_name() const = 0; - virtual int get_slider_count() const { return 3; }; + virtual int get_slider_count() const { return 3; } virtual float get_slider_step() const = 0; - virtual float get_spinbox_arrow_step() const { return get_slider_step(); }; + virtual float get_spinbox_arrow_step() const { return get_slider_step(); } virtual String get_slider_label(int idx) const = 0; virtual float get_slider_max(int idx) const = 0; virtual float get_slider_value(int idx) const = 0; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index e92f979c32..997120ff25 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -80,10 +80,10 @@ void ColorPicker::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - btn_pick->set_icon(theme_cache.screen_picker); + btn_pick->set_button_icon(theme_cache.screen_picker); _update_drop_down_arrow(btn_preset->is_pressed(), btn_preset); _update_drop_down_arrow(btn_recent_preset->is_pressed(), btn_recent_preset); - btn_add_preset->set_icon(theme_cache.add_preset); + btn_add_preset->set_button_icon(theme_cache.add_preset); btn_pick->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); btn_shape->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); @@ -116,7 +116,7 @@ void ColorPicker::_notification(int p_what) { shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_OKHSL_CIRCLE), theme_cache.shape_circle); if (current_shape != SHAPE_NONE) { - btn_shape->set_icon(shape_popup->get_item_icon(current_shape)); + btn_shape->set_button_icon(shape_popup->get_item_icon(current_shape)); } internal_margin->begin_bulk_theme_override(); @@ -705,14 +705,14 @@ void ColorPicker::_text_type_toggled() { if (text_is_constructor) { text_type->set_text(""); #ifdef TOOLS_ENABLED - text_type->set_icon(get_editor_theme_icon(SNAME("Script"))); + text_type->set_button_icon(get_editor_theme_icon(SNAME("Script"))); #endif c_text->set_editable(false); c_text->set_tooltip_text(RTR("Copy this constructor in a script.")); } else { text_type->set_text("#"); - text_type->set_icon(nullptr); + text_type->set_button_icon(nullptr); c_text->set_editable(true); c_text->set_tooltip_text(ETR("Enter a hex code (\"#ff0000\") or named color (\"red\").")); @@ -738,7 +738,7 @@ void ColorPicker::set_picker_shape(PickerShapeType p_shape) { } if (p_shape != SHAPE_NONE) { shape_popup->set_item_checked(p_shape, true); - btn_shape->set_icon(shape_popup->get_item_icon(p_shape)); + btn_shape->set_button_icon(shape_popup->get_item_icon(p_shape)); } current_shape = p_shape; @@ -794,9 +794,9 @@ void ColorPicker::_show_hide_preset(const bool &p_is_btn_pressed, Button *p_btn_ void ColorPicker::_update_drop_down_arrow(const bool &p_is_btn_pressed, Button *p_btn_preset) { if (p_is_btn_pressed) { - p_btn_preset->set_icon(theme_cache.expanded_arrow); + p_btn_preset->set_button_icon(theme_cache.expanded_arrow); } else { - p_btn_preset->set_icon(theme_cache.folded_arrow); + p_btn_preset->set_button_icon(theme_cache.folded_arrow); } } @@ -1553,23 +1553,21 @@ void ColorPicker::_pick_button_pressed_legacy() { picker_texture_rect = memnew(TextureRect); picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT); + picker_texture_rect->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE); picker_window->add_child(picker_texture_rect); picker_texture_rect->set_default_cursor_shape(CURSOR_POINTING_HAND); picker_texture_rect->connect(SceneStringName(gui_input), callable_mp(this, &ColorPicker::_picker_texture_input)); - picker_preview = memnew(Panel); - picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); - picker_preview->set_mouse_filter(MOUSE_FILTER_IGNORE); - picker_window->add_child(picker_preview); - picker_preview_label = memnew(Label); - picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); + picker_preview_label->set_anchors_preset(Control::PRESET_CENTER_TOP); picker_preview_label->set_text(ETR("Color Picking active")); - picker_preview->add_child(picker_preview_label); - picker_preview_style_box = (Ref<StyleBoxFlat>)memnew(StyleBoxFlat); + picker_preview_style_box.instantiate(); picker_preview_style_box->set_bg_color(Color(1.0, 1.0, 1.0)); - picker_preview->add_theme_style_override(SceneStringName(panel), picker_preview_style_box); + picker_preview_style_box->set_content_margin_all(4.0); + picker_preview_label->add_theme_style_override(CoreStringName(normal), picker_preview_style_box); + + picker_window->add_child(picker_preview_label); } Rect2i screen_rect; @@ -1611,7 +1609,7 @@ void ColorPicker::_pick_button_pressed_legacy() { } picker_window->set_size(screen_rect.size); - picker_preview->set_size(screen_rect.size / 10.0); // 10% of size in each axis. + picker_preview_label->set_custom_minimum_size(screen_rect.size / 10); // 10% of size in each axis. picker_window->popup(); } @@ -1634,7 +1632,7 @@ void ColorPicker::_picker_texture_input(const Ref<InputEvent> &p_event) { Vector2 ofs = mev->get_position(); picker_color = img->get_pixel(ofs.x, ofs.y); picker_preview_style_box->set_bg_color(picker_color); - picker_preview_label->set_self_modulate(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); + picker_preview_label->add_theme_color_override(SceneStringName(font_color), picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); } } } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index ad028584b1..59540d9ace 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -130,7 +130,6 @@ private: Popup *picker_window = nullptr; // Legacy color picking. TextureRect *picker_texture_rect = nullptr; - Panel *picker_preview = nullptr; Label *picker_preview_label = nullptr; Ref<StyleBoxFlat> picker_preview_style_box; Color picker_color; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 5052deb65a..4a3f7f2414 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -44,7 +44,7 @@ #ifdef TOOLS_ENABLED #include "editor/plugins/control_editor_plugin.h" -#endif +#endif // TOOLS_ENABLED // Editor plugin interoperability. @@ -120,11 +120,11 @@ void Control::_edit_set_state(const Dictionary &p_state) { void Control::_edit_set_position(const Point2 &p_position) { ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins."); set_position(p_position, ControlEditorToolbar::get_singleton()->is_anchors_mode_enabled() && get_parent_control()); -}; +} Point2 Control::_edit_get_position() const { return get_position(); -}; +} void Control::_edit_set_scale(const Size2 &p_scale) { set_scale(p_scale); @@ -140,14 +140,6 @@ void Control::_edit_set_rect(const Rect2 &p_edit_rect) { set_size(p_edit_rect.size.snappedf(1), ControlEditorToolbar::get_singleton()->is_anchors_mode_enabled()); } -Rect2 Control::_edit_get_rect() const { - return Rect2(Point2(), get_size()); -} - -bool Control::_edit_use_rect() const { - return true; -} - void Control::_edit_set_rotation(real_t p_rotation) { set_rotation(p_rotation); } @@ -178,7 +170,17 @@ bool Control::_edit_use_pivot() const { Size2 Control::_edit_get_minimum_size() const { return get_combined_minimum_size(); } -#endif +#endif // TOOLS_ENABLED + +#ifdef DEBUG_ENABLED +Rect2 Control::_edit_get_rect() const { + return Rect2(Point2(), get_size()); +} + +bool Control::_edit_use_rect() const { + return true; +} +#endif // DEBUG_ENABLED void Control::reparent(Node *p_parent, bool p_keep_global_transform) { ERR_MAIN_THREAD_GUARD; @@ -239,7 +241,7 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List } CanvasItem::get_argument_options(p_function, p_idx, r_options); } -#endif +#endif // TOOLS_ENABLED PackedStringArray Control::get_configuration_warnings() const { ERR_READ_THREAD_GUARD_V(PackedStringArray()); @@ -663,7 +665,7 @@ Rect2 Control::get_parent_anchorable_rect() const { #else parent_rect = get_viewport()->get_visible_rect(); -#endif +#endif // TOOLS_ENABLED } return parent_rect; @@ -1396,7 +1398,7 @@ void Control::set_position(const Point2 &p_point, bool p_keep_offsets) { data.pos_cache = p_point; return; } -#endif +#endif // TOOLS_ENABLED if (p_keep_offsets) { _compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor); @@ -1440,7 +1442,7 @@ void Control::_set_size(const Size2 &p_size) { if (data.size_warning && (data.anchor[SIDE_LEFT] != data.anchor[SIDE_RIGHT] || data.anchor[SIDE_TOP] != data.anchor[SIDE_BOTTOM])) { WARN_PRINT("Nodes with non-equal opposite anchors will have their size overridden after _ready(). \nIf you want to set size, change the anchors or consider using set_deferred()."); } -#endif +#endif // DEBUG_ENABLED set_size(p_size); } @@ -1462,7 +1464,7 @@ void Control::set_size(const Size2 &p_size, bool p_keep_offsets) { data.size_cache = new_size; return; } -#endif +#endif // TOOLS_ENABLED if (p_keep_offsets) { _compute_anchors(Rect2(data.pos_cache, new_size), data.offset, data.anchor); @@ -2745,7 +2747,7 @@ Variant Control::get_theme_item(Theme::DataType p_data_type, const StringName &p Ref<Texture2D> Control::get_editor_theme_icon(const StringName &p_name) const { return get_theme_icon(p_name, SNAME("EditorIcons")); } -#endif +#endif // TOOLS_ENABLED bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { ERR_READ_THREAD_GUARD_V(false); @@ -3087,7 +3089,7 @@ bool Control::is_layout_rtl() const { const_cast<Control *>(this)->data.is_rtl = true; return data.is_rtl; } -#endif +#endif // TOOLS_ENABLED Node *parent_node = get_parent(); while (parent_node) { Control *parent_control = Object::cast_to<Control>(parent_node); @@ -3162,7 +3164,7 @@ bool Control::is_auto_translating() const { ERR_READ_THREAD_GUARD_V(false); return can_auto_translate(); } -#endif +#endif // DISABLE_DEPRECATED void Control::set_tooltip_auto_translate_mode(AutoTranslateMode p_mode) { ERR_MAIN_THREAD_GUARD; @@ -3215,7 +3217,7 @@ void Control::_notification(int p_notification) { case NOTIFICATION_EDITOR_POST_SAVE: { saving = false; } break; -#endif +#endif // TOOLS_ENABLED case NOTIFICATION_POSTINITIALIZE: { data.initialized = true; @@ -3261,7 +3263,7 @@ void Control::_notification(int p_notification) { case NOTIFICATION_READY: { #ifdef DEBUG_ENABLED connect(SceneStringName(ready), callable_mp(this, &Control::_clear_size_warning), CONNECT_DEFERRED | CONNECT_ONE_SHOT); -#endif +#endif // DEBUG_ENABLED } break; case NOTIFICATION_ENTER_CANVAS: { @@ -3573,7 +3575,7 @@ void Control::_bind_methods() { #ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_auto_translate", "enable"), &Control::set_auto_translate); ClassDB::bind_method(D_METHOD("is_auto_translating"), &Control::is_auto_translating); -#endif +#endif // DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_localize_numeral_system", "enable"), &Control::set_localize_numeral_system); ClassDB::bind_method(D_METHOD("is_localizing_numeral_system"), &Control::is_localizing_numeral_system); @@ -3628,7 +3630,7 @@ void Control::_bind_methods() { #ifndef DISABLE_DEPRECATED ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_auto_translate", "is_auto_translating"); -#endif +#endif // DISABLE_DEPRECATED ADD_GROUP("Tooltip", "tooltip_"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "tooltip_text", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip_text", "get_tooltip_text"); diff --git a/scene/gui/control.h b/scene/gui/control.h index 6cabf10971..ac386659ec 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -48,7 +48,7 @@ class Control : public CanvasItem { #ifdef TOOLS_ENABLED bool saving = false; -#endif +#endif //TOOLS_ENABLED public: enum Anchor { @@ -396,8 +396,6 @@ public: virtual Size2 _edit_get_scale() const override; virtual void _edit_set_rect(const Rect2 &p_edit_rect) override; - virtual Rect2 _edit_get_rect() const override; - virtual bool _edit_use_rect() const override; virtual void _edit_set_rotation(real_t p_rotation) override; virtual real_t _edit_get_rotation() const override; @@ -408,7 +406,13 @@ public: virtual bool _edit_use_pivot() const override; virtual Size2 _edit_get_minimum_size() const override; -#endif +#endif //TOOLS_ENABLED + +#ifdef DEBUG_ENABLED + virtual Rect2 _edit_get_rect() const override; + virtual bool _edit_use_rect() const override; +#endif // DEBUG_ENABLED + virtual void reparent(Node *p_parent, bool p_keep_global_transform = true) override; // Editor integration. @@ -418,7 +422,7 @@ public: PackedStringArray get_configuration_warnings() const override; #ifdef TOOLS_ENABLED virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; -#endif +#endif //TOOLS_ENABLED virtual bool is_text_field() const; @@ -605,7 +609,7 @@ public: Variant get_theme_item(Theme::DataType p_data_type, const StringName &p_name, const StringName &p_theme_type = StringName()) const; #ifdef TOOLS_ENABLED Ref<Texture2D> get_editor_theme_icon(const StringName &p_name) const; -#endif +#endif //TOOLS_ENABLED bool has_theme_icon_override(const StringName &p_name) const; bool has_theme_stylebox_override(const StringName &p_name) const; @@ -637,7 +641,7 @@ public: #ifndef DISABLE_DEPRECATED void set_auto_translate(bool p_enable); bool is_auto_translating() const; -#endif +#endif //DISABLE_DEPRECATED void set_tooltip_auto_translate_mode(AutoTranslateMode p_mode); AutoTranslateMode get_tooltip_auto_translate_mode() const; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index d8e9d1bcc0..9eda1a256f 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -67,7 +67,18 @@ void FileDialog::_native_popup() { } else if (access == ACCESS_USERDATA) { root = OS::get_singleton()->get_user_data_dir(); } - DisplayServer::get_singleton()->file_dialog_with_options_show(get_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), filters, _get_options(), callable_mp(this, &FileDialog::_native_dialog_cb)); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE_EXTRA)) { + DisplayServer::get_singleton()->file_dialog_with_options_show(get_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), filters, _get_options(), callable_mp(this, &FileDialog::_native_dialog_cb_with_options)); + } else { + DisplayServer::get_singleton()->file_dialog_show(get_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), filters, callable_mp(this, &FileDialog::_native_dialog_cb)); + } +} + +bool FileDialog::_can_use_native_popup() { + if (access == ACCESS_RESOURCES || access == ACCESS_USERDATA || options.size() > 0) { + return DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE_EXTRA); + } + return DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE); } void FileDialog::popup(const Rect2i &p_rect) { @@ -80,7 +91,7 @@ void FileDialog::popup(const Rect2i &p_rect) { } #endif - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { + if (_can_use_native_popup() && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { _native_popup(); } else { ConfirmationDialog::popup(p_rect); @@ -99,7 +110,7 @@ void FileDialog::set_visible(bool p_visible) { } #endif - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { + if (_can_use_native_popup() && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { if (p_visible) { _native_popup(); } @@ -108,7 +119,11 @@ void FileDialog::set_visible(bool p_visible) { } } -void FileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter, const Dictionary &p_selected_options) { +void FileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter) { + _native_dialog_cb_with_options(p_ok, p_files, p_filter, Dictionary()); +} + +void FileDialog::_native_dialog_cb_with_options(bool p_ok, const Vector<String> &p_files, int p_filter, const Dictionary &p_selected_options) { if (!p_ok) { file->set_text(""); emit_signal(SNAME("canceled")); @@ -182,7 +197,7 @@ void FileDialog::_notification(int p_what) { #endif // Replace the built-in dialog with the native one if it started visible. - if (is_visible() && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { + if (is_visible() && _can_use_native_popup() && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { ConfirmationDialog::set_visible(false); _native_popup(); } @@ -197,18 +212,18 @@ void FileDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - dir_up->set_icon(theme_cache.parent_folder); + dir_up->set_button_icon(theme_cache.parent_folder); if (vbox->is_layout_rtl()) { - dir_prev->set_icon(theme_cache.forward_folder); - dir_next->set_icon(theme_cache.back_folder); + dir_prev->set_button_icon(theme_cache.forward_folder); + dir_next->set_button_icon(theme_cache.back_folder); } else { - dir_prev->set_icon(theme_cache.back_folder); - dir_next->set_icon(theme_cache.forward_folder); + dir_prev->set_button_icon(theme_cache.back_folder); + dir_next->set_button_icon(theme_cache.forward_folder); } - refresh->set_icon(theme_cache.reload); - show_hidden->set_icon(theme_cache.toggle_hidden); - makedir->set_icon(theme_cache.create_folder); - show_filename_filter_button->set_icon(theme_cache.toggle_filename_filter); + refresh->set_button_icon(theme_cache.reload); + show_hidden->set_button_icon(theme_cache.toggle_hidden); + makedir->set_button_icon(theme_cache.create_folder); + show_filename_filter_button->set_button_icon(theme_cache.toggle_filename_filter); dir_up->begin_bulk_theme_override(); dir_up->add_theme_color_override("icon_normal_color", theme_cache.icon_normal_color); @@ -1487,7 +1502,7 @@ void FileDialog::set_use_native_dialog(bool p_native) { #endif // Replace the built-in dialog with the native one if it's currently visible. - if (is_inside_tree() && is_visible() && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { + if (is_inside_tree() && is_visible() && _can_use_native_popup() && (use_native_dialog || OS::get_singleton()->is_sandboxed())) { ConfirmationDialog::set_visible(false); _native_popup(); } @@ -1571,6 +1586,7 @@ FileDialog::FileDialog() { vbox->add_child(hbc); tree = memnew(Tree); + tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); tree->set_hide_root(true); vbox->add_margin_child(ETR("Directories & Files:"), tree, true); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 6ef60a0f4f..28978dbed3 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -188,8 +188,10 @@ private: virtual void shortcut_input(const Ref<InputEvent> &p_event) override; + bool _can_use_native_popup(); void _native_popup(); - void _native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter, const Dictionary &p_selected_options); + void _native_dialog_cb(bool p_ok, const Vector<String> &p_files, int p_filter); + void _native_dialog_cb_with_options(bool p_ok, const Vector<String> &p_files, int p_filter, const Dictionary &p_selected_options); bool _is_open_should_be_disabled(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 646757008a..7e07f4a202 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -317,7 +317,7 @@ bool GraphEdit::is_node_connected(const StringName &p_from, int p_from_port, con void GraphEdit::disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port) { ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); - for (const List<Ref<Connection>>::Element *E = connections.front(); E; E = E->next()) { + for (List<Ref<Connection>>::Element *E = connections.front(); E; E = E->next()) { if (E->get()->from_node == p_from && E->get()->from_port == p_from_port && E->get()->to_node == p_to && E->get()->to_port == p_to_port) { connection_map[p_from].erase(E->get()); connection_map[p_to].erase(E->get()); @@ -733,14 +733,14 @@ void GraphEdit::_update_theme_item_cache() { void GraphEdit::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - zoom_minus_button->set_icon(theme_cache.zoom_out); - zoom_reset_button->set_icon(theme_cache.zoom_reset); - zoom_plus_button->set_icon(theme_cache.zoom_in); + zoom_minus_button->set_button_icon(theme_cache.zoom_out); + zoom_reset_button->set_button_icon(theme_cache.zoom_reset); + zoom_plus_button->set_button_icon(theme_cache.zoom_in); - toggle_snapping_button->set_icon(theme_cache.snapping_toggle); - toggle_grid_button->set_icon(theme_cache.grid_toggle); - minimap_button->set_icon(theme_cache.minimap_toggle); - arrange_button->set_icon(theme_cache.layout); + toggle_snapping_button->set_button_icon(theme_cache.snapping_toggle); + toggle_grid_button->set_button_icon(theme_cache.grid_toggle); + minimap_button->set_button_icon(theme_cache.minimap_toggle); + arrange_button->set_button_icon(theme_cache.layout); zoom_label->set_custom_minimum_size(Size2(48, 0) * theme_cache.base_scale); @@ -3001,5 +3001,5 @@ GraphEdit::GraphEdit() { set_clip_contents(true); - arranger = Ref<GraphEditArranger>(memnew(GraphEditArranger(this))); + arranger.instantiate(this); } diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 42b4e56b48..7a0e5b8867 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -335,6 +335,121 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col } } +void Label::_ensure_shaped() const { + if (dirty || font_dirty || lines_dirty) { + const_cast<Label *>(this)->_shape(); + } +} + +RID Label::get_line_rid(int p_line) const { + return lines_rid[p_line]; +} + +Rect2 Label::get_line_rect(int p_line) const { + // Returns a rect providing the line's horizontal offset and total size. To determine the vertical + // offset, use r_offset and r_line_spacing from get_layout_data. + bool rtl = TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL; + bool rtl_layout = is_layout_rtl(); + Ref<StyleBox> style = theme_cache.normal_style; + Size2 size = get_size(); + Size2 line_size = TS->shaped_text_get_size(lines_rid[p_line]); + Vector2 offset; + + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_FILL: + if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) { + offset.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); + } else { + offset.x = style->get_offset().x; + } + break; + case HORIZONTAL_ALIGNMENT_LEFT: { + if (rtl_layout) { + offset.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); + } else { + offset.x = style->get_offset().x; + } + } break; + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = int(size.width - line_size.width) / 2; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + if (rtl_layout) { + offset.x = style->get_offset().x; + } else { + offset.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); + } + } break; + } + + return Rect2(offset, line_size); +} + +void Label::get_layout_data(Vector2 &r_offset, int &r_line_limit, int &r_line_spacing) const { + // Computes several common parameters involved in laying out and rendering text set to this label. + // Only vertical margin is considered in r_offset: use get_line_rect to get the horizontal offset + // for a given line of text. + Size2 size = get_size(); + Ref<StyleBox> style = theme_cache.normal_style; + int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing; + + float total_h = 0.0; + int lines_visible = 0; + + // Get number of lines to fit to the height. + for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { + total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; + if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { + break; + } + lines_visible++; + } + + if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { + lines_visible = max_lines_visible; + } + + r_line_limit = MIN(lines_rid.size(), lines_visible + lines_skipped); + + // Get real total height. + total_h = 0; + for (int64_t i = lines_skipped; i < r_line_limit; i++) { + total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; + } + total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); + + int vbegin = 0, vsep = 0; + if (lines_visible > 0) { + switch (vertical_alignment) { + case VERTICAL_ALIGNMENT_TOP: { + // Nothing. + } break; + case VERTICAL_ALIGNMENT_CENTER: { + vbegin = (size.y - (total_h - line_spacing)) / 2; + vsep = 0; + + } break; + case VERTICAL_ALIGNMENT_BOTTOM: { + vbegin = size.y - (total_h - line_spacing); + vsep = 0; + + } break; + case VERTICAL_ALIGNMENT_FILL: { + vbegin = 0; + if (lines_visible > 1) { + vsep = (size.y - (total_h - line_spacing)) / (lines_visible - 1); + } else { + vsep = 0; + } + + } break; + } + } + + r_offset = { 0, style->get_offset().y + vbegin }; + r_line_spacing = line_spacing + vsep; +} + PackedStringArray Label::get_configuration_warnings() const { PackedStringArray warnings = Control::get_configuration_warnings(); @@ -361,10 +476,7 @@ PackedStringArray Label::get_configuration_warnings() const { } if (font.is_valid()) { - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } - + _ensure_shaped(); const Glyph *glyph = TS->shaped_text_get_glyphs(text_rid); int64_t glyph_count = TS->shaped_text_get_glyph_count(text_rid); for (int64_t i = 0; i < glyph_count; i++) { @@ -416,22 +528,17 @@ void Label::_notification(int p_what) { } } - if (dirty || font_dirty || lines_dirty) { - _shape(); - } + _ensure_shaped(); RID ci = get_canvas_item(); bool has_settings = settings.is_valid(); Size2 string_size; - Size2 size = get_size(); Ref<StyleBox> style = theme_cache.normal_style; - Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font; Color font_color = has_settings ? settings->get_font_color() : theme_cache.font_color; Color font_shadow_color = has_settings ? settings->get_shadow_color() : theme_cache.font_shadow_color; Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : theme_cache.font_shadow_offset; - int line_spacing = has_settings ? settings->get_line_spacing() : theme_cache.line_spacing; Color font_outline_color = has_settings ? settings->get_outline_color() : theme_cache.font_outline_color; int outline_size = has_settings ? settings->get_outline_size() : theme_cache.font_outline_size; int shadow_outline_size = has_settings ? settings->get_shadow_size() : theme_cache.font_shadow_outline_size; @@ -440,98 +547,28 @@ void Label::_notification(int p_what) { style->draw(ci, Rect2(Point2(0, 0), get_size())); - float total_h = 0.0; - int lines_visible = 0; - - // Get number of lines to fit to the height. - for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { - total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; - if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { - break; - } - lines_visible++; - } - - if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { - lines_visible = max_lines_visible; - } - - int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped); bool trim_chars = (visible_chars >= 0) && (visible_chars_behavior == TextServer::VC_CHARS_AFTER_SHAPING); bool trim_glyphs_ltr = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_LTR) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && !rtl_layout)); bool trim_glyphs_rtl = (visible_chars >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_RTL) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && rtl_layout)); - // Get real total height. + Vector2 ofs; + int line_limit; + int line_spacing; + get_layout_data(ofs, line_limit, line_spacing); + + int processed_glyphs = 0; int total_glyphs = 0; - total_h = 0; - for (int64_t i = lines_skipped; i < last_line; i++) { - total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; + + for (int64_t i = lines_skipped; i < line_limit; i++) { total_glyphs += TS->shaped_text_get_glyph_count(lines_rid[i]) + TS->shaped_text_get_ellipsis_glyph_count(lines_rid[i]); } - int visible_glyphs = total_glyphs * visible_ratio; - int processed_glyphs = 0; - total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); - - int vbegin = 0, vsep = 0; - if (lines_visible > 0) { - switch (vertical_alignment) { - case VERTICAL_ALIGNMENT_TOP: { - // Nothing. - } break; - case VERTICAL_ALIGNMENT_CENTER: { - vbegin = (size.y - (total_h - line_spacing)) / 2; - vsep = 0; - - } break; - case VERTICAL_ALIGNMENT_BOTTOM: { - vbegin = size.y - (total_h - line_spacing); - vsep = 0; - - } break; - case VERTICAL_ALIGNMENT_FILL: { - vbegin = 0; - if (lines_visible > 1) { - vsep = (size.y - (total_h - line_spacing)) / (lines_visible - 1); - } else { - vsep = 0; - } - } break; - } - } + int visible_glyphs = total_glyphs * visible_ratio; - Vector2 ofs; - ofs.y = style->get_offset().y + vbegin; - for (int i = lines_skipped; i < last_line; i++) { - Size2 line_size = TS->shaped_text_get_size(lines_rid[i]); - ofs.x = 0; + for (int i = lines_skipped; i < line_limit; i++) { + Vector2 line_offset = get_line_rect(i).position; + ofs.x = line_offset.x; ofs.y += TS->shaped_text_get_ascent(lines_rid[i]); - switch (horizontal_alignment) { - case HORIZONTAL_ALIGNMENT_FILL: - if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } else { - ofs.x = style->get_offset().x; - } - break; - case HORIZONTAL_ALIGNMENT_LEFT: { - if (rtl_layout) { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } else { - ofs.x = style->get_offset().x; - } - } break; - case HORIZONTAL_ALIGNMENT_CENTER: { - ofs.x = int(size.width - line_size.width) / 2; - } break; - case HORIZONTAL_ALIGNMENT_RIGHT: { - if (rtl_layout) { - ofs.x = style->get_offset().x; - } else { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } - } break; - } const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]); @@ -621,7 +658,7 @@ void Label::_notification(int p_what) { } } } - ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing; + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } break; @@ -637,102 +674,16 @@ void Label::_notification(int p_what) { } Rect2 Label::get_character_bounds(int p_pos) const { - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } - - bool has_settings = settings.is_valid(); - Size2 size = get_size(); - Ref<StyleBox> style = theme_cache.normal_style; - int line_spacing = has_settings ? settings->get_line_spacing() : theme_cache.line_spacing; - bool rtl = (TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL); - bool rtl_layout = is_layout_rtl(); - - float total_h = 0.0; - int lines_visible = 0; - - // Get number of lines to fit to the height. - for (int64_t i = lines_skipped; i < lines_rid.size(); i++) { - total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; - if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { - break; - } - lines_visible++; - } - - if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { - lines_visible = max_lines_visible; - } - - int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped); - - // Get real total height. - total_h = 0; - for (int64_t i = lines_skipped; i < last_line; i++) { - total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; - } - - total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); - - int vbegin = 0, vsep = 0; - if (lines_visible > 0) { - switch (vertical_alignment) { - case VERTICAL_ALIGNMENT_TOP: { - // Nothing. - } break; - case VERTICAL_ALIGNMENT_CENTER: { - vbegin = (size.y - (total_h - line_spacing)) / 2; - vsep = 0; - - } break; - case VERTICAL_ALIGNMENT_BOTTOM: { - vbegin = size.y - (total_h - line_spacing); - vsep = 0; - - } break; - case VERTICAL_ALIGNMENT_FILL: { - vbegin = 0; - if (lines_visible > 1) { - vsep = (size.y - (total_h - line_spacing)) / (lines_visible - 1); - } else { - vsep = 0; - } - - } break; - } - } + _ensure_shaped(); Vector2 ofs; - ofs.y = style->get_offset().y + vbegin; - for (int i = lines_skipped; i < last_line; i++) { - Size2 line_size = TS->shaped_text_get_size(lines_rid[i]); - ofs.x = 0; - switch (horizontal_alignment) { - case HORIZONTAL_ALIGNMENT_FILL: - if (rtl && autowrap_mode != TextServer::AUTOWRAP_OFF) { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } else { - ofs.x = style->get_offset().x; - } - break; - case HORIZONTAL_ALIGNMENT_LEFT: { - if (rtl_layout) { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } else { - ofs.x = style->get_offset().x; - } - } break; - case HORIZONTAL_ALIGNMENT_CENTER: { - ofs.x = int(size.width - line_size.width) / 2; - } break; - case HORIZONTAL_ALIGNMENT_RIGHT: { - if (rtl_layout) { - ofs.x = style->get_offset().x; - } else { - ofs.x = int(size.width - style->get_margin(SIDE_RIGHT) - line_size.width); - } - } break; - } + int line_limit; + int line_spacing; + get_layout_data(ofs, line_limit, line_spacing); + + for (int i = lines_skipped; i < line_limit; i++) { + Rect2 line_rect = get_line_rect(i); + ofs.x = line_rect.position.x; int v_size = TS->shaped_text_get_glyph_count(lines_rid[i]); const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); @@ -746,22 +697,19 @@ Rect2 Label::get_character_bounds(int p_pos) const { } Rect2 rect; rect.position = ofs + Vector2(gl_off, 0); - rect.size = Vector2(advance, TS->shaped_text_get_size(lines_rid[i]).y); + rect.size = Vector2(advance, line_rect.size.y); return rect; } } gl_off += glyphs[j].advance * glyphs[j].repeat; } - ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing; + ofs.y += TS->shaped_text_get_ascent(lines_rid[i]) + TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } return Rect2(); } Size2 Label::get_minimum_size() const { - // don't want to mutable everything - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } + _ensure_shaped(); Size2 min_size = minsize; @@ -798,10 +746,7 @@ int Label::get_line_count() const { if (!is_inside_tree()) { return 1; } - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } - + _ensure_shaped(); return lines_rid.size(); } @@ -1104,10 +1049,7 @@ int Label::get_max_lines_visible() const { } int Label::get_total_character_count() const { - if (dirty || font_dirty || lines_dirty) { - const_cast<Label *>(this)->_shape(); - } - + _ensure_shaped(); return xl_text.length(); } diff --git a/scene/gui/label.h b/scene/gui/label.h index e0ebca944a..2576d21c33 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -91,11 +91,16 @@ private: int font_shadow_outline_size; } theme_cache; + void _ensure_shaped() const; void _update_visible(); void _shape(); void _invalidate(); protected: + RID get_line_rid(int p_line) const; + Rect2 get_line_rect(int p_line) const; + void get_layout_data(Vector2 &r_offset, int &r_line_limit, int &r_line_spacing) const; + void _notification(int p_what); static void _bind_methods(); #ifndef DISABLE_DEPRECATED diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 9967805134..3f979f7c20 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -128,6 +128,7 @@ bool LineEdit::has_ime_text() const { void LineEdit::cancel_ime() { if (!has_ime_text()) { + _close_ime_window(); return; } ime_text = String(); @@ -140,6 +141,7 @@ void LineEdit::cancel_ime() { void LineEdit::apply_ime() { if (!has_ime_text()) { + _close_ime_window(); return; } diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 5432058f7b..79018c40f5 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -225,7 +225,7 @@ void OptionButton::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) { popup->set_item_icon(p_idx, p_icon); if (current == p_idx) { - set_icon(p_icon); + set_button_icon(p_icon); } _queue_update_size_cache(); } @@ -381,7 +381,7 @@ void OptionButton::_select(int p_which, bool p_emit) { current = NONE_SELECTED; set_text(""); - set_icon(nullptr); + set_button_icon(nullptr); } else { ERR_FAIL_INDEX(p_which, popup->get_item_count()); @@ -391,7 +391,7 @@ void OptionButton::_select(int p_which, bool p_emit) { current = p_which; set_text(popup->get_item_text(current)); - set_icon(popup->get_item_icon(current)); + set_button_icon(popup->get_item_icon(current)); } if (is_inside_tree() && p_emit) { diff --git a/scene/gui/range.h b/scene/gui/range.h index b1c2446ded..710fed8645 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -64,7 +64,7 @@ class Range : public Control { protected: virtual void _value_changed(double p_value); - void _notify_shared_value_changed() { shared->emit_value_changed(); }; + void _notify_shared_value_changed() { shared->emit_value_changed(); } static void _bind_methods(); diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h index 681f068fb2..94e1bd4f04 100644 --- a/scene/gui/rich_text_effect.h +++ b/scene/gui/rich_text_effect.h @@ -79,20 +79,20 @@ public: Color get_color() { return color; } void set_color(Color p_color) { color = p_color; } - uint32_t get_glyph_index() const { return glyph_index; }; - void set_glyph_index(uint32_t p_glyph_index) { glyph_index = p_glyph_index; }; + uint32_t get_glyph_index() const { return glyph_index; } + void set_glyph_index(uint32_t p_glyph_index) { glyph_index = p_glyph_index; } - uint16_t get_glyph_flags() const { return glyph_flags; }; - void set_glyph_flags(uint16_t p_glyph_flags) { glyph_flags = p_glyph_flags; }; + uint16_t get_glyph_flags() const { return glyph_flags; } + void set_glyph_flags(uint16_t p_glyph_flags) { glyph_flags = p_glyph_flags; } - uint8_t get_glyph_count() const { return glyph_count; }; - void set_glyph_count(uint8_t p_glyph_count) { glyph_count = p_glyph_count; }; + uint8_t get_glyph_count() const { return glyph_count; } + void set_glyph_count(uint8_t p_glyph_count) { glyph_count = p_glyph_count; } - int32_t get_relative_index() const { return relative_index; }; - void set_relative_index(int32_t p_relative_index) { relative_index = p_relative_index; }; + int32_t get_relative_index() const { return relative_index; } + void set_relative_index(int32_t p_relative_index) { relative_index = p_relative_index; } - RID get_font() const { return font; }; - void set_font(RID p_font) { font = p_font; }; + RID get_font() const { return font; } + void set_font(RID p_font) { font = p_font; } Dictionary get_environment() { return environment; } void set_environment(Dictionary p_environment) { environment = p_environment; } diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 1ac0e8b59f..312b538a99 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -461,7 +461,7 @@ void ScrollContainer::update_scrollbars() { void ScrollContainer::_scroll_moved(float) { queue_sort(); -}; +} void ScrollContainer::set_h_scroll(int p_pos) { h_scroll->set_value(p_pos); @@ -625,7 +625,7 @@ void ScrollContainer::_bind_methods() { BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollContainer, panel_style, "panel"); GLOBAL_DEF("gui/common/default_scroll_deadzone", 0); -}; +} ScrollContainer::ScrollContainer() { h_scroll = memnew(HScrollBar); @@ -641,4 +641,4 @@ ScrollContainer::ScrollContainer() { deadzone = GLOBAL_GET("gui/common/default_scroll_deadzone"); set_clip_contents(true); -}; +} diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 01c2b9bffe..e56a9e71ef 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -41,7 +41,11 @@ Size2 SpinBox::get_minimum_size() const { } void SpinBox::_update_text(bool p_keep_line_edit) { - String value = String::num(get_value(), Math::range_step_decimals(get_step())); + double step = get_step(); + if (use_custom_arrow_step && custom_arrow_step != 0.0) { + step = custom_arrow_step; + } + String value = String::num(get_value(), Math::range_step_decimals(step)); if (is_localizing_numeral_system()) { value = TS->format_number(value); } @@ -75,6 +79,9 @@ void SpinBox::_text_submitted(const String &p_string) { text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix); Error err = expr->parse(text); + + use_custom_arrow_step = false; + if (err != OK) { // If the expression failed try without converting commas to dots - they might have been for parameter separation. text = p_string; @@ -114,8 +121,13 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) { void SpinBox::_range_click_timeout() { if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) { bool up = get_local_mouse_position().y < (get_size().height / 2); - double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); - set_value(get_value() + (up ? step : -step)); + double step = get_step(); + // Arrow button is being pressed, so we also need to set the step to the same value as custom_arrow_step if its not 0. + double temp_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); + _set_step_no_signal(temp_step); + set_value(get_value() + (up ? temp_step : -temp_step)); + _set_step_no_signal(step); + use_custom_arrow_step = true; if (range_click_timer->is_one_shot()) { range_click_timer->set_wait_time(0.075); @@ -156,8 +168,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; Ref<InputEventMouseMotion> mm = p_event; - double step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); - + double step = get_step(); Vector2 mpos; bool mouse_on_up_button = false; bool mouse_on_down_button = false; @@ -177,7 +188,12 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { line_edit->grab_focus(); if (mouse_on_up_button || mouse_on_down_button) { - set_value(get_value() + (mouse_on_up_button ? step : -step)); + // Arrow button is being pressed, so step is being changed temporarily. + double temp_step = get_custom_arrow_step() != 0.0 ? get_custom_arrow_step() : get_step(); + _set_step_no_signal(temp_step); + set_value(get_value() + (mouse_on_up_button ? temp_step : -temp_step)); + _set_step_no_signal(step); + use_custom_arrow_step = true; } state_cache.up_button_pressed = mouse_on_up_button; state_cache.down_button_pressed = mouse_on_down_button; @@ -193,17 +209,20 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { case MouseButton::RIGHT: { line_edit->grab_focus(); if (mouse_on_up_button || mouse_on_down_button) { + use_custom_arrow_step = false; set_value(mouse_on_up_button ? get_max() : get_min()); } } break; case MouseButton::WHEEL_UP: { if (line_edit->is_editing()) { + use_custom_arrow_step = false; set_value(get_value() + step * mb->get_factor()); accept_event(); } } break; case MouseButton::WHEEL_DOWN: { if (line_edit->is_editing()) { + use_custom_arrow_step = false; set_value(get_value() - step * mb->get_factor()); accept_event(); } @@ -243,6 +262,7 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { if (drag.enabled) { drag.diff_y += mm->get_relative().y; double diff_y = -0.01 * Math::pow(ABS(drag.diff_y), 1.8) * SIGN(drag.diff_y); + use_custom_arrow_step = false; set_value(CLAMP(drag.base_val + step * diff_y, get_min(), get_max())); } else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); @@ -519,6 +539,12 @@ void SpinBox::_update_buttons_state_for_current_value() { } } +void SpinBox::_set_step_no_signal(double p_step) { + set_block_signals(true); + set_step(p_step); + set_block_signals(false); +} + void SpinBox::_bind_methods() { ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &SpinBox::set_horizontal_alignment); ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &SpinBox::get_horizontal_alignment); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 294dc3e5d5..06a0f622b9 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -66,6 +66,7 @@ class SpinBox : public Range { String suffix; String last_updated_text; double custom_arrow_step = 0.0; + bool use_custom_arrow_step = false; void _line_edit_input(const Ref<InputEvent> &p_event); @@ -133,6 +134,7 @@ class SpinBox : public Range { void _mouse_exited(); void _update_buttons_state_for_current_value(); + void _set_step_no_signal(double p_step); protected: virtual void gui_input(const Ref<InputEvent> &p_event) override; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 6b5ff23436..b1918ff23f 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -3169,6 +3169,7 @@ bool TextEdit::has_ime_text() const { void TextEdit::cancel_ime() { if (!has_ime_text()) { + _close_ime_window(); return; } ime_text = String(); @@ -3181,6 +3182,7 @@ void TextEdit::cancel_ime() { void TextEdit::apply_ime() { if (!has_ime_text()) { + _close_ime_window(); return; } @@ -5069,7 +5071,7 @@ bool TextEdit::multicaret_edit_ignore_caret(int p_caret) const { } bool TextEdit::is_caret_visible(int p_caret) const { - ERR_FAIL_INDEX_V(p_caret, carets.size(), 0); + ERR_FAIL_INDEX_V(p_caret, carets.size(), false); return carets[p_caret].visible; } @@ -5736,7 +5738,7 @@ TextServer::AutowrapMode TextEdit::get_autowrap_mode() const { } bool TextEdit::is_line_wrapped(int p_line) const { - ERR_FAIL_INDEX_V(p_line, text.size(), 0); + ERR_FAIL_INDEX_V(p_line, text.size(), false); if (get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) { return false; } diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 94b105d486..6b137581f2 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -139,7 +139,7 @@ private: Variant metadata; bool clickable = false; - Ref<Texture2D> icon = Ref<Texture2D>(); + Ref<Texture2D> icon; String text = ""; Color color = Color(1, 1, 1); }; @@ -693,9 +693,9 @@ protected: void _set_symbol_lookup_word(const String &p_symbol); // Theme items. - virtual Color _get_brace_mismatch_color() const { return Color(); }; - virtual Color _get_code_folding_color() const { return Color(); }; - virtual Ref<Texture2D> _get_folded_eol_icon() const { return Ref<Texture2D>(); }; + virtual Color _get_brace_mismatch_color() const { return Color(); } + virtual Color _get_code_folding_color() const { return Color(); } + virtual Ref<Texture2D> _get_folded_eol_icon() const { return Ref<Texture2D>(); } /* Text manipulation */ diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index c267ff93c6..47bb0643b3 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -340,11 +340,11 @@ Ref<BitMap> TextureButton::get_click_mask() const { Ref<Texture2D> TextureButton::get_texture_focused() const { return focused; -}; +} void TextureButton::set_texture_focused(const Ref<Texture2D> &p_focused) { focused = p_focused; -}; +} void TextureButton::_set_texture(Ref<Texture2D> *p_destination, const Ref<Texture2D> &p_texture) { DEV_ASSERT(p_destination); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6159e26efa..f6e05f5796 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -961,19 +961,17 @@ TreeItem *TreeItem::_get_prev_in_tree(bool p_wrap, bool p_include_invisible) { if (!prev_item) { current = current->parent; - if (current == tree->root && tree->hide_root) { - return nullptr; - } else if (!current) { - if (p_wrap) { - current = this; - TreeItem *temp = get_next_visible(); - while (temp) { - current = temp; - temp = temp->get_next_visible(); - } - } else { + if (!current || (current == tree->root && tree->hide_root)) { + if (!p_wrap) { return nullptr; } + // Wrap around to the last visible item. + current = this; + TreeItem *temp = get_next_visible(); + while (temp) { + current = temp; + temp = temp->get_next_visible(); + } } } else { current = prev_item; @@ -1101,7 +1099,7 @@ void TreeItem::clear_children() { first_child = nullptr; last_child = nullptr; children_cache.clear(); -}; +} int TreeItem::get_index() { int idx = 0; @@ -1576,7 +1574,7 @@ Size2 TreeItem::get_minimum_size(int p_column) { const TreeItem::Cell &cell = cells[p_column]; - if (cell.cached_minimum_size_dirty) { + if (cell.cached_minimum_size_dirty || cell.text_buf->is_dirty() || cell.dirty) { Size2 size = Size2( parent_tree->theme_cache.inner_item_margin_left + parent_tree->theme_cache.inner_item_margin_right, parent_tree->theme_cache.inner_item_margin_top + parent_tree->theme_cache.inner_item_margin_bottom); @@ -1595,7 +1593,9 @@ Size2 TreeItem::get_minimum_size(int p_column) { // Icon. if (cell.mode == CELL_MODE_CHECK) { - size.width += parent_tree->theme_cache.checked->get_width() + parent_tree->theme_cache.h_separation; + Size2i check_size = parent_tree->theme_cache.checked->get_size(); + size.width += check_size.width + parent_tree->theme_cache.h_separation; + size.height = MAX(size.height, check_size.height); } if (cell.icon.is_valid()) { Size2i icon_size = parent_tree->_get_cell_icon_size(cell); @@ -1607,7 +1607,8 @@ Size2 TreeItem::get_minimum_size(int p_column) { for (int i = 0; i < cell.buttons.size(); i++) { Ref<Texture2D> texture = cell.buttons[i].texture; if (texture.is_valid()) { - Size2 button_size = texture->get_size() + parent_tree->theme_cache.button_pressed->get_minimum_size(); + Size2 button_size = texture->get_size(); + button_size.width += parent_tree->theme_cache.button_pressed->get_minimum_size().width; size.width += button_size.width + parent_tree->theme_cache.button_margin; size.height = MAX(size.height, button_size.height); } @@ -1891,44 +1892,7 @@ int Tree::compute_item_height(TreeItem *p_item) const { int height = 0; for (int i = 0; i < columns.size(); i++) { - if (p_item->cells[i].dirty) { - const_cast<Tree *>(this)->update_item_cell(p_item, i); - } - height = MAX(height, p_item->cells[i].text_buf->get_size().y); - for (int j = 0; j < p_item->cells[i].buttons.size(); j++) { - Size2i s; // = cache.button_pressed->get_minimum_size(); - s += p_item->cells[i].buttons[j].texture->get_size(); - if (s.height > height) { - height = s.height; - } - } - - switch (p_item->cells[i].mode) { - case TreeItem::CELL_MODE_CHECK: { - int check_icon_h = theme_cache.checked->get_height(); - if (height < check_icon_h) { - height = check_icon_h; - } - [[fallthrough]]; - } - case TreeItem::CELL_MODE_STRING: - case TreeItem::CELL_MODE_CUSTOM: - case TreeItem::CELL_MODE_ICON: { - Ref<Texture2D> icon = p_item->cells[i].icon; - if (!icon.is_null()) { - Size2i s = _get_cell_icon_size(p_item->cells[i]); - if (s.height > height) { - height = s.height; - } - } - if (p_item->cells[i].mode == TreeItem::CELL_MODE_CUSTOM && p_item->cells[i].custom_button) { - height += theme_cache.custom_button->get_minimum_size().height; - } - - } break; - default: { - } - } + height = MAX(height, p_item->get_minimum_size(i).y); } int item_min_height = MAX(theme_cache.font->get_height(theme_cache.font_size), p_item->get_custom_minimum_height()); if (height < item_min_height) { @@ -4704,6 +4668,7 @@ void Tree::item_edited(int p_column, TreeItem *p_item, MouseButton p_custom_mous edited_col = p_column; if (p_item != nullptr && p_column >= 0 && p_column < p_item->cells.size()) { edited_item->cells.write[p_column].dirty = true; + edited_item->cells.write[p_column].cached_minimum_size_dirty = true; } emit_signal(SNAME("item_edited")); if (p_custom_mouse_index != MouseButton::NONE) { @@ -4829,7 +4794,7 @@ void Tree::clear() { _determine_hovered_item(); queue_redraw(); -}; +} void Tree::set_hide_root(bool p_enabled) { if (hide_root == p_enabled) { @@ -5364,14 +5329,16 @@ void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) { int y_offset = get_item_offset(p_item); if (y_offset != -1) { - const int tbh = _get_title_button_height(); - y_offset -= tbh; + const int title_button_height = _get_title_button_height(); + y_offset -= title_button_height; const int cell_h = compute_item_height(p_item) + theme_cache.v_separation; - int screen_h = area_size.height - tbh; + int screen_h = area_size.height - title_button_height; if (p_center_on_item) { - v_scroll->set_value(y_offset - (screen_h - cell_h) / 2.0f); + // This makes sure that centering the offset doesn't overflow. + const double v_scroll_value = y_offset - MAX((screen_h - cell_h) / 2.0, 0.0); + v_scroll->set_value(v_scroll_value); } else { if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet. v_scroll->set_value(y_offset); diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 0b521f926d..878bceccbc 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -178,6 +178,7 @@ void VideoStreamPlayer::_notification(int p_notification) { draw_texture_rect(texture, Rect2(Point2(), s), false); } break; + case NOTIFICATION_SUSPENDED: case NOTIFICATION_PAUSED: { if (is_playing() && !is_paused()) { paused_from_tree = true; @@ -189,6 +190,13 @@ void VideoStreamPlayer::_notification(int p_notification) { } } break; + case NOTIFICATION_UNSUSPENDED: { + if (get_tree()->is_paused()) { + break; + } + [[fallthrough]]; + } + case NOTIFICATION_UNPAUSED: { if (paused_from_tree) { paused_from_tree = false; |