diff options
Diffstat (limited to 'editor/editor_inspector.cpp')
-rw-r--r-- | editor/editor_inspector.cpp | 412 |
1 files changed, 255 insertions, 157 deletions
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index d19032da8b..d5cd61d792 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -34,10 +34,10 @@ #include "core/os/keyboard.h" #include "dictionary_property_edit.h" #include "editor/doc_tools.h" -#include "editor_feature_profile.h" -#include "editor_node.h" -#include "editor_scale.h" -#include "editor_settings.h" +#include "editor/editor_feature_profile.h" +#include "editor/editor_node.h" +#include "editor/editor_scale.h" +#include "editor/editor_settings.h" #include "multi_node_edit.h" #include "scene/property_utils.h" #include "scene/resources/packed_scene.h" @@ -251,14 +251,14 @@ void EditorProperty::_notification(int p_what) { } else { color = get_theme_color(is_read_only() ? SNAME("readonly_color") : SNAME("property_color")); } - if (label.find(".") != -1) { + if (label.contains(".")) { // FIXME: Move this to the project settings editor, as this is only used // for project settings feature tag overrides. color.a = 0.5; } int ofs = get_theme_constant(SNAME("font_offset")); - int text_limit = text_size; + int text_limit = text_size - ofs; if (checkable) { Ref<Texture2D> checkbox; @@ -280,8 +280,9 @@ void EditorProperty::_notification(int p_what) { } else { draw_texture(checkbox, check_rect.position, color2); } - ofs += get_theme_constant(SNAME("hseparator"), SNAME("Tree")) + checkbox->get_width() + get_theme_constant(SNAME("hseparation"), SNAME("CheckBox")); - text_limit -= ofs; + int check_ofs = get_theme_constant(SNAME("hseparator"), SNAME("Tree")) + checkbox->get_width() + get_theme_constant(SNAME("hseparation"), SNAME("CheckBox")); + ofs += check_ofs; + text_limit -= check_ofs; } else { check_rect = Rect2(); } @@ -289,7 +290,7 @@ void EditorProperty::_notification(int p_what) { if (can_revert && !is_read_only()) { Ref<Texture2D> reload_icon = get_theme_icon(SNAME("ReloadSmall"), SNAME("EditorIcons")); text_limit -= reload_icon->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree")) * 2; - revert_rect = Rect2(text_limit + get_theme_constant(SNAME("hseparator"), SNAME("Tree")), (size.height - reload_icon->get_height()) / 2, reload_icon->get_width(), reload_icon->get_height()); + revert_rect = Rect2(ofs + text_limit, (size.height - reload_icon->get_height()) / 2, reload_icon->get_width(), reload_icon->get_height()); Color color2(1, 1, 1); if (revert_hover) { @@ -833,30 +834,42 @@ void EditorProperty::_update_pin_flags() { } } -Control *EditorProperty::make_custom_tooltip(const String &p_text) const { - tooltip_text = p_text; +static Control *make_help_bit(const String &p_text, bool p_property) { EditorHelpBit *help_bit = memnew(EditorHelpBit); - //help_bit->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE); - String text; PackedStringArray slices = p_text.split("::", false); - if (!slices.is_empty()) { - String property_name = slices[0].strip_edges(); - text = TTR("Property:") + " [u][b]" + property_name + "[/b][/u]"; + if (slices.is_empty()) { + // Shouldn't happen here, but just in case pass the text along. + help_bit->set_text(p_text); + return help_bit; + } - if (slices.size() > 1) { - String property_doc = slices[1].strip_edges(); - if (property_name != property_doc) { - text += "\n" + property_doc; - } + String property_name = slices[0].strip_edges(); + String text; + if (p_property) { + text = TTR("Property:") + " "; + } + text += "[u][b]" + property_name + "[/b][/u]"; + + if (slices.size() > 1) { + String property_doc = slices[1].strip_edges(); + if (property_name != property_doc) { + text += "\n" + property_doc; } - help_bit->call_deferred(SNAME("set_text"), text); //hack so it uses proper theme once inside scene + } else { + text += "\n[i]" + TTR("No description.") + "[/i]"; } + help_bit->set_text(text); return help_bit; } +Control *EditorProperty::make_custom_tooltip(const String &p_text) const { + tooltip_text = p_text; + return make_help_bit(p_text, true); +} + String EditorProperty::get_tooltip_text() const { return tooltip_text; } @@ -919,6 +932,7 @@ void EditorProperty::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_warning"), "set_draw_warning", "is_draw_warning"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keying"), "set_keying", "is_keying"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deletable"), "set_deletable", "is_deletable"); + ADD_SIGNAL(MethodInfo("property_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); ADD_SIGNAL(MethodInfo("multiple_properties_changed", PropertyInfo(Variant::PACKED_STRING_ARRAY, "properties"), PropertyInfo(Variant::ARRAY, "value"))); ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING_NAME, "property"))); @@ -1093,25 +1107,7 @@ void EditorInspectorCategory::_notification(int p_what) { Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) const { tooltip_text = p_text; - EditorHelpBit *help_bit = memnew(EditorHelpBit); - help_bit->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); - help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE); - - PackedStringArray slices = p_text.split("::", false); - if (!slices.is_empty()) { - String property_name = slices[0].strip_edges(); - String text = "[u][b]" + property_name + "[/b][/u]"; - - if (slices.size() > 1) { - String property_doc = slices[1].strip_edges(); - if (property_name != property_doc) { - text += "\n" + property_doc; - } - } - help_bit->call_deferred(SNAME("set_text"), text); //hack so it uses proper theme once inside scene - } - - return help_bit; + return make_help_bit(p_text, false); } Size2 EditorInspectorCategory::get_minimum_size() const { @@ -1186,6 +1182,15 @@ void EditorInspectorSection::_notification(int p_what) { header_height += get_theme_constant(SNAME("vseparation"), SNAME("Tree")); int inspector_margin = get_theme_constant(SNAME("inspector_margin"), SNAME("Editor")); + int section_indent_size = get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection")); + if (indent_depth > 0 && section_indent_size > 0) { + inspector_margin += indent_depth * section_indent_size; + } + Ref<StyleBoxFlat> section_indent_style = get_theme_stylebox(SNAME("indent_box"), SNAME("EditorInspectorSection")); + if (indent_depth > 0 && section_indent_style.is_valid()) { + inspector_margin += section_indent_style->get_margin(SIDE_LEFT) + section_indent_style->get_margin(SIDE_RIGHT); + } + Size2 size = get_size() - Vector2(inspector_margin, 0); Vector2 offset = Vector2(is_layout_rtl() ? 0 : inspector_margin, header_height); for (int i = 0; i < get_child_count(); i++) { @@ -1221,14 +1226,31 @@ void EditorInspectorSection::_notification(int p_what) { bool rtl = is_layout_rtl(); - // Compute the height of the section header. + // Compute the height and width of the section header. int header_height = font->get_height(font_size); if (arrow.is_valid()) { header_height = MAX(header_height, arrow->get_height()); } header_height += get_theme_constant(SNAME("vseparation"), SNAME("Tree")); - Rect2 header_rect = Rect2(Vector2(), Vector2(get_size().width, header_height)); + int section_indent = 0; + int section_indent_size = get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection")); + if (indent_depth > 0 && section_indent_size > 0) { + section_indent = indent_depth * section_indent_size; + } + Ref<StyleBoxFlat> section_indent_style = get_theme_stylebox(SNAME("indent_box"), SNAME("EditorInspectorSection")); + if (indent_depth > 0 && section_indent_style.is_valid()) { + section_indent += section_indent_style->get_margin(SIDE_LEFT) + section_indent_style->get_margin(SIDE_RIGHT); + } + + int header_width = get_size().width - section_indent; + int header_offset_x = 0.0; + if (!rtl) { + header_offset_x += section_indent; + } + + // Draw header area. + Rect2 header_rect = Rect2(Vector2(header_offset_x, 0.0), Vector2(header_width, header_height)); Color c = bg_color; c.a *= 0.4; if (foldable && header_rect.has_point(get_local_mouse_position())) { @@ -1236,24 +1258,46 @@ void EditorInspectorSection::_notification(int p_what) { } draw_rect(header_rect, c); + // Draw header title and folding arrow. const int arrow_margin = 2; const int arrow_width = arrow.is_valid() ? arrow->get_width() : 0; Color color = get_theme_color(SNAME("font_color")); - float text_width = get_size().width - Math::round(arrow_width + arrow_margin * EDSCALE); - draw_string(font, Point2(rtl ? 0 : Math::round(arrow_width + arrow_margin * EDSCALE), font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2).floor(), label, rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT, text_width, font_size, color); + float text_width = get_size().width - Math::round(arrow_width + arrow_margin * EDSCALE) - section_indent; + Point2 text_offset = Point2(0, font->get_ascent(font_size) + (header_height - font->get_height(font_size)) / 2); + HorizontalAlignment text_align = HORIZONTAL_ALIGNMENT_LEFT; + if (rtl) { + text_align = HORIZONTAL_ALIGNMENT_RIGHT; + } else { + text_offset.x = section_indent + Math::round(arrow_width + arrow_margin * EDSCALE); + } + draw_string(font, text_offset.floor(), label, text_align, text_width, font_size, color); if (arrow.is_valid()) { + Point2 arrow_position = Point2(0, (header_height - arrow->get_height()) / 2); if (rtl) { - draw_texture(arrow, Point2(get_size().width - arrow->get_width() - Math::round(arrow_margin * EDSCALE), (header_height - arrow->get_height()) / 2).floor()); + arrow_position.x = get_size().width - section_indent - arrow->get_width() - Math::round(arrow_margin * EDSCALE); } else { - draw_texture(arrow, Point2(Math::round(arrow_margin * EDSCALE), (header_height - arrow->get_height()) / 2).floor()); + arrow_position.x = section_indent + Math::round(arrow_margin * EDSCALE); } + draw_texture(arrow, arrow_position.floor()); } + // Draw dropping highlight. if (dropping && !vbox->is_visible_in_tree()) { Color accent_color = get_theme_color(SNAME("accent_color"), SNAME("Editor")); draw_rect(Rect2(Point2(), get_size()), accent_color, false); } + + // Draw section indentation. + if (section_indent_style.is_valid() && section_indent > 0) { + Rect2 indent_rect = Rect2(Vector2(), Vector2(indent_depth * section_indent_size, get_size().height)); + if (rtl) { + indent_rect.position.x = get_size().width - section_indent + section_indent_style->get_margin(SIDE_RIGHT); + } else { + indent_rect.position.x = section_indent_style->get_margin(SIDE_LEFT); + } + draw_style_box(section_indent_style, indent_rect); + } } break; case NOTIFICATION_DRAG_BEGIN: { Dictionary dd = get_viewport()->gui_get_drag_data(); @@ -1316,15 +1360,25 @@ Size2 EditorInspectorSection::get_minimum_size() const { ms.height += font->get_height(font_size) + get_theme_constant(SNAME("vseparation"), SNAME("Tree")); ms.width += get_theme_constant(SNAME("inspector_margin"), SNAME("Editor")); + int section_indent_size = get_theme_constant(SNAME("indent_size"), SNAME("EditorInspectorSection")); + if (indent_depth > 0 && section_indent_size > 0) { + ms.width += indent_depth * section_indent_size; + } + Ref<StyleBoxFlat> section_indent_style = get_theme_stylebox(SNAME("indent_box"), SNAME("EditorInspectorSection")); + if (indent_depth > 0 && section_indent_style.is_valid()) { + ms.width += section_indent_style->get_margin(SIDE_LEFT) + section_indent_style->get_margin(SIDE_RIGHT); + } + return ms; } -void EditorInspectorSection::setup(const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable) { +void EditorInspectorSection::setup(const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable, int p_indent_depth) { section = p_section; label = p_label; object = p_object; bg_color = p_bg_color; foldable = p_foldable; + indent_depth = p_indent_depth; if (!foldable && !vbox_added) { add_child(vbox); @@ -1406,12 +1460,8 @@ void EditorInspectorSection::_bind_methods() { } EditorInspectorSection::EditorInspectorSection() { - object = nullptr; - foldable = false; vbox = memnew(VBoxContainer); - vbox_added = false; - dropping = false; dropping_unfold_timer = memnew(Timer); dropping_unfold_timer->set_wait_time(0.6); dropping_unfold_timer->set_one_shot(true); @@ -1427,6 +1477,7 @@ EditorInspectorSection::~EditorInspectorSection() { //////////////////////////////////////////////// //////////////////////////////////////////////// + int EditorInspectorArray::_get_array_count() { if (mode == MODE_USE_MOVE_ARRAY_ELEMENT_FUNCTION) { List<PropertyInfo> object_property_list; @@ -1445,31 +1496,8 @@ void EditorInspectorArray::_add_button_pressed() { _move_element(-1, -1); } -void EditorInspectorArray::_first_page_button_pressed() { - emit_signal("page_change_request", 0); -} - -void EditorInspectorArray::_prev_page_button_pressed() { - emit_signal("page_change_request", MAX(0, page - 1)); -} - -void EditorInspectorArray::_page_line_edit_text_submitted(String p_text) { - if (p_text.is_valid_int()) { - int new_page = p_text.to_int() - 1; - new_page = MIN(MAX(0, new_page), max_page); - page_line_edit->set_text(Variant(new_page)); - emit_signal("page_change_request", new_page); - } else { - page_line_edit->set_text(Variant(page)); - } -} - -void EditorInspectorArray::_next_page_button_pressed() { - emit_signal("page_change_request", MIN(max_page, page + 1)); -} - -void EditorInspectorArray::_last_page_button_pressed() { - emit_signal("page_change_request", max_page); +void EditorInspectorArray::_paginator_page_changed(int p_page) { + emit_signal("page_change_request", p_page); } void EditorInspectorArray::_rmb_popup_id_pressed(int p_id) { @@ -1537,7 +1565,7 @@ void EditorInspectorArray::_vbox_visibility_changed() { void EditorInspectorArray::_panel_draw(int p_index) { ERR_FAIL_INDEX(p_index, (int)array_elements.size()); - Ref<StyleBox> style = get_theme_stylebox("Focus", "EditorStyles"); + Ref<StyleBox> style = get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles")); if (!style.is_valid()) { return; } @@ -1641,17 +1669,17 @@ void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) { // Handle page change and update counts. if (p_element_index < 0) { int added_index = p_to_pos < 0 ? count : p_to_pos; - emit_signal("page_change_request", added_index / page_lenght); + emit_signal(SNAME("page_change_request"), added_index / page_length); count += 1; } else if (p_to_pos < 0) { count -= 1; - if (page == max_page && (MAX(0, count - 1) / page_lenght != max_page)) { - emit_signal("page_change_request", max_page - 1); + if (page == max_page && (MAX(0, count - 1) / page_length != max_page)) { + emit_signal(SNAME("page_change_request"), max_page - 1); } } - begin_array_index = page * page_lenght; - end_array_index = MIN(count, (page + 1) * page_lenght); - max_page = MAX(0, count - 1) / page_lenght; + begin_array_index = page * page_length; + end_array_index = MIN(count, (page + 1) * page_length); + max_page = MAX(0, count - 1) / page_length; } void EditorInspectorArray::_clear_array() { @@ -1694,7 +1722,7 @@ void EditorInspectorArray::_clear_array() { undo_redo->commit_action(); // Handle page change and update counts. - emit_signal("page_change_request", 0); + emit_signal(SNAME("page_change_request"), 0); count = 0; begin_array_index = 0; end_array_index = 0; @@ -1767,7 +1795,7 @@ void EditorInspectorArray::_resize_array(int p_size) { undo_redo->commit_action(); // Handle page change and update counts. - emit_signal("page_change_request", 0); + emit_signal(SNAME("page_change_request"), 0); /* count = 0; begin_array_index = 0; @@ -1785,7 +1813,7 @@ Array EditorInspectorArray::_extract_properties_as_array(const List<PropertyInfo int to_char_index = 0; while (to_char_index < str.length()) { - if (str[to_char_index] < '0' || str[to_char_index] > '9') { + if (!is_digit(str[to_char_index])) { break; } to_char_index++; @@ -1865,9 +1893,9 @@ void EditorInspectorArray::_resize_dialog_confirmed() { void EditorInspectorArray::_setup() { // Setup counts. count = _get_array_count(); - begin_array_index = page * page_lenght; - end_array_index = MIN(count, (page + 1) * page_lenght); - max_page = MAX(0, count - 1) / page_lenght; + begin_array_index = page * page_length; + end_array_index = MIN(count, (page + 1) * page_length); + max_page = MAX(0, count - 1) / page_length; array_elements.resize(MAX(0, end_array_index - begin_array_index)); if (page < 0 || page > max_page) { WARN_PRINT(vformat("Invalid page number %d", page)); @@ -1894,7 +1922,7 @@ void EditorInspectorArray::_setup() { ae.margin = memnew(MarginContainer); ae.margin->set_mouse_filter(MOUSE_FILTER_PASS); if (is_inside_tree()) { - Size2 min_size = get_theme_stylebox("Focus", "EditorStyles")->get_minimum_size(); + Size2 min_size = get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles"))->get_minimum_size(); ae.margin->add_theme_constant_override("margin_left", min_size.x / 2); ae.margin->add_theme_constant_override("margin_top", min_size.y / 2); ae.margin->add_theme_constant_override("margin_right", min_size.x / 2); @@ -1925,18 +1953,12 @@ void EditorInspectorArray::_setup() { // Hide/show the add button. add_button->set_visible(page == max_page); - if (max_page == 0) { - hbox_pagination->hide(); - } else { - // Update buttons. - first_page_button->set_disabled(page == 0); - prev_page_button->set_disabled(page == 0); - next_page_button->set_disabled(page == max_page); - last_page_button->set_disabled(page == max_page); - - // Update page number and page count. - page_line_edit->set_text(vformat("%d", page + 1)); - page_count_label->set_text(vformat("/ %d", max_page + 1)); + // Add paginator if there's more than 1 page. + if (max_page > 0) { + EditorPaginator *paginator = memnew(EditorPaginator); + paginator->update(page, max_page); + paginator->connect("page_changed", callable_mp(this, &EditorInspectorArray::_paginator_page_changed)); + vbox->add_child(paginator); } } @@ -1993,7 +2015,7 @@ void EditorInspectorArray::_notification(int p_what) { ArrayElement &ae = array_elements[i]; ae.move_texture_rect->set_texture(get_theme_icon(SNAME("TripleBar"), SNAME("EditorIcons"))); - Size2 min_size = get_theme_stylebox("Focus", "EditorStyles")->get_minimum_size(); + Size2 min_size = get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles"))->get_minimum_size(); ae.margin->add_theme_constant_override("margin_left", min_size.x / 2); ae.margin->add_theme_constant_override("margin_top", min_size.y / 2); ae.margin->add_theme_constant_override("margin_right", min_size.x / 2); @@ -2001,10 +2023,6 @@ void EditorInspectorArray::_notification(int p_what) { } add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - first_page_button->set_icon(get_theme_icon(SNAME("PageFirst"), SNAME("EditorIcons"))); - prev_page_button->set_icon(get_theme_icon(SNAME("PagePrevious"), SNAME("EditorIcons"))); - next_page_button->set_icon(get_theme_icon(SNAME("PageNext"), SNAME("EditorIcons"))); - last_page_button->set_icon(get_theme_icon(SNAME("PageLast"), SNAME("EditorIcons"))); update_minimum_size(); } break; case NOTIFICATION_DRAG_BEGIN: { @@ -2041,7 +2059,7 @@ void EditorInspectorArray::setup_with_move_element_function(Object *p_object, St array_element_prefix = p_array_element_prefix; page = p_page; - EditorInspectorSection::setup(String(p_array_element_prefix) + "_array", p_label, p_object, p_bg_color, p_foldable); + EditorInspectorSection::setup(String(p_array_element_prefix) + "_array", p_label, p_object, p_bg_color, p_foldable, 0); _setup(); } @@ -2052,7 +2070,7 @@ void EditorInspectorArray::setup_with_count_property(Object *p_object, String p_ array_element_prefix = p_array_element_prefix; page = p_page; - EditorInspectorSection::setup(String(count_property) + "_array", p_label, p_object, p_bg_color, p_foldable); + EditorInspectorSection::setup(String(count_property) + "_array", p_label, p_object, p_bg_color, p_foldable, 0); _setup(); } @@ -2097,38 +2115,6 @@ EditorInspectorArray::EditorInspectorArray() { add_button->connect("pressed", callable_mp(this, &EditorInspectorArray::_add_button_pressed)); vbox->add_child(add_button); - hbox_pagination = memnew(HBoxContainer); - hbox_pagination->set_h_size_flags(SIZE_EXPAND_FILL); - hbox_pagination->set_alignment(BoxContainer::ALIGNMENT_CENTER); - vbox->add_child(hbox_pagination); - - first_page_button = memnew(Button); - first_page_button->set_flat(true); - first_page_button->connect("pressed", callable_mp(this, &EditorInspectorArray::_first_page_button_pressed)); - hbox_pagination->add_child(first_page_button); - - prev_page_button = memnew(Button); - prev_page_button->set_flat(true); - prev_page_button->connect("pressed", callable_mp(this, &EditorInspectorArray::_prev_page_button_pressed)); - hbox_pagination->add_child(prev_page_button); - - page_line_edit = memnew(LineEdit); - page_line_edit->connect("text_submitted", callable_mp(this, &EditorInspectorArray::_page_line_edit_text_submitted)); - page_line_edit->add_theme_constant_override("minimum_character_width", 2); - hbox_pagination->add_child(page_line_edit); - - page_count_label = memnew(Label); - hbox_pagination->add_child(page_count_label); - next_page_button = memnew(Button); - next_page_button->set_flat(true); - next_page_button->connect("pressed", callable_mp(this, &EditorInspectorArray::_next_page_button_pressed)); - hbox_pagination->add_child(next_page_button); - - last_page_button = memnew(Button); - last_page_button->set_flat(true); - last_page_button->connect("pressed", callable_mp(this, &EditorInspectorArray::_last_page_button_pressed)); - hbox_pagination->add_child(last_page_button); - control_dropping = memnew(Control); control_dropping->connect("draw", callable_mp(this, &EditorInspectorArray::_control_dropping_draw)); control_dropping->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); @@ -2154,6 +2140,97 @@ EditorInspectorArray::EditorInspectorArray() { //////////////////////////////////////////////// //////////////////////////////////////////////// +void EditorPaginator::_first_page_button_pressed() { + emit_signal("page_changed", 0); +} + +void EditorPaginator::_prev_page_button_pressed() { + emit_signal("page_changed", MAX(0, page - 1)); +} + +void EditorPaginator::_page_line_edit_text_submitted(String p_text) { + if (p_text.is_valid_int()) { + int new_page = p_text.to_int() - 1; + new_page = MIN(MAX(0, new_page), max_page); + page_line_edit->set_text(Variant(new_page)); + emit_signal("page_changed", new_page); + } else { + page_line_edit->set_text(Variant(page)); + } +} + +void EditorPaginator::_next_page_button_pressed() { + emit_signal("page_changed", MIN(max_page, page + 1)); +} + +void EditorPaginator::_last_page_button_pressed() { + emit_signal("page_changed", max_page); +} + +void EditorPaginator::update(int p_page, int p_max_page) { + page = p_page; + max_page = p_max_page; + + // Update buttons. + first_page_button->set_disabled(page == 0); + prev_page_button->set_disabled(page == 0); + next_page_button->set_disabled(page == max_page); + last_page_button->set_disabled(page == max_page); + + // Update page number and page count. + page_line_edit->set_text(vformat("%d", page + 1)); + page_count_label->set_text(vformat("/ %d", max_page + 1)); +} + +void EditorPaginator::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + first_page_button->set_icon(get_theme_icon(SNAME("PageFirst"), SNAME("EditorIcons"))); + prev_page_button->set_icon(get_theme_icon(SNAME("PagePrevious"), SNAME("EditorIcons"))); + next_page_button->set_icon(get_theme_icon(SNAME("PageNext"), SNAME("EditorIcons"))); + last_page_button->set_icon(get_theme_icon(SNAME("PageLast"), SNAME("EditorIcons"))); + } +} + +void EditorPaginator::_bind_methods() { + ADD_SIGNAL(MethodInfo("page_changed", PropertyInfo(Variant::INT, "page"))); +} + +EditorPaginator::EditorPaginator() { + set_h_size_flags(SIZE_EXPAND_FILL); + set_alignment(ALIGNMENT_CENTER); + + first_page_button = memnew(Button); + first_page_button->set_flat(true); + first_page_button->connect("pressed", callable_mp(this, &EditorPaginator::_first_page_button_pressed)); + add_child(first_page_button); + + prev_page_button = memnew(Button); + prev_page_button->set_flat(true); + prev_page_button->connect("pressed", callable_mp(this, &EditorPaginator::_prev_page_button_pressed)); + add_child(prev_page_button); + + page_line_edit = memnew(LineEdit); + page_line_edit->connect("text_submitted", callable_mp(this, &EditorPaginator::_page_line_edit_text_submitted)); + page_line_edit->add_theme_constant_override("minimum_character_width", 2); + add_child(page_line_edit); + + page_count_label = memnew(Label); + add_child(page_count_label); + + next_page_button = memnew(Button); + next_page_button->set_flat(true); + next_page_button->connect("pressed", callable_mp(this, &EditorPaginator::_next_page_button_pressed)); + add_child(next_page_button); + + last_page_button = memnew(Button); + last_page_button->set_flat(true); + last_page_button->connect("pressed", callable_mp(this, &EditorPaginator::_last_page_button_pressed)); + add_child(last_page_button); +} + +//////////////////////////////////////////////// +//////////////////////////////////////////////// + Ref<EditorInspectorPlugin> EditorInspector::inspector_plugins[MAX_PLUGINS]; int EditorInspector::inspector_plugin_count = 0; @@ -2304,7 +2381,7 @@ void EditorInspector::update_tree() { if (property_focusable != -1) { //check focusable is really focusable bool restore_focus = false; - Control *focused = get_focus_owner(); + Control *focused = get_viewport() ? get_viewport()->gui_get_focus_owner() : nullptr; if (focused) { Node *parent = focused->get_parent(); while (parent) { @@ -2354,6 +2431,7 @@ void EditorInspector::update_tree() { String group_base; String subgroup; String subgroup_base; + int section_depth = 0; VBoxContainer *category_vbox = nullptr; List<PropertyInfo> plist; @@ -2378,14 +2456,29 @@ void EditorInspector::update_tree() { if (p.usage & PROPERTY_USAGE_SUBGROUP) { // Setup a property sub-group. subgroup = p.name; - subgroup_base = p.hint_string; + + Vector<String> hint_parts = p.hint_string.split(","); + subgroup_base = hint_parts[0]; + if (hint_parts.size() > 1) { + section_depth = hint_parts[1].to_int(); + } else { + section_depth = 0; + } continue; } else if (p.usage & PROPERTY_USAGE_GROUP) { // Setup a property group. group = p.name; - group_base = p.hint_string; + + Vector<String> hint_parts = p.hint_string.split(","); + group_base = hint_parts[0]; + if (hint_parts.size() > 1) { + section_depth = hint_parts[1].to_int(); + } else { + section_depth = 0; + } + subgroup = ""; subgroup_base = ""; @@ -2397,6 +2490,7 @@ void EditorInspector::update_tree() { group_base = ""; subgroup = ""; subgroup_base = ""; + section_depth = 0; if (!show_categories) { continue; @@ -2430,7 +2524,7 @@ void EditorInspector::update_tree() { if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) { // If we have a category inside a script, search for the first script with a valid icon. Ref<Script> script = ResourceLoader::load(p.hint_string, "Script"); - String base_type; + StringName base_type; if (script.is_valid()) { base_type = script->get_instance_base_type(); } @@ -2517,7 +2611,7 @@ void EditorInspector::update_tree() { String str = p.name.trim_prefix(array_prefix); int to_char_index = 0; while (to_char_index < str.length()) { - if (str[to_char_index] < '0' || str[to_char_index] > '9') { + if (!is_digit(str[to_char_index])) { break; } to_char_index++; @@ -2571,7 +2665,7 @@ void EditorInspector::update_tree() { } // Get the property label's string. - String property_label_string = (path.find("/") != -1) ? path.substr(path.rfind("/") + 1) : path; + String property_label_string = (path.contains("/")) ? path.substr(path.rfind("/") + 1) : path; if (capitalize_paths) { // Capitalize paths. int dot = property_label_string.find("."); @@ -2595,7 +2689,7 @@ void EditorInspector::update_tree() { // Ignore properties that do not fit the filter. if (use_filter && !filter.is_empty()) { - if (!filter.is_subsequence_ofn(path) && !filter.is_subsequence_ofn(property_label_string) && property_prefix.to_lower().find(filter.to_lower()) == -1) { + if (!filter.is_subsequence_ofn(path) && !filter.is_subsequence_ofn(property_label_string) && !property_prefix.to_lower().contains(filter.to_lower())) { continue; } } @@ -2638,7 +2732,7 @@ void EditorInspector::update_tree() { Color c = sscolor; c.a /= level; - section->setup(acc_path, component, object, c, use_folding); + section->setup(acc_path, component, object, c, use_folding, section_depth); // Add editors at the start of a group. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { @@ -2669,7 +2763,7 @@ void EditorInspector::update_tree() { array_element_prefix = p.class_name; editor_inspector_array = memnew(EditorInspectorArray); - String array_label = (path.find("/") != -1) ? path.substr(path.rfind("/") + 1) : path; + String array_label = path.contains("/") ? path.substr(path.rfind("/") + 1) : path; array_label = property_label_string.capitalize(); int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0; editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding); @@ -2908,7 +3002,7 @@ void EditorInspector::edit(Object *p_object) { object->connect("property_list_changed", callable_mp(this, &EditorInspector::_changed_callback)); update_tree(); } - emit_signal("edited_object_changed"); + emit_signal(SNAME("edited_object_changed")); } void EditorInspector::set_keying(bool p_active) { @@ -3025,7 +3119,7 @@ void EditorInspector::_update_inspector_bg() { n = n->get_parent(); } count_subinspectors = MIN(15, count_subinspectors); - add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg" + itos(count_subinspectors), "Editor")); + add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg" + itos(count_subinspectors), SNAME("Editor"))); } else { add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); } @@ -3484,10 +3578,14 @@ void EditorInspector::_update_script_class_properties(const Object &p_object, Li String path = s->get_path(); String name = EditorNode::get_editor_data().script_class_get_name(path); if (name.is_empty()) { - if (!s->is_built_in()) { - name = path.get_file(); + if (s->is_built_in()) { + if (s->get_name().is_empty()) { + name = TTR("Built-in script"); + } else { + name = vformat("%s (%s)", s->get_name(), TTR("Built-in")); + } } else { - name = TTR("Built-in script"); + name = path.get_file(); } } @@ -3543,7 +3641,7 @@ void EditorInspector::_bind_methods() { ADD_SIGNAL(MethodInfo("property_selected", PropertyInfo(Variant::STRING, "property"))); ADD_SIGNAL(MethodInfo("property_keyed", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), PropertyInfo(Variant::BOOL, "advance"))); ADD_SIGNAL(MethodInfo("property_deleted", PropertyInfo(Variant::STRING, "property"))); - ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::OBJECT, "res"), PropertyInfo(Variant::STRING, "prop"))); + ADD_SIGNAL(MethodInfo("resource_selected", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::STRING, "path"))); ADD_SIGNAL(MethodInfo("object_id_selected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("property_edited", PropertyInfo(Variant::STRING, "property"))); ADD_SIGNAL(MethodInfo("property_toggled", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::BOOL, "checked"))); |