feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -33,6 +33,7 @@
#include "core/os/keyboard.h"
#include "editor/add_metadata_dialog.h"
#include "editor/debugger/editor_debugger_inspector.h"
#include "editor/doc_tools.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_main_screen.h"
@ -252,6 +253,25 @@ void EditorProperty::emit_changed(const StringName &p_property, const Variant &p
void EditorProperty::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
RID ae = get_accessibility_element();
ERR_FAIL_COND(ae.is_null());
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_BUTTON);
DisplayServer::get_singleton()->accessibility_update_set_name(ae, vformat(TTR("Property: %s"), label));
DisplayServer::get_singleton()->accessibility_update_set_value(ae, vformat(TTR("Property: %s"), label));
DisplayServer::get_singleton()->accessibility_update_set_popup_type(ae, DisplayServer::AccessibilityPopupType::POPUP_MENU);
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SHOW_CONTEXT_MENU, callable_mp(this, &EditorProperty::_accessibility_action_menu));
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_CLICK, callable_mp(this, &EditorProperty::_accessibility_action_click));
DisplayServer::get_singleton()->accessibility_update_set_flag(ae, DisplayServer::AccessibilityFlags::FLAG_READONLY, read_only);
if (checkable) {
DisplayServer::get_singleton()->accessibility_update_set_checked(ae, checked);
}
} break;
case NOTIFICATION_SORT_CHILDREN: {
Size2 size = get_size();
Rect2 rect;
@ -578,6 +598,12 @@ void EditorProperty::_notification(int p_what) {
}
} break;
case NOTIFICATION_ENTER_TREE: {
EditorInspector *inspector = get_parent_inspector();
if (inspector) {
inspector = inspector->get_root_inspector();
}
set_shortcut_context(inspector);
if (has_borders) {
get_parent()->connect(SceneStringName(theme_changed), callable_mp(this, &EditorProperty::_update_property_bg));
_update_property_bg();
@ -617,6 +643,16 @@ StringName EditorProperty::get_edited_property() const {
return property;
}
Variant EditorProperty::get_edited_property_display_value() const {
ERR_FAIL_NULL_V(object, Variant());
Control *control = Object::cast_to<Control>(object);
if (checkable && !checked && control && String(property).begins_with("theme_override_")) {
return control->get_used_theme_item(property);
} else {
return get_edited_property_value();
}
}
EditorInspector *EditorProperty::get_parent_inspector() const {
Node *parent = get_parent();
while (parent) {
@ -769,9 +805,7 @@ bool EditorProperty::use_keying_next() const {
List<PropertyInfo> plist;
object->get_property_list(&plist, true);
for (List<PropertyInfo>::Element *I = plist.front(); I; I = I->next()) {
PropertyInfo &p = I->get();
for (const PropertyInfo &p : plist) {
if (p.name == property) {
return (p.usage & PROPERTY_USAGE_KEYING_INCREMENTS);
}
@ -918,6 +952,9 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
if (me.is_valid()) {
Vector2 mpos = me->get_position();
if (bottom_child_rect.has_point(mpos)) {
return; // Makes child EditorProperties behave like sibling nodes when handling mouse events.
}
if (is_layout_rtl()) {
mpos.x = get_size().x - mpos.x;
}
@ -1013,6 +1050,22 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
}
}
void EditorProperty::_accessibility_action_click(const Variant &p_data) {
select();
if (checkable) {
checked = !checked;
queue_redraw();
emit_signal(SNAME("property_checked"), property, checked);
}
}
void EditorProperty::_accessibility_action_menu(const Variant &p_data) {
_update_popup();
menu->set_position(get_screen_position());
menu->reset_size();
menu->popup();
}
void EditorProperty::shortcut_input(const Ref<InputEvent> &p_event) {
if (!selected || !p_event->is_pressed()) {
return;
@ -1250,6 +1303,19 @@ void EditorProperty::menu_option(int p_option) {
emit_signal(SNAME("property_pinned"), property, !pinned);
queue_redraw();
} break;
case MENU_DELETE: {
accept_event();
emit_signal(SNAME("property_deleted"), property);
} break;
case MENU_REVERT_VALUE: {
accept_event();
get_viewport()->gui_release_focus();
bool is_valid_revert = false;
Variant revert_value = EditorPropertyRevert::get_property_revert_value(object, property, &is_valid_revert);
ERR_FAIL_COND(!is_valid_revert);
emit_changed(_get_revert_property(), revert_value);
update_property();
} break;
case MENU_OPEN_DOCUMENTATION: {
ScriptEditor::get_singleton()->goto_help(doc_path);
EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_SCRIPT);
@ -1343,6 +1409,8 @@ void EditorProperty::_bind_methods() {
}
EditorProperty::EditorProperty() {
set_focus_mode(FOCUS_ACCESSIBILITY);
object = nullptr;
split_ratio = 0.5;
text_size = 0;
@ -1377,6 +1445,7 @@ void EditorProperty::_update_popup() {
menu->add_icon_item(get_editor_theme_icon(SNAME("Unfavorite")), TTR("Unfavorite Property"), MENU_FAVORITE_PROPERTY);
menu->set_item_tooltip(menu->get_item_index(MENU_FAVORITE_PROPERTY), TTR("Make this property be put back at its original place."));
} else {
// TRANSLATORS: This is a menu item to add a property to the favorites.
menu->add_icon_item(get_editor_theme_icon(SNAME("Favorites")), TTR("Favorite Property"), MENU_FAVORITE_PROPERTY);
menu->set_item_tooltip(menu->get_item_index(MENU_FAVORITE_PROPERTY), TTR("Make this property be placed at the top for all objects of this class."));
}
@ -1392,7 +1461,15 @@ void EditorProperty::_update_popup() {
}
menu->set_item_tooltip(menu->get_item_index(MENU_PIN_VALUE), TTR("Pinning a value forces it to be saved even if it's equal to the default."));
}
if (deletable || can_revert) {
menu->add_separator();
if (deletable) {
menu->add_icon_item(get_editor_theme_icon(SNAME("Remove")), TTR("Delete Property"), MENU_PIN_VALUE);
}
if (can_revert) {
menu->add_icon_item(get_editor_theme_icon(SNAME("Reload")), TTR("Revert Value"), MENU_REVERT_VALUE);
}
}
if (!doc_path.is_empty()) {
menu->add_separator();
menu->add_icon_item(get_editor_theme_icon(SNAME("Help")), TTR("Open Documentation"), MENU_OPEN_DOCUMENTATION);
@ -1471,6 +1548,19 @@ void EditorInspectorPlugin::_bind_methods() {
void EditorInspectorCategory::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
RID ae = get_accessibility_element();
ERR_FAIL_COND(ae.is_null());
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_BUTTON);
DisplayServer::get_singleton()->accessibility_update_set_name(ae, vformat(TTR("Category: %s"), label));
DisplayServer::get_singleton()->accessibility_update_set_value(ae, vformat(TTR("Category: %s"), label));
DisplayServer::get_singleton()->accessibility_update_set_popup_type(ae, DisplayServer::AccessibilityPopupType::POPUP_MENU);
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SHOW_CONTEXT_MENU, callable_mp(this, &EditorInspectorCategory::_accessibility_action_menu));
} break;
case NOTIFICATION_THEME_CHANGED: {
if (menu) {
if (is_favorite) {
@ -1524,6 +1614,22 @@ void EditorInspectorCategory::_notification(int p_what) {
}
}
void EditorInspectorCategory::_accessibility_action_menu(const Variant &p_data) {
if (!is_favorite) {
if (!menu) {
menu = memnew(PopupMenu);
menu->add_icon_item(get_editor_theme_icon(SNAME("Help")), TTR("Open Documentation"), MENU_OPEN_DOCS);
add_child(menu);
menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorInspectorCategory::_handle_menu_option));
}
menu->set_item_disabled(menu->get_item_index(MENU_OPEN_DOCS), !EditorHelp::get_doc_data()->class_list.has(doc_class_name));
}
menu->set_position(get_screen_position());
menu->reset_size();
menu->popup();
}
Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) const {
// If it's not a doc tooltip, fallback to the default one.
if (doc_class_name.is_empty()) {
@ -1594,6 +1700,10 @@ void EditorInspectorCategory::gui_input(const Ref<InputEvent> &p_event) {
menu->popup();
}
EditorInspectorCategory::EditorInspectorCategory() {
set_focus_mode(FOCUS_ACCESSIBILITY);
}
////////////////////////////////////////////////
////////////////////////////////////////////////
@ -1637,10 +1747,24 @@ int EditorInspectorSection::_get_header_height() {
void EditorInspectorSection::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
RID ae = get_accessibility_element();
ERR_FAIL_COND(ae.is_null());
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_BUTTON);
DisplayServer::get_singleton()->accessibility_update_set_name(ae, vformat(TTR("Section: %s"), label));
DisplayServer::get_singleton()->accessibility_update_set_value(ae, vformat(TTR("Section: %s"), label));
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_COLLAPSE, callable_mp(this, &EditorInspectorSection::_accessibility_action_collapse));
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_EXPAND, callable_mp(this, &EditorInspectorSection::_accessibility_action_expand));
} break;
case NOTIFICATION_THEME_CHANGED: {
update_minimum_size();
bg_color = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor));
bg_color.a /= level;
int separation = get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector"));
vbox->add_theme_constant_override(SNAME("separation"), separation);
} break;
case NOTIFICATION_SORT_CHILDREN: {
@ -1864,6 +1988,20 @@ void EditorInspectorSection::gui_input(const Ref<InputEvent> &p_event) {
return;
}
Ref<InputEventKey> k = p_event;
if (k.is_valid() && k->is_pressed()) {
if (k->is_action("ui_accept", true)) {
accept_event();
bool should_unfold = !object->editor_is_section_unfolded(section);
if (should_unfold) {
unfold();
} else {
fold();
}
}
}
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
if (object->editor_is_section_unfolded(section)) {
@ -1885,6 +2023,15 @@ void EditorInspectorSection::gui_input(const Ref<InputEvent> &p_event) {
} else if (mb.is_valid() && !mb->is_pressed()) {
queue_redraw();
}
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
int header_height = _get_header_height();
Vector2 previous = mm->get_position() - mm->get_relative();
if ((mm->get_position().y >= header_height) != (previous.y >= header_height)) {
queue_redraw();
}
}
}
String EditorInspectorSection::get_section() const {
@ -1895,6 +2042,14 @@ VBoxContainer *EditorInspectorSection::get_vbox() {
return vbox;
}
void EditorInspectorSection::_accessibility_action_collapse(const Variant &p_data) {
fold();
}
void EditorInspectorSection::_accessibility_action_expand(const Variant &p_data) {
unfold();
}
void EditorInspectorSection::unfold() {
if (!foldable) {
return;
@ -1926,6 +2081,12 @@ void EditorInspectorSection::set_bg_color(const Color &p_bg_color) {
queue_redraw();
}
void EditorInspectorSection::reset_timer() {
if (dropping_for_unfold && !dropping_unfold_timer->is_stopped()) {
dropping_unfold_timer->start();
}
}
bool EditorInspectorSection::has_revertable_properties() const {
return !revertable_properties.is_empty();
}
@ -1950,6 +2111,8 @@ void EditorInspectorSection::_bind_methods() {
}
EditorInspectorSection::EditorInspectorSection() {
set_focus_mode(FOCUS_ACCESSIBILITY);
vbox = memnew(VBoxContainer);
dropping_unfold_timer = memnew(Timer);
@ -2063,6 +2226,18 @@ void EditorInspectorArray::_panel_draw(int p_index) {
}
}
void EditorInspectorArray::_panel_gui_focus(int p_index) {
array_elements[p_index].panel->queue_redraw();
selected = p_index;
}
void EditorInspectorArray::_panel_gui_unfocus(int p_index) {
array_elements[p_index].panel->queue_redraw();
if (selected == p_index) {
selected = -1;
}
}
void EditorInspectorArray::_panel_gui_input(Ref<InputEvent> p_event, int p_index) {
ERR_FAIL_INDEX(p_index, (int)array_elements.size());
@ -2087,13 +2262,22 @@ void EditorInspectorArray::_panel_gui_input(Ref<InputEvent> p_event, int p_index
popup_array_index_pressed = begin_array_index + p_index;
rmb_popup->set_item_disabled(OPTION_MOVE_UP, popup_array_index_pressed == 0);
rmb_popup->set_item_disabled(OPTION_MOVE_DOWN, popup_array_index_pressed == count - 1);
rmb_popup->set_position(get_screen_position() + mb->get_position());
rmb_popup->set_position(array_elements[p_index].panel->get_screen_position() + mb->get_position());
rmb_popup->reset_size();
rmb_popup->popup();
}
}
}
void EditorInspectorArray::show_menu(int p_index, const Vector2 &p_offset) {
popup_array_index_pressed = begin_array_index + p_index;
rmb_popup->set_item_disabled(OPTION_MOVE_UP, popup_array_index_pressed == 0);
rmb_popup->set_item_disabled(OPTION_MOVE_DOWN, popup_array_index_pressed == count - 1);
rmb_popup->set_position(get_screen_position() + p_offset);
rmb_popup->reset_size();
rmb_popup->popup();
}
void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) {
String action_name;
if (p_element_index < 0) {
@ -2193,10 +2377,8 @@ void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) {
undo_redo->add_undo_property(object, count_property, properties_as_array.size());
for (int i = 0; i < (int)properties_as_array.size(); i++) {
Dictionary d = Dictionary(properties_as_array[i]);
Array keys = d.keys();
for (int j = 0; j < keys.size(); j++) {
String key = keys[j];
undo_redo->add_undo_property(object, vformat(key, i), d[key]);
for (const KeyValue<Variant, Variant> &kv : d) {
undo_redo->add_undo_property(object, vformat(kv.key, i), kv.value);
}
}
@ -2216,10 +2398,8 @@ void EditorInspectorArray::_move_element(int p_element_index, int p_to_pos) {
undo_redo->add_do_property(object, count_property, properties_as_array.size());
for (int i = 0; i < (int)properties_as_array.size(); i++) {
Dictionary d = properties_as_array[i];
Array keys = d.keys();
for (int j = 0; j < keys.size(); j++) {
String key = keys[j];
undo_redo->add_do_property(object, vformat(key, i), d[key]);
for (const KeyValue<Variant, Variant> &kv : d) {
undo_redo->add_do_property(object, vformat(kv.key, i), kv.value);
}
}
}
@ -2270,10 +2450,8 @@ void EditorInspectorArray::_clear_array() {
undo_redo->add_undo_property(object, count_property, count);
for (int i = 0; i < (int)properties_as_array.size(); i++) {
Dictionary d = Dictionary(properties_as_array[i]);
Array keys = d.keys();
for (int j = 0; j < keys.size(); j++) {
String key = keys[j];
undo_redo->add_undo_property(object, vformat(key, i), d[key]);
for (const KeyValue<Variant, Variant> &kv : d) {
undo_redo->add_undo_property(object, vformat(kv.key, i), kv.value);
}
}
@ -2335,10 +2513,8 @@ void EditorInspectorArray::_resize_array(int p_size) {
undo_redo->add_undo_property(object, count_property, count);
for (int i = count - 1; i > p_size - 1; i--) {
Dictionary d = Dictionary(properties_as_array[i]);
Array keys = d.keys();
for (int j = 0; j < keys.size(); j++) {
String key = keys[j];
undo_redo->add_undo_property(object, vformat(key, i), d[key]);
for (const KeyValue<Variant, Variant> &kv : d) {
undo_redo->add_undo_property(object, vformat(kv.key, i), kv.value);
}
}
@ -2462,16 +2638,20 @@ void EditorInspectorArray::_setup() {
ArrayElement &ae = array_elements[i];
// Panel and its hbox.
ae.panel = memnew(PanelContainer);
ae.panel = memnew(ArrayPanelContainer);
ae.panel->set_focus_mode(FOCUS_ALL);
ae.panel->set_mouse_filter(MOUSE_FILTER_PASS);
SET_DRAG_FORWARDING_GCD(ae.panel, EditorInspectorArray);
int element_position = begin_array_index + i;
String ae_name = vformat(TTR("Element %d: %s%d*"), element_position, array_element_prefix, element_position);
ae.panel->set_meta("index", element_position);
ae.panel->set_tooltip_text(vformat(TTR("Element %d: %s%d*"), element_position, array_element_prefix, element_position));
ae.panel->connect(SceneStringName(focus_entered), callable_mp((CanvasItem *)ae.panel, &PanelContainer::queue_redraw));
ae.panel->connect(SceneStringName(focus_exited), callable_mp((CanvasItem *)ae.panel, &PanelContainer::queue_redraw));
ae.panel->set_meta("name", ae_name);
ae.panel->set_meta("element", this);
ae.panel->set_tooltip_text(ae_name);
ae.panel->connect(SceneStringName(focus_entered), callable_mp(this, &EditorInspectorArray::_panel_gui_focus).bind(i));
ae.panel->connect(SceneStringName(focus_exited), callable_mp(this, &EditorInspectorArray::_panel_gui_unfocus).bind(i));
ae.panel->connect(SceneStringName(draw), callable_mp(this, &EditorInspectorArray::_panel_draw).bind(i));
ae.panel->connect(SceneStringName(gui_input), callable_mp(this, &EditorInspectorArray::_panel_gui_input).bind(i));
ae.panel->add_theme_style_override(SceneStringName(panel), i % 2 ? odd_style : even_style);
@ -2504,6 +2684,7 @@ void EditorInspectorArray::_setup() {
if (element_position > 0) {
ae.move_up = memnew(Button);
ae.move_up->set_accessibility_name(TTRC("Move Up"));
ae.move_up->set_button_icon(get_editor_theme_icon(SNAME("MoveUp")));
ae.move_up->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorArray::_move_element).bind(element_position, element_position - 1));
move_vbox->add_child(ae.move_up);
@ -2520,6 +2701,7 @@ void EditorInspectorArray::_setup() {
if (element_position < count - 1) {
ae.move_down = memnew(Button);
ae.move_down->set_accessibility_name(TTRC("Move Down"));
ae.move_down->set_button_icon(get_editor_theme_icon(SNAME("MoveDown")));
ae.move_down->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorArray::_move_element).bind(element_position, element_position + 2));
move_vbox->add_child(ae.move_down);
@ -2544,6 +2726,7 @@ void EditorInspectorArray::_setup() {
if (!unresizable) {
ae.erase = memnew(Button);
ae.erase->set_accessibility_name(TTRC("Remove"));
ae.erase->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
ae.erase->set_v_size_flags(SIZE_SHRINK_CENTER);
ae.erase->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorArray::_remove_item).bind(element_position));
@ -2584,7 +2767,7 @@ void EditorInspectorArray::drop_data_fw(const Point2 &p_point, const Variant &p_
Dictionary dict = p_data;
int to_drop = dict["index"];
int drop_position = _drop_position();
int drop_position = (p_point == Vector2(Math::INF, Math::INF)) ? selected : _drop_position();
if (drop_position < 0) {
return;
}
@ -2602,7 +2785,7 @@ bool EditorInspectorArray::can_drop_data_fw(const Point2 &p_point, const Variant
return false;
}
Dictionary dict = p_data;
int drop_position = _drop_position();
int drop_position = (p_point == Vector2(Math::INF, Math::INF)) ? selected : _drop_position();
if (!dict.has("type") || dict["type"] != "property_array_element" || String(dict["property_array_prefix"]) != array_element_prefix || drop_position < 0) {
return false;
}
@ -2614,8 +2797,45 @@ bool EditorInspectorArray::can_drop_data_fw(const Point2 &p_point, const Variant
return drop_array_index != moved_array_index && drop_array_index - 1 != moved_array_index;
}
void ArrayPanelContainer::_accessibility_action_menu(const Variant &p_data) {
EditorInspectorArray *el = Object::cast_to<EditorInspectorArray>(get_meta("element"));
if (el) {
int index = get_meta("index");
el->show_menu(index, Vector2());
}
}
void ArrayPanelContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
RID ae = get_accessibility_element();
ERR_FAIL_COND(ae.is_null());
DisplayServer::get_singleton()->accessibility_update_set_role(ae, DisplayServer::AccessibilityRole::ROLE_BUTTON);
DisplayServer::get_singleton()->accessibility_update_set_name(ae, get_meta("text"));
DisplayServer::get_singleton()->accessibility_update_set_value(ae, get_meta("text"));
DisplayServer::get_singleton()->accessibility_update_set_popup_type(ae, DisplayServer::AccessibilityPopupType::POPUP_MENU);
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_SHOW_CONTEXT_MENU, callable_mp(this, &ArrayPanelContainer::_accessibility_action_menu));
} break;
}
}
ArrayPanelContainer::ArrayPanelContainer() {
set_focus_mode(FOCUS_ACCESSIBILITY);
}
void EditorInspectorArray::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
RID ae = get_accessibility_element();
ERR_FAIL_COND(ae.is_null());
DisplayServer::get_singleton()->accessibility_update_set_name(ae, vformat(TTR("Array: %s"), get_label()));
DisplayServer::get_singleton()->accessibility_update_set_value(ae, vformat(TTR("Array: %s"), get_label()));
} break;
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
Color color = get_theme_color(SNAME("dark_color_1"), EditorStringName(Editor));
@ -2715,12 +2935,11 @@ VBoxContainer *EditorInspectorArray::get_vbox(int p_index) {
EditorInspectorArray::EditorInspectorArray(bool p_read_only) {
read_only = p_read_only;
set_mouse_filter(Control::MOUSE_FILTER_STOP);
odd_style.instantiate();
even_style.instantiate();
rmb_popup = memnew(PopupMenu);
rmb_popup->set_accessibility_name(TTRC("Move"));
rmb_popup->add_item(TTR("Move Up"), OPTION_MOVE_UP);
rmb_popup->add_item(TTR("Move Down"), OPTION_MOVE_DOWN);
rmb_popup->add_separator();
@ -2758,6 +2977,7 @@ EditorInspectorArray::EditorInspectorArray(bool p_read_only) {
resize_dialog->add_child(resize_dialog_vbox);
new_size_spin_box = memnew(SpinBox);
new_size_spin_box->set_accessibility_name(TTRC("Size"));
new_size_spin_box->set_max(16384);
new_size_spin_box->connect(SceneStringName(value_changed), callable_mp(this, &EditorInspectorArray::_new_size_spin_box_value_changed));
new_size_spin_box->get_line_edit()->connect(SceneStringName(text_submitted), callable_mp(this, &EditorInspectorArray::_new_size_spin_box_text_submitted));
@ -2833,16 +3053,19 @@ EditorPaginator::EditorPaginator() {
set_alignment(ALIGNMENT_CENTER);
first_page_button = memnew(Button);
first_page_button->set_accessibility_name(TTRC("First Page"));
first_page_button->set_flat(true);
first_page_button->connect(SceneStringName(pressed), callable_mp(this, &EditorPaginator::_first_page_button_pressed));
add_child(first_page_button);
prev_page_button = memnew(Button);
prev_page_button->set_accessibility_name(TTRC("Previuos Page"));
prev_page_button->set_flat(true);
prev_page_button->connect(SceneStringName(pressed), callable_mp(this, &EditorPaginator::_prev_page_button_pressed));
add_child(prev_page_button);
page_line_edit = memnew(LineEdit);
page_line_edit->set_accessibility_name(TTRC("Page"));
page_line_edit->connect(SceneStringName(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);
@ -2851,11 +3074,13 @@ EditorPaginator::EditorPaginator() {
add_child(page_count_label);
next_page_button = memnew(Button);
prev_page_button->set_accessibility_name(TTRC("Next Page"));
next_page_button->set_flat(true);
next_page_button->connect(SceneStringName(pressed), callable_mp(this, &EditorPaginator::_next_page_button_pressed));
add_child(next_page_button);
last_page_button = memnew(Button);
last_page_button->set_accessibility_name(TTRC("Last Page"));
last_page_button->set_flat(true);
last_page_button->connect(SceneStringName(pressed), callable_mp(this, &EditorPaginator::_last_page_button_pressed));
add_child(last_page_button);
@ -2968,7 +3193,7 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, EditorIn
ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned));
ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected));
ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed));
ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), CONNECT_DEFERRED);
ep->connect("resource_selected", callable_mp(get_root_inspector(), &EditorInspector::_resource_selected), CONNECT_DEFERRED);
ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), CONNECT_DEFERRED);
if (F.properties.size()) {
@ -3040,15 +3265,21 @@ bool EditorInspector::_is_property_disabled_by_feature_profile(const StringName
}
void EditorInspector::update_tree() {
if (!object) {
return;
}
bool root_inspector_was_following_focus = get_root_inspector()->is_following_focus();
if (root_inspector_was_following_focus) {
// Temporarily disable focus following on the root inspector to avoid jumping while the inspector is updating.
get_root_inspector()->set_follow_focus(false);
}
// Store currently selected and focused elements to restore after the update.
// TODO: Can be useful to store more context for the focusable, such as the caret position in LineEdit.
StringName current_selected = property_selected;
int current_focusable = -1;
// Temporarily disable focus following on the root inspector to avoid jumping while the inspector is updating.
bool was_following = get_root_inspector()->is_following_focus();
get_root_inspector()->set_follow_focus(false);
if (property_focusable != -1) {
// Check that focusable is actually focusable.
bool restore_focus = false;
@ -3070,14 +3301,9 @@ void EditorInspector::update_tree() {
}
}
// Only hide plugins if we are not editing any object.
// This should be handled outside of the update_tree call anyway (see EditorInspector::edit), but might as well keep it safe.
_clear(!object);
if (!object) {
get_root_inspector()->set_follow_focus(was_following);
return;
}
// The call here is for the edited object that has not changed, but the tree needs to be updated (for example, the object's property list has been modified).
// Since the edited object has not changed, there is no need to hide the plugin at this time.
_clear(false);
List<Ref<EditorInspectorPlugin>> valid_plugins;
@ -3132,13 +3358,14 @@ void EditorInspector::update_tree() {
Color sscolor = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor));
bool sub_inspectors_enabled = EDITOR_GET("interface/inspector/open_resources_in_current_inspector");
// Get the lists of editors to add the beginning.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_begin(object);
_parse_added_editors(begin_vbox, nullptr, ped);
}
if (begin_vbox->get_child_count()) {
if (!valid_plugins.is_empty()) {
begin_vbox->show();
// Get the lists of editors to add the beginning.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_begin(object);
_parse_added_editors(begin_vbox, nullptr, ped);
}
}
StringName doc_name;
@ -3440,6 +3667,8 @@ void EditorInspector::update_tree() {
// Recreate the category vbox if it was reset.
if (category_vbox == nullptr) {
category_vbox = memnew(VBoxContainer);
int separation = get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector"));
category_vbox->add_theme_constant_override(SNAME("separation"), separation);
category_vbox->hide();
main_vbox->add_child(category_vbox);
}
@ -3467,6 +3696,7 @@ void EditorInspector::update_tree() {
if (!vbox_per_path[root_vbox].has(acc_path)) {
// If the section does not exists, create it.
EditorInspectorSection *section = memnew(EditorInspectorSection);
get_root_inspector()->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(section, &EditorInspectorSection::reset_timer).unbind(1));
current_vbox->add_child(section);
sections.push_back(section);
@ -3535,9 +3765,9 @@ void EditorInspector::update_tree() {
String swap_method;
for (int i = (p.type == Variant::NIL ? 1 : 2); i < class_name_components.size(); i++) {
if (class_name_components[i].begins_with("page_size") && class_name_components[i].get_slice_count("=") == 2) {
page_size = class_name_components[i].get_slice("=", 1).to_int();
page_size = class_name_components[i].get_slicec('=', 1).to_int();
} else if (class_name_components[i].begins_with("add_button_text") && class_name_components[i].get_slice_count("=") == 2) {
add_button_text = class_name_components[i].get_slice("=", 1).strip_edges();
add_button_text = class_name_components[i].get_slicec('=', 1).strip_edges();
} else if (class_name_components[i] == "static") {
movable = false;
} else if (class_name_components[i] == "const") {
@ -3547,7 +3777,7 @@ void EditorInspector::update_tree() {
} else if (class_name_components[i] == "unfoldable") {
foldable = false;
} else if (class_name_components[i].begins_with("swap_method") && class_name_components[i].get_slice_count("=") == 2) {
swap_method = class_name_components[i].get_slice("=", 1).strip_edges();
swap_method = class_name_components[i].get_slicec('=', 1).strip_edges();
}
}
@ -3807,7 +4037,7 @@ void EditorInspector::update_tree() {
ep->connect("property_pinned", callable_mp(this, &EditorInspector::_property_pinned));
ep->connect("selected", callable_mp(this, &EditorInspector::_property_selected));
ep->connect("multiple_properties_changed", callable_mp(this, &EditorInspector::_multiple_properties_changed));
ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), CONNECT_DEFERRED);
ep->connect("resource_selected", callable_mp(get_root_inspector(), &EditorInspector::_resource_selected), CONNECT_DEFERRED);
ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), CONNECT_DEFERRED);
if (use_doc_hints) {
@ -3867,6 +4097,7 @@ void EditorInspector::update_tree() {
}
EditorInspectorSection *section = memnew(EditorInspectorSection);
get_root_inspector()->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(section, &EditorInspectorSection::reset_timer).unbind(1));
favorites_groups_vbox->add_child(section);
parent_vbox = section->get_vbox();
section->setup("", section_name, object, sscolor, false);
@ -3886,6 +4117,7 @@ void EditorInspector::update_tree() {
}
EditorInspectorSection *section = memnew(EditorInspectorSection);
get_root_inspector()->get_v_scroll_bar()->connect(SceneStringName(value_changed), callable_mp(section, &EditorInspectorSection::reset_timer).unbind(1));
vbox->add_child(section);
vbox = section->get_vbox();
section->setup("", section_name, object, sscolor, false);
@ -3918,8 +4150,9 @@ void EditorInspector::update_tree() {
}
// Clean up empty sections.
for (List<EditorInspectorSection *>::Element *I = sections.back(); I; I = I->prev()) {
for (List<EditorInspectorSection *>::Element *I = sections.back(); I;) {
EditorInspectorSection *section = I->get();
I = I->prev(); // Note: Advance before erasing element.
if (section->get_vbox()->get_child_count() == 0) {
sections.erase(section);
vbox_per_path[main_vbox].erase(section->get_section());
@ -3954,7 +4187,9 @@ void EditorInspector::update_tree() {
EditorNode::get_singleton()->hide_unused_editors();
}
get_root_inspector()->set_follow_focus(was_following);
if (root_inspector_was_following_focus) {
get_root_inspector()->set_follow_focus(true);
}
}
void EditorInspector::update_property(const String &p_prop) {
@ -4271,6 +4506,10 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
Object::cast_to<MultiNodeEdit>(object)->set_property_field(p_name, p_value, p_changed_field);
_edit_request_change(object, p_name);
emit_signal(_prop_edited, p_name);
} else if (Object::cast_to<EditorDebuggerRemoteObjects>(object)) {
Object::cast_to<EditorDebuggerRemoteObjects>(object)->set_property_field(p_name, p_value, p_changed_field);
_edit_request_change(object, p_name);
emit_signal(_prop_edited, p_name);
} else {
undo_redo->create_action(vformat(TTR("Set %s"), p_name), UndoRedo::MERGE_ENDS);
undo_redo->add_do_property(object, p_name, p_value);
@ -4450,13 +4689,26 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
_edit_set(p_path, Variant(), false, "");
} else {
Variant to_create;
List<PropertyInfo> pinfo;
object->get_property_list(&pinfo);
for (const PropertyInfo &E : pinfo) {
if (E.name == p_path) {
Callable::CallError ce;
Variant::construct(E.type, to_create, nullptr, 0, ce);
break;
Control *control = Object::cast_to<Control>(object);
bool skip = false;
if (control && p_path.begins_with("theme_override_")) {
to_create = control->get_used_theme_item(p_path);
Ref<Resource> resource = to_create;
if (resource.is_valid()) {
to_create = resource->duplicate();
}
skip = true;
}
if (!skip) {
List<PropertyInfo> pinfo;
object->get_property_list(&pinfo);
for (const PropertyInfo &E : pinfo) {
if (E.name == p_path) {
Callable::CallError ce;
Variant::construct(E.type, to_create, nullptr, 0, ce);
break;
}
}
}
_edit_set(p_path, to_create, false, "");
@ -4528,14 +4780,6 @@ void EditorInspector::_node_removed(Node *p_node) {
}
}
void EditorInspector::_gui_focus_changed(Control *p_control) {
if (!is_visible_in_tree() && !is_following_focus()) {
return;
}
// Don't follow focus when the inspector nor any of its children is focused. Prevents potential jumping when gaining focus.
set_follow_focus(has_focus() || child_has_focus());
}
void EditorInspector::_update_current_favorites() {
current_favorites.clear();
if (!can_favorite) {
@ -4608,7 +4852,7 @@ void EditorInspector::_set_property_favorited(const String &p_path, bool p_favor
String theme_property;
if (p_path.begins_with("theme_override_")) {
theme_property = p_path.get_slice("/", 1);
theme_property = p_path.get_slicec('/', 1);
}
while (!validate_name.is_empty()) {
@ -4712,9 +4956,25 @@ void EditorInspector::_clear_current_favorites() {
update_tree();
}
void EditorInspector::_update_theme() {
updating_theme = true;
add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));
updating_theme = false;
}
void EditorInspector::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED: {
if (property_name_style == EditorPropertyNameProcessor::STYLE_LOCALIZED) {
update_tree_pending = true;
}
} break;
case NOTIFICATION_THEME_CHANGED: {
if (updating_theme) {
break;
}
favorites_category->icon = get_editor_theme_icon(SNAME("Favorites"));
int separation = get_theme_constant(SNAME("v_separation"), SNAME("EditorInspector"));
@ -4729,14 +4989,15 @@ void EditorInspector::_notification(int p_what) {
ERR_FAIL_NULL(EditorFeatureProfileManager::get_singleton());
EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", callable_mp(this, &EditorInspector::_feature_profile_changed));
set_process(is_visible_in_tree());
add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));
get_parent()->connect(SceneStringName(theme_changed), callable_mp(this, &EditorInspector::_update_theme));
_update_theme();
if (!is_sub_inspector()) {
get_tree()->connect("node_removed", callable_mp(this, &EditorInspector::_node_removed));
}
} break;
Viewport *viewport = get_viewport();
ERR_FAIL_NULL(viewport);
viewport->connect("gui_focus_changed", callable_mp(this, &EditorInspector::_gui_focus_changed));
case NOTIFICATION_EXIT_TREE: {
get_parent()->disconnect(SceneStringName(theme_changed), callable_mp(this, &EditorInspector::_update_theme));
} break;
case NOTIFICATION_PREDELETE: {
@ -4798,25 +5059,20 @@ void EditorInspector::_notification(int p_what) {
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
bool needs_update = false;
if (!is_sub_inspector() && EditorThemeManager::is_generated_theme_outdated()) {
add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));
_update_theme();
}
if (use_settings_name_style && EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) {
EditorPropertyNameProcessor::Style style = EditorPropertyNameProcessor::get_settings_style();
if (property_name_style != style) {
property_name_style = style;
needs_update = true;
update_tree_pending = true;
}
}
if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/inspector")) {
needs_update = true;
}
if (needs_update) {
update_tree();
update_tree_pending = true;
}
} break;
}
@ -4975,6 +5231,7 @@ EditorInspector::EditorInspector() {
base_vbox->add_child(main_vbox);
set_horizontal_scroll_mode(SCROLL_MODE_DISABLED);
set_follow_focus(true);
changing = 0;
search_box = nullptr;
@ -5001,4 +5258,5 @@ EditorInspector::EditorInspector() {
set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style());
set_draw_focus_border(true);
set_scroll_on_drag_hover(true);
}