diff options
-rw-r--r-- | core/project_settings.cpp | 6 | ||||
-rw-r--r-- | core/project_settings.h | 1 | ||||
-rw-r--r-- | editor/doc_data.cpp | 3 | ||||
-rw-r--r-- | editor/project_manager.cpp | 4 | ||||
-rw-r--r-- | editor/project_settings_editor.cpp | 537 | ||||
-rw-r--r-- | editor/project_settings_editor.h | 70 | ||||
-rw-r--r-- | modules/bullet/rigid_body_bullet.cpp | 3 | ||||
-rw-r--r-- | modules/bullet/space_bullet.cpp | 1 | ||||
-rw-r--r-- | modules/gdscript/editor/gdscript_highlighter.cpp | 4 | ||||
-rw-r--r-- | modules/gdscript/gdscript_analyzer.cpp | 48 | ||||
-rw-r--r-- | modules/gdscript/gdscript_analyzer.h | 2 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 4 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.h | 1 | ||||
-rw-r--r-- | modules/gdscript/register_types.cpp | 4 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 5 | ||||
-rw-r--r-- | scene/resources/syntax_highlighter.cpp | 4 |
16 files changed, 352 insertions, 345 deletions
diff --git a/core/project_settings.cpp b/core/project_settings.cpp index e08a44d0c1..960a0ec1b0 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -659,6 +659,12 @@ void ProjectSettings::set_builtin_order(const String &p_name) { } } +bool ProjectSettings::is_builtin_setting(const String &p_name) const { + // Return true because a false negative is worse than a false positive. + ERR_FAIL_COND_V_MSG(!props.has(p_name), true, "Request for nonexistent project setting: " + p_name + "."); + return props[p_name].order < NO_BUILTIN_ORDER_BASE; +} + void ProjectSettings::clear(const String &p_name) { ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); props.erase(p_name); diff --git a/core/project_settings.h b/core/project_settings.h index 659ee402b3..686f6f3873 100644 --- a/core/project_settings.h +++ b/core/project_settings.h @@ -142,6 +142,7 @@ public: int get_order(const String &p_name) const; void set_order(const String &p_name, int p_order); void set_builtin_order(const String &p_name); + bool is_builtin_setting(const String &p_name) const; Error setup(const String &p_path, const String &p_main_pack, bool p_upwards = false); diff --git a/editor/doc_data.cpp b/editor/doc_data.cpp index 75b16b4510..791b49319a 100644 --- a/editor/doc_data.cpp +++ b/editor/doc_data.cpp @@ -316,8 +316,7 @@ void DocData::generate(bool p_basic_types) { if (name == "ProjectSettings") { // Special case for project settings, so that settings are not taken from the current project's settings - if (E->get().name == "script" || - ProjectSettings::get_singleton()->get_order(E->get().name) >= ProjectSettings::NO_BUILTIN_ORDER_BASE) { + if (E->get().name == "script" || !ProjectSettings::get_singleton()->is_builtin_setting(E->get().name)) { continue; } if (E->get().usage & PROPERTY_USAGE_EDITOR) { diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index a68742a985..35311b32eb 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -475,10 +475,12 @@ private: set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR); } else { f->store_line("[gd_resource type=\"Environment\" load_steps=2 format=2]"); + f->store_line(""); f->store_line("[sub_resource type=\"Sky\" id=1]"); + f->store_line(""); f->store_line("[resource]"); f->store_line("background_mode = 2"); - f->store_line("background_sky = SubResource( 1 )"); + f->store_line("sky = SubResource( 1 )"); memdelete(f); } } diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 0257e31ee7..9be1a7c2fe 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -30,8 +30,6 @@ #include "project_settings_editor.h" -#include "core/global_constants.h" -#include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_export.h" #include "editor/editor_node.h" @@ -48,175 +46,157 @@ void ProjectSettingsEditor::popup_project_settings() { popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); } - globals_editor->update_category_list(); + _add_feature_overrides(); + inspector->update_category_list(); + localization_editor->update_translations(); autoload_settings->update_autoload(); plugin_settings->update_plugins(); - set_process_unhandled_input(true); } -void ProjectSettingsEditor::_unhandled_input(const Ref<InputEvent> &p_event) { - const Ref<InputEventKey> k = p_event; - - if (k.is_valid() && k->is_pressed()) { - if (k->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) { - if (search_button->is_pressed()) { - search_box->grab_focus(); - search_box->select_all(); - } else { - // This toggles the search bar display while giving the button its "pressed" appearance - search_button->set_pressed(true); - } - - set_input_as_handled(); - } - } +void ProjectSettingsEditor::queue_save() { + timer->start(); } -void ProjectSettingsEditor::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible()) { - EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "project_settings", Rect2(get_position(), get_size())); - set_process_unhandled_input(false); - } - } break; - case NOTIFICATION_ENTER_TREE: { - globals_editor->edit(ProjectSettings::get_singleton()); - - search_button->set_icon(get_theme_icon("Search", "EditorIcons")); - search_box->set_right_icon(get_theme_icon("Search", "EditorIcons")); - search_box->set_clear_button_enabled(true); - - restart_close_button->set_icon(get_theme_icon("Close", "EditorIcons")); - restart_container->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); - restart_icon->set_texture(get_theme_icon("StatusWarning", "EditorIcons")); - restart_label->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor")); - - } break; - case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - search_button->set_icon(get_theme_icon("Search", "EditorIcons")); - search_box->set_right_icon(get_theme_icon("Search", "EditorIcons")); - search_box->set_clear_button_enabled(true); - } break; - } +void ProjectSettingsEditor::set_plugins_page() { + tab_container->set_current_tab(plugin_settings->get_index()); } void ProjectSettingsEditor::update_plugins() { plugin_settings->update_plugins(); } -void ProjectSettingsEditor::_item_selected(const String &p_path) { - const String &selected_path = p_path; - if (selected_path == String()) { - return; +void ProjectSettingsEditor::_setting_edited(const String &p_name) { + queue_save(); +} + +void ProjectSettingsEditor::_advanced_pressed() { + if (advanced->is_pressed()) { + _update_advanced_bar(); + advanced_bar->show(); + } else { + advanced_bar->hide(); } - category->set_text(globals_editor->get_current_section()); - property->set_text(selected_path); - popup_copy_to_feature->set_disabled(false); } -void ProjectSettingsEditor::_item_adds(String) { - _item_add(); +void ProjectSettingsEditor::_setting_selected(const String &p_path) { + if (p_path == String()) { + return; + } + + category_box->set_text(inspector->get_current_section()); + property_box->set_text(p_path); + + if (advanced_bar->is_visible()) { + _update_advanced_bar(); // set_text doesn't trigger text_changed + } } -void ProjectSettingsEditor::_item_add() { +void ProjectSettingsEditor::_add_setting() { + String setting = _get_setting_name(); + // Initialize the property with the default value for the given type. // The type list starts at 1 (as we exclude Nil), so add 1 to the selected value. Callable::CallError ce; const Variant value = Variant::construct(Variant::Type(type->get_selected() + 1), nullptr, 0, ce); - String catname = category->get_text().strip_edges(); - String propname = property->get_text().strip_edges(); + undo_redo->create_action(TTR("Add Project Setting")); + undo_redo->add_do_property(ps, setting, value); + undo_redo->add_undo_property(ps, setting, ps->has_setting(setting) ? ps->get(setting) : Variant()); - if (propname.empty()) { - return; - } + undo_redo->add_do_method(inspector, "update_category_list"); + undo_redo->add_undo_method(inspector, "update_category_list"); + undo_redo->add_do_method(this, "queue_save"); + undo_redo->add_undo_method(this, "queue_save"); + undo_redo->commit_action(); - if (catname.empty()) { - catname = "global"; - } + inspector->set_current_section(setting.get_slice("/", 1)); +} - String name = catname + "/" + propname; +void ProjectSettingsEditor::_delete_setting() { + String setting = _get_setting_name(); + Variant value = ps->get(setting); + int order = ps->get_order(setting); - undo_redo->create_action(TTR("Add Global Property")); + undo_redo->create_action(TTR("Delete Item")); - undo_redo->add_do_property(ProjectSettings::get_singleton(), name, value); + undo_redo->add_do_method(ps, "clear", setting); + undo_redo->add_undo_method(ps, "set", setting, value); + undo_redo->add_undo_method(ps, "set_order", setting, order); - if (ProjectSettings::get_singleton()->has_setting(name)) { - undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, ProjectSettings::get_singleton()->get(name)); - } else { - undo_redo->add_undo_property(ProjectSettings::get_singleton(), name, Variant()); - } + undo_redo->add_do_method(inspector, "update_category_list"); + undo_redo->add_undo_method(inspector, "update_category_list"); + undo_redo->add_do_method(this, "queue_save"); + undo_redo->add_undo_method(this, "queue_save"); - undo_redo->add_do_method(globals_editor, "update_category_list"); - undo_redo->add_undo_method(globals_editor, "update_category_list"); - undo_redo->add_do_method(this, "_settings_changed"); - undo_redo->add_undo_method(this, "_settings_changed"); undo_redo->commit_action(); - globals_editor->set_current_section(catname); - - _settings_changed(); + property_box->clear(); } -void ProjectSettingsEditor::_item_del() { - String path = globals_editor->get_inspector()->get_selected_path(); - if (path == String()) { - EditorNode::get_singleton()->show_warning(TTR("Select a setting item first!")); - return; - } +void ProjectSettingsEditor::_text_field_changed(const String &p_text) { + _update_advanced_bar(); +} - String property = globals_editor->get_current_section().plus_file(path); +void ProjectSettingsEditor::_feature_selected(int p_index) { + _update_advanced_bar(); +} - if (!ProjectSettings::get_singleton()->has_setting(property)) { - EditorNode::get_singleton()->show_warning(vformat(TTR("No property '%s' exists."), property)); - return; - } +void ProjectSettingsEditor::_update_advanced_bar() { + const String property_text = property_box->get_text().strip_edges(); - if (ProjectSettings::get_singleton()->get_order(property) < ProjectSettings::NO_BUILTIN_ORDER_BASE) { - EditorNode::get_singleton()->show_warning(vformat(TTR("Setting '%s' is internal, and it can't be deleted."), property)); - return; - } - - undo_redo->create_action(TTR("Delete Item")); + String error_msg = ""; + bool disable_add = true; + bool disable_del = true; - Variant value = ProjectSettings::get_singleton()->get(property); - int order = ProjectSettings::get_singleton()->get_order(property); + if (!property_box->get_text().empty()) { + const String setting = _get_setting_name(); + bool setting_exists = ps->has_setting(setting); + if (setting_exists) { + error_msg = TTR(" - Cannot add already existing setting."); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", property); - undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property, value); - undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", property, order); + disable_del = ps->is_builtin_setting(setting); + if (disable_del) { + String msg = TTR(" - Cannot delete built-in setting."); + error_msg += (error_msg == "") ? msg : "\n" + msg; + } + } else { + bool bad_category = false; // Allow empty string. + Vector<String> cats = category_box->get_text().strip_edges().split("/"); + for (int i = 0; i < cats.size(); i++) { + if (!cats[i].is_valid_identifier()) { + bad_category = true; + error_msg = TTR(" - Invalid category name."); + break; + } + } - undo_redo->add_do_method(globals_editor, "update_category_list"); - undo_redo->add_undo_method(globals_editor, "update_category_list"); + disable_add = !bad_category; - undo_redo->add_do_method(this, "_settings_changed"); - undo_redo->add_undo_method(this, "_settings_changed"); + if (!property_text.is_valid_identifier()) { + disable_add = true; + String msg = TTR(" - Invalid property name."); + error_msg += (error_msg == "") ? msg : "\n" + msg; + } + } + } - undo_redo->commit_action(); -} + add_button->set_disabled(disable_add); + del_button->set_disabled(disable_del); -void ProjectSettingsEditor::_save() { - Error err = ProjectSettings::get_singleton()->save(); - message->set_text(err != OK ? TTR("Error saving settings.") : TTR("Settings saved OK.")); - message->popup_centered(Size2(300, 100) * EDSCALE); + error_label->set_text(error_msg); + error_label->set_visible(error_msg != ""); } -void ProjectSettingsEditor::_settings_prop_edited(const String &p_name) { - // Method needed to discard the mandatory argument of the property_edited signal - _settings_changed(); -} +String ProjectSettingsEditor::_get_setting_name() const { + const String cat = category_box->get_text(); + const String name = (cat.empty() ? "global" : cat.strip_edges()).plus_file(property_box->get_text().strip_edges()); + const String feature = feature_override->get_item_text(feature_override->get_selected()); -void ProjectSettingsEditor::_settings_changed() { - timer->start(); + return (feature == "") ? name : (name + "." + feature); } -void ProjectSettingsEditor::queue_save() { - _settings_changed(); -} - -void ProjectSettingsEditor::_copy_to_platform_about_to_show() { +void ProjectSettingsEditor::_add_feature_overrides() { Set<String> presets; presets.insert("bptc"); @@ -230,25 +210,26 @@ void ProjectSettingsEditor::_copy_to_platform_about_to_show() { presets.insert("standalone"); presets.insert("32"); presets.insert("64"); - // Not available as an export platform yet, so it needs to be added manually - presets.insert("Server"); + presets.insert("Server"); // Not available as an export platform yet, so it needs to be added manually - for (int i = 0; i < EditorExport::get_singleton()->get_export_platform_count(); i++) { + EditorExport *ee = EditorExport::get_singleton(); + + for (int i = 0; i < ee->get_export_platform_count(); i++) { List<String> p; - EditorExport::get_singleton()->get_export_platform(i)->get_platform_features(&p); + ee->get_export_platform(i)->get_platform_features(&p); for (List<String>::Element *E = p.front(); E; E = E->next()) { presets.insert(E->get()); } } - for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); i++) { + for (int i = 0; i < ee->get_export_preset_count(); i++) { List<String> p; - EditorExport::get_singleton()->get_export_preset(i)->get_platform()->get_preset_features(EditorExport::get_singleton()->get_export_preset(i), &p); + ee->get_export_preset(i)->get_platform()->get_preset_features(ee->get_export_preset(i), &p); for (List<String>::Element *E = p.front(); E; E = E->next()) { presets.insert(E->get()); } - String custom = EditorExport::get_singleton()->get_export_preset(i)->get_custom_features(); + String custom = ee->get_export_preset(i)->get_custom_features(); Vector<String> custom_list = custom.split(","); for (int j = 0; j < custom_list.size(); j++) { String f = custom_list[j].strip_edges(); @@ -258,70 +239,14 @@ void ProjectSettingsEditor::_copy_to_platform_about_to_show() { } } - popup_copy_to_feature->get_popup()->clear(); - int id = 0; + feature_override->clear(); + feature_override->add_item("", 0); // So it is always on top. + int id = 1; for (Set<String>::Element *E = presets.front(); E; E = E->next()) { - popup_copy_to_feature->get_popup()->add_item(E->get(), id++); + feature_override->add_item(E->get(), id++); } } -void ProjectSettingsEditor::_copy_to_platform(int p_which) { - String path = globals_editor->get_inspector()->get_selected_path(); - if (path == String()) { - EditorNode::get_singleton()->show_warning(TTR("Select a setting item first!")); - return; - } - - String property = globals_editor->get_current_section().plus_file(path); - - undo_redo->create_action(TTR("Override for Feature")); - - Variant value = ProjectSettings::get_singleton()->get(property); - if (property.find(".") != -1) { //overwriting overwrite, keep overwrite - undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", property); - undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property, value); - } - - String feature = popup_copy_to_feature->get_popup()->get_item_text(p_which); - String new_path = property + "." + feature; - - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", new_path, value); - if (ProjectSettings::get_singleton()->has_setting(new_path)) { - undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", new_path, ProjectSettings::get_singleton()->get(new_path)); - } - - undo_redo->add_do_method(globals_editor, "update_category_list"); - undo_redo->add_undo_method(globals_editor, "update_category_list"); - - undo_redo->add_do_method(this, "_settings_changed"); - undo_redo->add_undo_method(this, "_settings_changed"); - - undo_redo->commit_action(); -} - -void ProjectSettingsEditor::_toggle_search_bar(bool p_pressed) { - globals_editor->get_inspector()->set_use_filter(p_pressed); - - if (p_pressed) { - search_bar->show(); - add_prop_bar->hide(); - search_box->grab_focus(); - search_box->select_all(); - } else { - search_box->clear(); - search_bar->hide(); - add_prop_bar->show(); - } -} - -void ProjectSettingsEditor::set_plugins_page() { - tab_container->set_current_tab(plugin_settings->get_index()); -} - -TabContainer *ProjectSettingsEditor::get_tabs() { - return tab_container; -} - void ProjectSettingsEditor::_editor_restart() { EditorNode::get_singleton()->save_all_scenes(); EditorNode::get_singleton()->restart_editor(); @@ -335,17 +260,48 @@ void ProjectSettingsEditor::_editor_restart_close() { restart_container->hide(); } -void ProjectSettingsEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_unhandled_input"), &ProjectSettingsEditor::_unhandled_input); - ClassDB::bind_method(D_METHOD("_save"), &ProjectSettingsEditor::_save); +void ProjectSettingsEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "project_settings", Rect2(get_position(), get_size())); + if (advanced->is_pressed()) { + advanced->set_pressed(false); + advanced_bar->hide(); + } + } + } break; + case NOTIFICATION_ENTER_TREE: { + inspector->edit(ps); + + error_label->add_theme_color_override("font_color", error_label->get_theme_color("error_color", "Editor")); + add_button->set_icon(get_theme_icon("Add", "EditorIcons")); + del_button->set_icon(get_theme_icon("Remove", "EditorIcons")); + + search_box->set_right_icon(get_theme_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); + + restart_close_button->set_icon(get_theme_icon("Close", "EditorIcons")); + restart_container->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + restart_icon->set_texture(get_theme_icon("StatusWarning", "EditorIcons")); + restart_label->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor")); + } break; + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + search_box->set_right_icon(get_theme_icon("Search", "EditorIcons")); + search_box->set_clear_button_enabled(true); + } break; + } +} - ClassDB::bind_method(D_METHOD("get_tabs"), &ProjectSettingsEditor::get_tabs); +void ProjectSettingsEditor::_bind_methods() { + ClassDB::bind_method(D_METHOD("queue_save"), &ProjectSettingsEditor::queue_save); } ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { singleton = this; set_title(TTR("Project Settings (project.godot)")); + ps = ProjectSettings::get_singleton(); undo_redo = &p_data->get_undo_redo(); data = p_data; @@ -354,103 +310,110 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { tab_container->set_use_hidden_tabs_for_min_size(true); add_child(tab_container); - VBoxContainer *props_base = memnew(VBoxContainer); - props_base->set_name(TTR("General")); - props_base->set_alignment(BoxContainer::ALIGN_BEGIN); - props_base->set_v_size_flags(Control::SIZE_EXPAND_FILL); - tab_container->add_child(props_base); - - HBoxContainer *hbc = memnew(HBoxContainer); - hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); - props_base->add_child(hbc); - - search_button = memnew(Button); - search_button->set_text(TTR("Search")); - search_button->set_toggle_mode(true); - search_button->set_pressed(false); - search_button->connect("toggled", callable_mp(this, &ProjectSettingsEditor::_toggle_search_bar)); - hbc->add_child(search_button); - - hbc->add_child(memnew(VSeparator)); - - add_prop_bar = memnew(HBoxContainer); - add_prop_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); - hbc->add_child(add_prop_bar); - - Label *l = memnew(Label); - l->set_text(TTR("Category:")); - add_prop_bar->add_child(l); - - category = memnew(LineEdit); - category->set_h_size_flags(Control::SIZE_EXPAND_FILL); - category->connect("text_entered", callable_mp(this, &ProjectSettingsEditor::_item_adds)); - add_prop_bar->add_child(category); - - l = memnew(Label); - l->set_text(TTR("Property:")); - add_prop_bar->add_child(l); - - property = memnew(LineEdit); - property->set_h_size_flags(Control::SIZE_EXPAND_FILL); - property->connect("text_entered", callable_mp(this, &ProjectSettingsEditor::_item_adds)); - add_prop_bar->add_child(property); - - l = memnew(Label); - l->set_text(TTR("Type:")); - add_prop_bar->add_child(l); - - type = memnew(OptionButton); - type->set_h_size_flags(Control::SIZE_EXPAND_FILL); - add_prop_bar->add_child(type); - - // Start at 1 to avoid adding "Nil" as an option - for (int i = 1; i < Variant::VARIANT_MAX; i++) { - type->add_item(Variant::get_type_name(Variant::Type(i))); + VBoxContainer *general_editor = memnew(VBoxContainer); + general_editor->set_name(TTR("General")); + general_editor->set_alignment(BoxContainer::ALIGN_BEGIN); + general_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + tab_container->add_child(general_editor); + + VBoxContainer *header = memnew(VBoxContainer); + header->set_h_size_flags(Control::SIZE_EXPAND_FILL); + general_editor->add_child(header); + + { + // Search bar. + search_bar = memnew(HBoxContainer); + search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); + header->add_child(search_bar); + + search_box = memnew(LineEdit); + search_box->set_custom_minimum_size(Size2(300, 0)); + search_bar->add_child(search_box); + + search_bar->add_spacer(); + + advanced = memnew(CheckButton); + advanced->set_text(TTR("Advanced")); + advanced->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_advanced_pressed)); + search_bar->add_child(advanced); } - Button *add = memnew(Button); - add->set_text(TTR("Add")); - add->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_item_add)); - add_prop_bar->add_child(add); + { + // Advanced bar. + advanced_bar = memnew(VBoxContainer); + advanced_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); + advanced_bar->hide(); + header->add_child(advanced_bar); + + HBoxContainer *hbc = memnew(HBoxContainer); + hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); + advanced_bar->add_margin_child(TTR("Add or remove custom project settings."), hbc, true); + + category_box = memnew(LineEdit); + category_box->set_custom_minimum_size(Size2(140, 0) * EDSCALE); + category_box->connect("text_changed", callable_mp(this, &ProjectSettingsEditor::_text_field_changed)); + category_box->set_placeholder(TTR("Category")); + hbc->add_child(category_box); + + Label *l = memnew(Label); + l->set_text("/"); + hbc->add_child(l); + + property_box = memnew(LineEdit); + property_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + property_box->set_placeholder(TTR("Property")); + property_box->connect("text_changed", callable_mp(this, &ProjectSettingsEditor::_text_field_changed)); + hbc->add_child(property_box); + + l = memnew(Label); + l->set_text(TTR("Type:")); + hbc->add_child(l); + + type = memnew(OptionButton); + type->set_custom_minimum_size(Size2(70, 0) * EDSCALE); + hbc->add_child(type); + + // Start at 1 to avoid adding "Nil" as an option + for (int i = 1; i < Variant::VARIANT_MAX; i++) { + type->add_item(Variant::get_type_name(Variant::Type(i))); + } - search_bar = memnew(HBoxContainer); - search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL); - search_bar->hide(); - hbc->add_child(search_bar); + l = memnew(Label); + l->set_text(TTR("Feature Override:")); + hbc->add_child(l); - search_box = memnew(LineEdit); - search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); - search_bar->add_child(search_box); + feature_override = memnew(OptionButton); + feature_override->set_custom_minimum_size(Size2(70, 0) * EDSCALE); + feature_override->connect("item_selected", callable_mp(this, &ProjectSettingsEditor::_feature_selected)); + hbc->add_child(feature_override); - globals_editor = memnew(SectionedInspector); - globals_editor->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); - globals_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); - globals_editor->register_search_box(search_box); - globals_editor->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_item_selected)); - globals_editor->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_settings_prop_edited)); - globals_editor->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request)); - props_base->add_child(globals_editor); + hbc->add_spacer(); - Button *del = memnew(Button); - del->set_text(TTR("Delete")); - del->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_item_del)); - hbc->add_child(del); + add_button = memnew(Button); + add_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_add_setting)); + hbc->add_child(add_button); - add_prop_bar->add_child(memnew(VSeparator)); + del_button = memnew(Button); + del_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_delete_setting)); + hbc->add_child(del_button); - popup_copy_to_feature = memnew(MenuButton); - popup_copy_to_feature->set_text(TTR("Override For...")); - popup_copy_to_feature->set_disabled(true); - add_prop_bar->add_child(popup_copy_to_feature); + error_label = memnew(Label); + advanced_bar->add_child(error_label); + } - popup_copy_to_feature->get_popup()->connect("id_pressed", callable_mp(this, &ProjectSettingsEditor::_copy_to_platform)); - popup_copy_to_feature->get_popup()->connect("about_to_popup", callable_mp(this, &ProjectSettingsEditor::_copy_to_platform_about_to_show)); + header->add_child(memnew(HSeparator)); - get_ok()->set_text(TTR("Close")); - set_hide_on_ok(true); + inspector = memnew(SectionedInspector); + inspector->get_inspector()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo()); + inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL); + inspector->register_search_box(search_box); + inspector->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_setting_selected)); + inspector->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited)); + inspector->get_inspector()->connect("restart_requested", callable_mp(this, &ProjectSettingsEditor::_editor_restart_request)); + general_editor->add_child(inspector); restart_container = memnew(PanelContainer); - props_base->add_child(restart_container); + general_editor->add_child(restart_container); HBoxContainer *restart_hb = memnew(HBoxContainer); restart_container->hide(); @@ -475,27 +438,24 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { restart_close_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_editor_restart_close)); restart_hb->add_child(restart_close_button); - message = memnew(AcceptDialog); - add_child(message); - inputmap_editor = memnew(InputMapEditor); inputmap_editor->set_name(TTR("Input Map")); - inputmap_editor->connect("inputmap_changed", callable_mp(this, &ProjectSettingsEditor::_settings_changed)); + inputmap_editor->connect("inputmap_changed", callable_mp(this, &ProjectSettingsEditor::queue_save)); tab_container->add_child(inputmap_editor); localization_editor = memnew(LocalizationEditor); localization_editor->set_name(TTR("Localization")); - localization_editor->connect("localization_changed", callable_mp(this, &ProjectSettingsEditor::_settings_changed)); + localization_editor->connect("localization_changed", callable_mp(this, &ProjectSettingsEditor::queue_save)); tab_container->add_child(localization_editor); autoload_settings = memnew(EditorAutoloadSettings); autoload_settings->set_name(TTR("AutoLoad")); - autoload_settings->connect("autoload_changed", callable_mp(this, &ProjectSettingsEditor::_settings_changed)); + autoload_settings->connect("autoload_changed", callable_mp(this, &ProjectSettingsEditor::queue_save)); tab_container->add_child(autoload_settings); shaders_global_variables_editor = memnew(ShaderGlobalsEditor); shaders_global_variables_editor->set_name(TTR("Shader Globals")); - shaders_global_variables_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::_settings_changed)); + shaders_global_variables_editor->connect("globals_changed", callable_mp(this, &ProjectSettingsEditor::queue_save)); tab_container->add_child(shaders_global_variables_editor); plugin_settings = memnew(EditorPluginSettings); @@ -504,7 +464,10 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { timer = memnew(Timer); timer->set_wait_time(1.5); - timer->connect("timeout", callable_mp(ProjectSettings::get_singleton(), &ProjectSettings::save)); + timer->connect("timeout", callable_mp(ps, &ProjectSettings::save)); timer->set_one_shot(true); add_child(timer); + + get_ok()->set_text(TTR("Close")); + set_hide_on_ok(true); } diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index c99c2fe9a2..0d7e19b242 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -35,12 +35,11 @@ #include "editor/editor_data.h" #include "editor/editor_plugin_settings.h" #include "editor/editor_sectioned_inspector.h" +#include "editor/input_map_editor.h" +#include "editor/localization_editor.h" +#include "editor/shader_globals_editor.h" #include "editor_autoload_settings.h" -#include "input_map_editor.h" -#include "localization_editor.h" -#include "scene/gui/dialogs.h" #include "scene/gui/tab_container.h" -#include "shader_globals_editor.h" class ProjectSettingsEditor : public AcceptDialog { GDCLASS(ProjectSettingsEditor, AcceptDialog); @@ -53,28 +52,31 @@ class ProjectSettingsEditor : public AcceptDialog { INPUT_MOUSE_BUTTON }; - TabContainer *tab_container; - AcceptDialog *message; + static ProjectSettingsEditor *singleton; + ProjectSettings *ps; Timer *timer; - HBoxContainer *search_bar; - Button *search_button; - LineEdit *search_box; - HBoxContainer *add_prop_bar; - LineEdit *category; - LineEdit *property; - OptionButton *type; - - SectionedInspector *globals_editor; - - MenuButton *popup_copy_to_feature; - + TabContainer *tab_container; + SectionedInspector *inspector; InputMapEditor *inputmap_editor; LocalizationEditor *localization_editor; EditorAutoloadSettings *autoload_settings; ShaderGlobalsEditor *shaders_global_variables_editor; EditorPluginSettings *plugin_settings; + HBoxContainer *search_bar; + LineEdit *search_box; + CheckButton *advanced; + + VBoxContainer *advanced_bar; + LineEdit *category_box; + LineEdit *property_box; + Button *add_button; + Button *del_button; + OptionButton *type; + OptionButton *feature_override; + Label *error_label; + Label *restart_label; TextureRect *restart_icon; PanelContainer *restart_container; @@ -83,30 +85,25 @@ class ProjectSettingsEditor : public AcceptDialog { EditorData *data; UndoRedo *undo_redo; - void _item_selected(const String &); - void _item_adds(String); - void _item_add(); - void _item_del(); - void _save(); - - void _settings_prop_edited(const String &p_name); - void _settings_changed(); + void _advanced_pressed(); + void _update_advanced_bar(); + void _text_field_changed(const String &p_text); + void _feature_selected(int p_index); - void _copy_to_platform(int p_which); - void _copy_to_platform_about_to_show(); - - void _toggle_search_bar(bool p_pressed); - - ProjectSettingsEditor(); - - static ProjectSettingsEditor *singleton; + String _get_setting_name() const; + void _setting_edited(const String &p_name); + void _setting_selected(const String &p_path); + void _add_setting(); + void _delete_setting(); void _editor_restart_request(); void _editor_restart(); void _editor_restart_close(); + void _add_feature_overrides(); + ProjectSettingsEditor(); + protected: - void _unhandled_input(const Ref<InputEvent> &p_event); void _notification(int p_what); static void _bind_methods(); @@ -117,8 +114,7 @@ public: void update_plugins(); EditorAutoloadSettings *get_autoload_settings() { return autoload_settings; } - - TabContainer *get_tabs(); + TabContainer *get_tabs() { return tab_container; } void queue_save(); diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 5c1144b875..32c3240a35 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -897,8 +897,7 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) { } void RigidBodyBullet::reload_space_override_modificator() { - // Make sure that kinematic bodies have their total gravity calculated - if (!is_active() && PhysicsServer3D::BODY_MODE_KINEMATIC != mode) { + if (mode == PhysicsServer3D::BODY_MODE_STATIC) { return; } diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 2b60f8df36..d0515e7c97 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -177,6 +177,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf bt_xform_to.getOrigin() += bt_motion; if ((bt_xform_to.getOrigin() - bt_xform_from.getOrigin()).fuzzyZero()) { + shape->destroy_bt_shape(btShape); return false; } diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index aba3e07134..ae1f2893f1 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -82,6 +82,10 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) const String &str = text_edit->get_line(p_line); const int line_length = str.length(); Color prev_color; + + if (in_region != -1 && str.length() == 0) { + color_region_cache[p_line] = in_region; + } for (int j = 0; j < str.length(); j++) { Dictionary highlighter_info; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 531666bec5..1e72216ad2 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -71,6 +71,10 @@ static StringName get_real_class_name(const StringName &p_source) { return p_source; } +void GDScriptAnalyzer::cleanup() { + underscore_map.clear(); +} + static GDScriptParser::DataType make_callable_type(const MethodInfo &p_info) { GDScriptParser::DataType type; type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; @@ -1406,23 +1410,25 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig break; } - bool compatible = true; - GDScriptParser::DataType op_type = p_assignment->assigned_value->get_datatype(); - if (vop != Variant::OP_EQUAL) { - op_type = get_operation_type(vop, p_assignment->assignee->get_datatype(), p_assignment->assigned_value->get_datatype(), compatible); - } + if (!p_assignment->assignee->get_datatype().is_variant() && !p_assignment->assigned_value->get_datatype().is_variant()) { + bool compatible = true; + GDScriptParser::DataType op_type = p_assignment->assigned_value->get_datatype(); + if (vop != Variant::OP_EQUAL) { + op_type = get_operation_type(vop, p_assignment->assignee->get_datatype(), p_assignment->assigned_value->get_datatype(), compatible); + } - if (compatible) { - compatible = is_type_compatible(p_assignment->assignee->get_datatype(), op_type, true); - if (!compatible) { - if (p_assignment->assignee->get_datatype().is_hard_type()) { - push_error(vformat(R"(Cannot assign a value of type "%s" to a target of type "%s".)", p_assignment->assigned_value->get_datatype().to_string(), p_assignment->assignee->get_datatype().to_string()), p_assignment->assigned_value); - } else { - // TODO: Warning in this case. + if (compatible) { + compatible = is_type_compatible(p_assignment->assignee->get_datatype(), op_type, true); + if (!compatible) { + if (p_assignment->assignee->get_datatype().is_hard_type()) { + push_error(vformat(R"(Cannot assign a value of type "%s" to a target of type "%s".)", p_assignment->assigned_value->get_datatype().to_string(), p_assignment->assignee->get_datatype().to_string()), p_assignment->assigned_value); + } else { + // TODO: Warning in this case. + } } + } else { + push_error(vformat(R"(Invalid operands "%s" and "%s" for assignment operator.)", p_assignment->assignee->get_datatype().to_string(), p_assignment->assigned_value->get_datatype().to_string()), p_assignment); } - } else { - push_error(vformat(R"(Invalid operands "%s" and "%s" for assignment operator.)", p_assignment->assignee->get_datatype().to_string(), p_assignment->assigned_value->get_datatype().to_string()), p_assignment); } if (p_assignment->assignee->get_datatype().has_no_type() || p_assignment->assigned_value->get_datatype().is_variant()) { @@ -1536,7 +1542,19 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o if (p_binary_op->left_operand->is_constant && p_binary_op->right_operand->is_constant) { p_binary_op->is_constant = true; if (p_binary_op->variant_op < Variant::OP_MAX) { - p_binary_op->reduced_value = Variant::evaluate(p_binary_op->variant_op, p_binary_op->left_operand->reduced_value, p_binary_op->right_operand->reduced_value); + bool valid = false; + Variant::evaluate(p_binary_op->variant_op, p_binary_op->left_operand->reduced_value, p_binary_op->right_operand->reduced_value, p_binary_op->reduced_value, valid); + if (!valid) { + if (p_binary_op->reduced_value.get_type() == Variant::STRING) { + push_error(vformat(R"(%s in operator %s.)", p_binary_op->reduced_value, Variant::get_operator_name(p_binary_op->variant_op)), p_binary_op); + } else { + push_error(vformat(R"(Invalid operands to operator %s, %s and %s.".)", + Variant::get_operator_name(p_binary_op->variant_op), + Variant::get_type_name(p_binary_op->left_operand->reduced_value.get_type()), + Variant::get_type_name(p_binary_op->right_operand->reduced_value.get_type())), + p_binary_op); + } + } } else { if (p_binary_op->operation == GDScriptParser::BinaryOpNode::OP_TYPE_TEST) { GDScriptParser::DataType test_type = right_type; diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 85183d3272..06d3530cb6 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -113,6 +113,8 @@ public: Error analyze(); GDScriptAnalyzer(GDScriptParser *p_parser); + + static void cleanup(); }; #endif // GDSCRIPT_ANALYZER_H diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index af07457750..1f3e1c1e40 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -94,6 +94,10 @@ Variant::Type GDScriptParser::get_builtin_type(const StringName &p_type) { return Variant::VARIANT_MAX; } +void GDScriptParser::cleanup() { + builtin_types.clear(); +} + GDScriptFunctions::Function GDScriptParser::get_builtin_function(const StringName &p_name) { for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) { if (p_name == GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index a741ae0cc7..c9ab3d4e12 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -1335,6 +1335,7 @@ public: void print_tree(const GDScriptParser &p_parser); }; #endif // DEBUG_ENABLED + static void cleanup(); }; #endif // GDSCRIPT_PARSER_H diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 23c7f97b5a..c554cbac05 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -35,6 +35,7 @@ #include "core/os/dir_access.h" #include "core/os/file_access.h" #include "gdscript.h" +#include "gdscript_analyzer.h" #include "gdscript_cache.h" #include "gdscript_tokenizer.h" @@ -148,4 +149,7 @@ void unregister_gdscript_types() { EditorTranslationParser::get_singleton()->remove_parser(gdscript_translation_parser_plugin, EditorTranslationParser::STANDARD); gdscript_translation_parser_plugin.unref(); #endif // TOOLS_ENABLED + + GDScriptParser::cleanup(); + GDScriptAnalyzer::cleanup(); } diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 2449b3bd35..adefb53862 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -880,7 +880,10 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p if (n->get_script_instance()) { n->get_script_instance()->call(p_method, (const Variant **)v, 1, err); } - n->call(p_method, (const Variant **)v, 1, err); + MethodBind *method = ClassDB::get_method(n->get_class_name(), p_method); + if (method) { + method->call(n, (const Variant **)v, 1, err); + } } call_lock--; diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp index 9c8f9334a9..4479b822c0 100644 --- a/scene/resources/syntax_highlighter.cpp +++ b/scene/resources/syntax_highlighter.cpp @@ -158,6 +158,10 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) { const String &str = text_edit->get_line(p_line); const int line_length = str.length(); Color prev_color; + + if (in_region != -1 && str.length() == 0) { + color_region_cache[p_line] = in_region; + } for (int j = 0; j < line_length; j++) { Dictionary highlighter_info; |