diff options
194 files changed, 648 insertions, 730 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 9dea66914f..7ffae10a2a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -45,7 +45,7 @@ body: label: Issue description description: | Describe your issue briefly. What doesn't work, and how do you expect it to work instead? - You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags, on separate lines before and after the text. (Use <code>```gdscript</code> to add GDScript syntax highlighting.) + You can include images or videos with drag and drop, and format code blocks or logs with <code>\`\`\`</code> tags, on separate lines before and after the text. (Use <code>\`\`\`gdscript</code> to add GDScript syntax highlighting.) Please do not add code examples or error messages as screenshots, but as text, this helps searching for issues and testing the code. If you are reporting a bug in the editor interface, like the script editor, please provide both a screenshot *and* the text of the code to help with testing. validations: required: true diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 535515165b..4fd288f16d 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -72,9 +72,6 @@ <member name="checked" type="bool" setter="set_checked" getter="is_checked" default="false"> Used by the inspector, set to [code]true[/code] when the property is checked. </member> - <member name="configuration_warning" type="String" setter="set_configuration_warning" getter="get_configuration_warning" default=""""> - Used by the inspector, set to show a configuration warning on the property. - </member> <member name="deletable" type="bool" setter="set_deletable" getter="is_deletable" default="false"> Used by the inspector, set to [code]true[/code] when the property can be deleted by the user. </member> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index a46bb593d4..4fced2142f 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -37,13 +37,9 @@ </description> </method> <method name="_get_configuration_warnings" qualifiers="virtual const"> - <return type="Array" /> + <return type="PackedStringArray" /> <description> The elements in the array returned from this method are displayed as warnings in the Scene dock if the script that overrides it is a [code]tool[/code] script. - Each array element must either be a [String] or a [Dictionary]. - A dictionary element must contain a key [code]message[/code] of type [String] which is shown in the user interface. - The dictionary may optionally contain a key [code]property[/code] of type [NodePath], which also shows this warning in the inspector on the corresponding property. - If a string is found in the returned array, it is converted to an equivalent dictionary with the [code]message[/code] field set. Returning an empty array produces no warnings. Call [method update_configuration_warnings] when the warnings need to be updated for this node. [codeblock] diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 02bb1d219e..cbfd233acc 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -5907,7 +5907,7 @@ void AnimationTrackEditor::_edit_menu_about_to_popup() { bool has_length = false; for (const KeyValue<SelectedKey, KeyInfo> &E : selection) { - if (animation->track_get_type(E.key.track) == Animation::TYPE_AUDIO) { + if (animation->track_get_type(E.key.track) == Animation::TYPE_AUDIO && animation->audio_track_get_key_stream(E.key.track, E.key.key).is_valid()) { has_length = true; break; } @@ -6247,6 +6247,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { continue; } Ref<AudioStream> stream = animation->audio_track_get_key_stream(E.key.track, E.key.key); + if (stream.is_null()) { + continue; + } double len = stream->get_length() - animation->audio_track_get_key_end_offset(E.key.track, E.key.key); real_t prev_offset = animation->audio_track_get_key_start_offset(E.key.track, E.key.key); double prev_time = animation->track_get_key_time(E.key.track, E.key.key); @@ -6273,6 +6276,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { continue; } Ref<AudioStream> stream = animation->audio_track_get_key_stream(E.key.track, E.key.key); + if (stream.is_null()) { + continue; + } double len = stream->get_length() - animation->audio_track_get_key_start_offset(E.key.track, E.key.key); real_t prev_offset = animation->audio_track_get_key_end_offset(E.key.track, E.key.key); double prev_time = animation->track_get_key_time(E.key.track, E.key.key); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 4e76d40b1d..583a52ed52 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -214,22 +214,6 @@ void EditorProperty::_notification(int p_what) { text_size -= close->get_width() + 4 * EDSCALE; } } - - if (!configuration_warning.is_empty() && !read_only) { - Ref<Texture2D> warning; - - warning = get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")); - - rect.size.x -= warning->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree")); - - if (is_layout_rtl()) { - rect.position.x += warning->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree")); - } - - if (no_children) { - text_size -= warning->get_width() + 4 * EDSCALE; - } - } } //set children @@ -415,38 +399,6 @@ void EditorProperty::_notification(int p_what) { } else { delete_rect = Rect2(); } - - if (!configuration_warning.is_empty() && !read_only) { - Ref<Texture2D> warning; - - StringName warning_icon; - Node *node = Object::cast_to<Node>(object); - if (node) { - const int warning_num = node->get_configuration_warnings_of_property(property_path).size(); - warning_icon = Node::get_configuration_warning_icon(warning_num); - } else { - // This shouldn't happen, but let's not crash over an icon. - warning_icon = "NodeWarning"; - } - warning = get_theme_icon(warning_icon, SNAME("EditorIcons")); - - ofs -= warning->get_width() + get_theme_constant(SNAME("hseparator"), SNAME("Tree")); - - Color color2(1, 1, 1); - if (configuration_warning_hover) { - color2.r *= 1.2; - color2.g *= 1.2; - color2.b *= 1.2; - } - configuration_warning_rect = Rect2(ofs, ((size.height - warning->get_height()) / 2), warning->get_width(), warning->get_height()); - if (rtl) { - draw_texture(warning, Vector2(size.width - configuration_warning_rect.position.x - warning->get_width(), configuration_warning_rect.position.y), color2); - } else { - draw_texture(warning, configuration_warning_rect.position, color2); - } - } else { - configuration_warning_rect = Rect2(); - } } break; } } @@ -722,12 +674,6 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { check_hover = new_check_hover; queue_redraw(); } - - bool new_configuration_warning_hover = configuration_warning_rect.has_point(mpos) && !button_left; - if (new_configuration_warning_hover != configuration_warning_hover) { - configuration_warning_hover = new_configuration_warning_hover; - queue_redraw(); - } } Ref<InputEventMouseButton> mb = p_event; @@ -784,16 +730,6 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { queue_redraw(); emit_signal(SNAME("property_checked"), property, checked); } - - if (configuration_warning_rect.has_point(mpos)) { - if (warning_dialog == nullptr) { - warning_dialog = memnew(AcceptDialog); - add_child(warning_dialog); - warning_dialog->set_title(TTR("Node Configuration Warning!")); - } - warning_dialog->set_text(configuration_warning); - warning_dialog->popup_centered(); - } } else if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) { accept_event(); _update_popup(); @@ -919,16 +855,6 @@ float EditorProperty::get_name_split_ratio() const { return split_ratio; } -void EditorProperty::set_configuration_warning(const String &p_configuration_warning) { - configuration_warning = p_configuration_warning; - queue_redraw(); - queue_sort(); -} - -String EditorProperty::get_configuration_warning() const { - return configuration_warning; -} - void EditorProperty::set_object_and_property(Object *p_object, const StringName &p_property) { object = p_object; property = p_property; @@ -985,15 +911,6 @@ void EditorProperty::_update_pin_flags() { } } -void EditorProperty::_update_configuration_warnings() { - Node *node = Object::cast_to<Node>(object); - if (node) { - const PackedStringArray warnings = node->get_configuration_warnings_as_strings(true, property_path); - const String warning_lines = String("\n").join(warnings); - set_configuration_warning(warning_lines); - } -} - Control *EditorProperty::make_custom_tooltip(const String &p_text) const { EditorHelpBit *tooltip = nullptr; @@ -1069,9 +986,6 @@ void EditorProperty::_bind_methods() { ClassDB::bind_method(D_METHOD("set_deletable", "deletable"), &EditorProperty::set_deletable); ClassDB::bind_method(D_METHOD("is_deletable"), &EditorProperty::is_deletable); - ClassDB::bind_method(D_METHOD("set_configuration_warning", "configuration_warning"), &EditorProperty::set_configuration_warning); - ClassDB::bind_method(D_METHOD("get_configuration_warning"), &EditorProperty::get_configuration_warning); - ClassDB::bind_method(D_METHOD("get_edited_property"), &EditorProperty::get_edited_property); ClassDB::bind_method(D_METHOD("get_edited_object"), &EditorProperty::get_edited_object); @@ -1089,7 +1003,6 @@ 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_PROPERTY(PropertyInfo(Variant::STRING, "configuration_warning"), "set_configuration_warning", "get_configuration_warning"); ADD_SIGNAL(MethodInfo("property_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), PropertyInfo(Variant::STRING_NAME, "field"), PropertyInfo(Variant::BOOL, "changing"))); ADD_SIGNAL(MethodInfo("multiple_properties_changed", PropertyInfo(Variant::PACKED_STRING_ARRAY, "properties"), PropertyInfo(Variant::ARRAY, "value"))); @@ -3409,7 +3322,6 @@ void EditorInspector::update_tree() { ep->set_keying(keying); ep->set_read_only(property_read_only || all_read_only); ep->set_deletable(deletable_properties || p.name.begins_with("metadata/")); - ep->_update_configuration_warnings(); } current_vbox->add_child(editors[i].property_editor); @@ -3535,9 +3447,6 @@ void EditorInspector::edit(Object *p_object) { object = p_object; - property_configuration_warnings.clear(); - _update_configuration_warnings(); - if (object) { update_scroll_request = 0; //reset if (scroll_cache.has(object->get_instance_id())) { //if exists, set something else @@ -4059,52 +3968,6 @@ void EditorInspector::_node_removed(Node *p_node) { } } -void EditorInspector::_warning_changed(Node *p_node) { - if (p_node == object) { - // Only update the tree if the list of configuration warnings has changed. - if (_update_configuration_warnings()) { - update_tree_pending = true; - } - } -} - -bool EditorInspector::_update_configuration_warnings() { - Node *node = Object::cast_to<Node>(object); - if (!node) { - return false; - } - - bool changed = false; - LocalVector<int> found_warning_indices; - - // New and changed warnings. - Vector<Dictionary> warnings = node->get_configuration_warnings_as_dicts(); - for (const Dictionary &warning : warnings) { - if (!warning.has("property")) { - continue; - } - - int found_warning_index = property_configuration_warnings.find(warning); - if (found_warning_index < 0) { - found_warning_index = property_configuration_warnings.size(); - property_configuration_warnings.push_back(warning); - changed = true; - } - found_warning_indices.push_back(found_warning_index); - } - - // Removed warnings. - for (uint32_t i = 0; i < property_configuration_warnings.size(); i++) { - if (found_warning_indices.find(i) < 0) { - property_configuration_warnings.remove_at(i); - i--; - changed = true; - } - } - - return changed; -} - void EditorInspector::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { @@ -4116,7 +3979,6 @@ void EditorInspector::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { if (!sub_inspector) { get_tree()->connect("node_removed", callable_mp(this, &EditorInspector::_node_removed)); - get_tree()->connect("node_configuration_warning_changed", callable_mp(this, &EditorInspector::_warning_changed)); } } break; @@ -4127,7 +3989,6 @@ void EditorInspector::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { if (!sub_inspector) { get_tree()->disconnect("node_removed", callable_mp(this, &EditorInspector::_node_removed)); - get_tree()->disconnect("node_configuration_warning_changed", callable_mp(this, &EditorInspector::_warning_changed)); } edit(nullptr); } break; diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 4e937ae4ad..0e908b7a14 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -76,7 +76,6 @@ private: String doc_path; bool internal = false; bool has_doc_tooltip = false; - AcceptDialog *warning_dialog = nullptr; int property_usage; @@ -99,8 +98,6 @@ private: bool check_hover = false; Rect2 delete_rect; bool delete_hover = false; - Rect2 configuration_warning_rect; - bool configuration_warning_hover = false; bool can_revert = false; bool can_pin = false; @@ -124,15 +121,12 @@ private: Control *bottom_editor = nullptr; PopupMenu *menu = nullptr; - String configuration_warning; - HashMap<StringName, Variant> cache; GDVIRTUAL0(_update_property) GDVIRTUAL1(_set_read_only, bool) void _update_pin_flags(); - void _update_configuration_warnings(); protected: void _notification(int p_what); @@ -209,9 +203,6 @@ public: void set_name_split_ratio(float p_ratio); float get_name_split_ratio() const; - void set_configuration_warning(const String &p_configuration_warning); - String get_configuration_warning() const; - void set_object_and_property(Object *p_object, const StringName &p_property); virtual Control *make_custom_tooltip(const String &p_text) const override; @@ -514,7 +505,6 @@ class EditorInspector : public ScrollContainer { int property_focusable; int update_scroll_request; - LocalVector<Dictionary> property_configuration_warnings; HashMap<StringName, HashMap<StringName, String>> doc_path_cache; HashSet<StringName> restart_request_props; HashMap<String, String> custom_property_descriptions; @@ -543,8 +533,6 @@ class EditorInspector : public ScrollContainer { void _object_id_selected(const String &p_path, ObjectID p_id); void _node_removed(Node *p_node); - void _warning_changed(Node *p_node); - bool _update_configuration_warnings(); HashMap<StringName, int> per_array_page; void _page_change_request(int p_new_page, const StringName &p_array_prefix); diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp index 7fb52251ce..14af49aabf 100644 --- a/editor/gui/scene_tree_editor.cpp +++ b/editor/gui/scene_tree_editor.cpp @@ -132,13 +132,32 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i } undo_redo->commit_action(); } else if (p_id == BUTTON_WARNING) { - const PackedStringArray warnings = n->get_configuration_warnings_as_strings(true); + const PackedStringArray warnings = n->get_configuration_warnings(); + if (warnings.is_empty()) { return; } - const String warning_lines = String("\n").join(warnings); - warning->set_text(warning_lines); + // Improve looks on tooltip, extra spacing on non-bullet point newlines. + const String bullet_point = U"• "; + String all_warnings; + for (const String &w : warnings) { + all_warnings += "\n" + bullet_point + w; + } + + // Limit the line width while keeping some padding. + // It is not efficient, but it does not have to be. + const PackedInt32Array boundaries = TS->string_get_word_breaks(all_warnings, "", 80); + PackedStringArray lines; + for (int i = 0; i < boundaries.size(); i += 2) { + const int start = boundaries[i]; + const int end = boundaries[i + 1]; + const String line = all_warnings.substr(start, end - start); + lines.append(line); + } + all_warnings = String("\n").join(lines).indent(" ").replace(U" •", U"\n•").substr(2); // We don't want the first two newlines. + + warning->set_text(all_warnings); warning->popup_centered(); } else if (p_id == BUTTON_SIGNALS) { @@ -275,12 +294,29 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { if (can_rename) { //should be can edit.. - const PackedStringArray warnings = p_node->get_configuration_warnings_as_strings(false); + const PackedStringArray warnings = p_node->get_configuration_warnings(); const int num_warnings = warnings.size(); if (num_warnings > 0) { - const StringName warning_icon = Node::get_configuration_warning_icon(num_warnings); - const String warning_lines = String("\n\n").join(warnings); - item->add_button(0, get_editor_theme_icon(warning_icon), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n\n" + warning_lines); + String warning_icon; + if (num_warnings == 1) { + warning_icon = SNAME("NodeWarning"); + } else if (num_warnings <= 3) { + warning_icon = vformat("NodeWarnings%d", num_warnings); + } else { + warning_icon = SNAME("NodeWarnings4Plus"); + } + + // Improve looks on tooltip, extra spacing on non-bullet point newlines. + const String bullet_point = U"• "; + String all_warnings; + for (const String &w : warnings) { + all_warnings += "\n\n" + bullet_point + w.replace("\n", "\n "); + } + if (num_warnings == 1) { + all_warnings.remove_at(0); // With only one warning, two newlines do not look great. + } + + item->add_button(0, get_editor_theme_icon(warning_icon), BUTTON_WARNING, false, TTR("Node configuration warning:") + all_warnings); } if (p_node->is_unique_name_in_owner()) { diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected index f79b6ae5e6..b801066204 100644 --- a/misc/extension_api_validation/4.2-stable.expected +++ b/misc/extension_api_validation/4.2-stable.expected @@ -84,13 +84,6 @@ Validate extension JSON: Error: Field 'classes/Sky/properties/sky_material': typ Property hints reordered to improve editor usability. The types allowed are still the same as before. No adjustments should be necessary. -GH-68420 --------- -Validate extension JSON: Error: Field 'classes/Node/methods/_get_configuration_warnings/return_value': type changed value in new API, from "PackedStringArray" to "Array". - -Allow configuration warnings to refer to a property. Compatibility method registered. - - GH-86907 -------- diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs index 01aa65bfc3..3c46079414 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs @@ -7,11 +7,11 @@ namespace GodotTools.BuildLogger { public class GodotBuildLogger : ILogger { - public string Parameters { get; set; } + public string? Parameters { get; set; } public LoggerVerbosity Verbosity { get; set; } - private StreamWriter _logStreamWriter; - private StreamWriter _issuesStreamWriter; + private StreamWriter _logStreamWriter = StreamWriter.Null; + private StreamWriter _issuesStreamWriter = StreamWriter.Null; private int _indent; public void Initialize(IEventSource eventSource) diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj index d0972f1eae..fd836f9ad2 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj @@ -3,6 +3,7 @@ <ProjectGuid>{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}</ProjectGuid> <TargetFramework>net6.0</TargetFramework> <LangVersion>10</LangVersion> + <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" ExcludeAssets="runtime" /> diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj index cfd5c88a58..0755484465 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj @@ -3,5 +3,6 @@ <ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid> <TargetFramework>net6.0</TargetFramework> <LangVersion>10</LangVersion> + <Nullable>enable</Nullable> </PropertyGroup> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs index a4d7dedbd5..4dd18b4c03 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.Core/ProcessExtensions.cs @@ -11,7 +11,7 @@ namespace GodotTools.Core { var tcs = new TaskCompletionSource<bool>(); - void ProcessExited(object sender, EventArgs e) + void ProcessExited(object? sender, EventArgs e) { tcs.TrySetResult(true); } diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs index d86a77d222..d5c3a92351 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs @@ -7,7 +7,7 @@ namespace GodotTools.Core { public static class StringExtensions { - private static readonly string _driveRoot = Path.GetPathRoot(Environment.CurrentDirectory); + private static readonly string _driveRoot = Path.GetPathRoot(Environment.CurrentDirectory)!; public static string RelativeToPath(this string path, string dir) { @@ -26,9 +26,6 @@ namespace GodotTools.Core public static string NormalizePath(this string path) { - if (string.IsNullOrEmpty(path)) - return path; - bool rooted = path.IsAbsolutePath(); path = path.Replace('\\', '/'); diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj index eb6ac8bafc..3bf678e9f9 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj @@ -4,6 +4,7 @@ <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <LangVersion>10</LangVersion> + <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" /> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs index 450c4bf0cb..e344aa4a37 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs @@ -64,14 +64,14 @@ namespace GodotTools.IdeMessaging.CLI while (!fwdClient.IsDisposed) { - string firstLine = await inputReader.ReadLineAsync(); + string? firstLine = await inputReader.ReadLineAsync(); if (firstLine == null || firstLine == "QUIT") goto ExitMainLoop; string messageId = firstLine; - string messageArgcLine = await inputReader.ReadLineAsync(); + string? messageArgcLine = await inputReader.ReadLineAsync(); if (messageArgcLine == null) { @@ -89,7 +89,7 @@ namespace GodotTools.IdeMessaging.CLI for (int i = 0; i < messageArgc; i++) { - string bodyLine = await inputReader.ReadLineAsync(); + string? bodyLine = await inputReader.ReadLineAsync(); if (bodyLine == null) { @@ -126,29 +126,29 @@ namespace GodotTools.IdeMessaging.CLI } } - private static async Task<Response> SendRequest(Client client, string id, MessageContent content) + private static async Task<Response?> SendRequest(Client client, string id, MessageContent content) { - var handlers = new Dictionary<string, Func<Task<Response>>> + var handlers = new Dictionary<string, Func<Task<Response?>>> { [PlayRequest.Id] = async () => { var request = JsonConvert.DeserializeObject<PlayRequest>(content.Body); - return await client.SendRequest<PlayResponse>(request); + return await client.SendRequest<PlayResponse>(request!); }, [DebugPlayRequest.Id] = async () => { var request = JsonConvert.DeserializeObject<DebugPlayRequest>(content.Body); - return await client.SendRequest<DebugPlayResponse>(request); + return await client.SendRequest<DebugPlayResponse>(request!); }, [ReloadScriptsRequest.Id] = async () => { var request = JsonConvert.DeserializeObject<ReloadScriptsRequest>(content.Body); - return await client.SendRequest<ReloadScriptsResponse>(request); + return await client.SendRequest<ReloadScriptsResponse>(request!); }, [CodeCompletionRequest.Id] = async () => { var request = JsonConvert.DeserializeObject<CodeCompletionRequest>(content.Body); - return await client.SendRequest<CodeCompletionResponse>(request); + return await client.SendRequest<CodeCompletionResponse>(request!); } }; diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs index 72e2a1fc0d..7bfa07be0b 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; using System.IO; using System.Net; @@ -27,7 +28,7 @@ namespace GodotTools.IdeMessaging private readonly IMessageHandler messageHandler; - private Peer peer; + private Peer? peer; private readonly SemaphoreSlim connectionSem = new SemaphoreSlim(1); private readonly Queue<NotifyAwaiter<bool>> clientConnectedAwaiters = new Queue<NotifyAwaiter<bool>>(); @@ -53,6 +54,7 @@ namespace GodotTools.IdeMessaging public bool IsDisposed { get; private set; } // ReSharper disable once MemberCanBePrivate.Global + [MemberNotNullWhen(true, "peer")] public bool IsConnected => peer != null && !peer.IsDisposed && peer.IsTcpClientConnected; // ReSharper disable once EventNeverSubscribedTo.Global @@ -111,7 +113,7 @@ namespace GodotTools.IdeMessaging if (disposing) { peer?.Dispose(); - fsWatcher?.Dispose(); + fsWatcher.Dispose(); } } @@ -215,12 +217,12 @@ namespace GodotTools.IdeMessaging using (var fileStream = new FileStream(MetaFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (var reader = new StreamReader(fileStream)) { - string portStr = reader.ReadLine(); + string? portStr = reader.ReadLine(); if (portStr == null) return null; - string editorExecutablePath = reader.ReadLine(); + string? editorExecutablePath = reader.ReadLine(); if (editorExecutablePath == null) return null; @@ -333,7 +335,7 @@ namespace GodotTools.IdeMessaging } } - public async Task<TResponse> SendRequest<TResponse>(Request request) + public async Task<TResponse?> SendRequest<TResponse>(Request request) where TResponse : Response, new() { if (!IsConnected) @@ -346,7 +348,7 @@ namespace GodotTools.IdeMessaging return await peer.SendRequest<TResponse>(request.Id, body); } - public async Task<TResponse> SendRequest<TResponse>(string id, string body) + public async Task<TResponse?> SendRequest<TResponse>(string id, string body) where TResponse : Response, new() { if (!IsConnected) diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientHandshake.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientHandshake.cs index 43041be7be..7fef628c79 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientHandshake.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientHandshake.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; namespace GodotTools.IdeMessaging @@ -9,7 +10,7 @@ namespace GodotTools.IdeMessaging public string GetHandshakeLine(string identity) => $"{ClientHandshakeBase},{identity}"; - public bool IsValidPeerHandshake(string handshake, out string identity, ILogger logger) + public bool IsValidPeerHandshake(string handshake, [NotNullWhen(true)] out string? identity, ILogger logger) { identity = null; diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientMessageHandler.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientMessageHandler.cs index 64bcfd824c..0321aa1b57 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientMessageHandler.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ClientMessageHandler.cs @@ -42,7 +42,7 @@ namespace GodotTools.IdeMessaging [OpenFileRequest.Id] = async (peer, content) => { var request = JsonConvert.DeserializeObject<OpenFileRequest>(content.Body); - return await HandleOpenFile(request); + return await HandleOpenFile(request!); } }; } diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/CodeAnalysisAttributes.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/CodeAnalysisAttributes.cs new file mode 100644 index 0000000000..a4a7ee82df --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/CodeAnalysisAttributes.cs @@ -0,0 +1,142 @@ +// ReSharper disable once CheckNamespace +namespace System.Diagnostics.CodeAnalysis +{ + /// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary> + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class AllowNullAttribute : Attribute + { } + + /// <summary>Specifies that null is disallowed as an input even if the corresponding type allows it.</summary> + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class DisallowNullAttribute : Attribute + { } + + /// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary> + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class MaybeNullAttribute : Attribute + { } + + /// <summary>Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns.</summary> + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class NotNullAttribute : Attribute + { } + + /// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter may be null even if the corresponding type disallows it.</summary> + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class MaybeNullWhenAttribute : Attribute + { + /// <summary>Initializes the attribute with the specified return value condition.</summary> + /// <param name="returnValue"> + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// </param> + public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// <summary>Gets the return value condition.</summary> + public bool ReturnValue { get; } + } + + /// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.</summary> + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class NotNullWhenAttribute : Attribute + { + /// <summary>Initializes the attribute with the specified return value condition.</summary> + /// <param name="returnValue"> + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// </param> + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// <summary>Gets the return value condition.</summary> + public bool ReturnValue { get; } + } + + /// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary> + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] + internal sealed class NotNullIfNotNullAttribute : Attribute + { + /// <summary>Initializes the attribute with the associated parameter name.</summary> + /// <param name="parameterName"> + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// </param> + public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// <summary>Gets the associated parameter name.</summary> + public string ParameterName { get; } + } + + /// <summary>Applied to a method that will never return under any circumstance.</summary> + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + internal sealed class DoesNotReturnAttribute : Attribute + { } + + /// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary> + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class DoesNotReturnIfAttribute : Attribute + { + /// <summary>Initializes the attribute with the specified parameter value.</summary> + /// <param name="parameterValue"> + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// </param> + public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// <summary>Gets the condition parameter value.</summary> + public bool ParameterValue { get; } + } + + /// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values.</summary> + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullAttribute : Attribute + { + /// <summary>Initializes the attribute with a field or property member.</summary> + /// <param name="member"> + /// The field or property member that is promised to be not-null. + /// </param> + public MemberNotNullAttribute(string member) => Members = new[] { member }; + + /// <summary>Initializes the attribute with the list of field and property members.</summary> + /// <param name="members"> + /// The list of field and property members that are promised to be not-null. + /// </param> + public MemberNotNullAttribute(params string[] members) => Members = members; + + /// <summary>Gets field or property member names.</summary> + public string[] Members { get; } + } + + /// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition.</summary> + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullWhenAttribute : Attribute + { + /// <summary>Initializes the attribute with the specified return value condition and a field or property member.</summary> + /// <param name="returnValue"> + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// </param> + /// <param name="member"> + /// The field or property member that is promised to be not-null. + /// </param> + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new[] { member }; + } + + /// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary> + /// <param name="returnValue"> + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// </param> + /// <param name="members"> + /// The list of field and property members that are promised to be not-null. + /// </param> + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// <summary>Gets the return value condition.</summary> + public bool ReturnValue { get; } + + /// <summary>Gets field or property member names.</summary> + public string[] Members { get; } + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs index 2448a2953b..f11a7cc149 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs @@ -1,3 +1,5 @@ +using System.Diagnostics.CodeAnalysis; + namespace GodotTools.IdeMessaging { public readonly struct GodotIdeMetadata @@ -23,7 +25,7 @@ namespace GodotTools.IdeMessaging return !(a == b); } - public override bool Equals(object obj) + public override bool Equals([NotNullWhen(true)] object? obj) { return obj is GodotIdeMetadata metadata && metadata == this; } diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj index 02f1764f32..be6af398e2 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj @@ -2,9 +2,10 @@ <PropertyGroup> <ProjectGuid>{92600954-25F0-4291-8E11-1FEE9FC4BE20}</ProjectGuid> <TargetFramework>netstandard2.0</TargetFramework> - <LangVersion>7.2</LangVersion> + <LangVersion>9</LangVersion> + <Nullable>enable</Nullable> <PackageId>GodotTools.IdeMessaging</PackageId> - <Version>1.1.1</Version> + <Version>1.1.2</Version> <AssemblyVersion>$(Version)</AssemblyVersion> <Authors>Godot Engine contributors</Authors> <Company /> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IHandshake.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IHandshake.cs index 6387145a28..8ec60876cc 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IHandshake.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/IHandshake.cs @@ -1,8 +1,10 @@ +using System.Diagnostics.CodeAnalysis; + namespace GodotTools.IdeMessaging { public interface IHandshake { string GetHandshakeLine(string identity); - bool IsValidPeerHandshake(string handshake, out string identity, ILogger logger); + bool IsValidPeerHandshake(string handshake, [NotNullWhen(true)] out string? identity, ILogger logger); } } diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/MessageDecoder.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/MessageDecoder.cs index a00575a2a1..caf1ae2705 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/MessageDecoder.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/MessageDecoder.cs @@ -8,7 +8,7 @@ namespace GodotTools.IdeMessaging private class DecodedMessage { public MessageKind? Kind; - public string Id; + public string? Id; public MessageStatus? Status; public readonly StringBuilder Body = new StringBuilder(); public uint? PendingBodyLines; @@ -41,7 +41,7 @@ namespace GodotTools.IdeMessaging private readonly DecodedMessage decodingMessage = new DecodedMessage(); - public State Decode(string messageLine, out Message decodedMessage) + public State Decode(string messageLine, out Message? decodedMessage) { decodedMessage = null; diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs index dd3913b4f3..5e453dcfab 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs @@ -46,11 +46,11 @@ namespace GodotTools.IdeMessaging private readonly SemaphoreSlim writeSem = new SemaphoreSlim(1); - private string remoteIdentity = string.Empty; - public string RemoteIdentity => remoteIdentity; + private string? remoteIdentity; + public string RemoteIdentity => remoteIdentity ??= string.Empty; - public event Action Connected; - public event Action Disconnected; + public event Action? Connected; + public event Action? Disconnected; private ILogger Logger { get; } @@ -87,7 +87,7 @@ namespace GodotTools.IdeMessaging { var decoder = new MessageDecoder(); - string messageLine; + string? messageLine; while ((messageLine = await ReadLine()) != null) { var state = decoder.Decode(messageLine, out var msg); @@ -105,7 +105,7 @@ namespace GodotTools.IdeMessaging try { - if (msg.Kind == MessageKind.Request) + if (msg!.Kind == MessageKind.Request) { var responseContent = await messageHandler.HandleRequest(this, msg.Id, msg.Content, Logger); await WriteMessage(new Message(MessageKind.Response, msg.Id, responseContent)); @@ -163,9 +163,9 @@ namespace GodotTools.IdeMessaging return false; } - string peerHandshake = await readHandshakeTask; + string? peerHandshake = await readHandshakeTask; - if (handshake == null || !handshake.IsValidPeerHandshake(peerHandshake, out remoteIdentity, Logger)) + if (peerHandshake == null || !handshake.IsValidPeerHandshake(peerHandshake, out remoteIdentity, Logger)) { Logger.LogError("Received invalid handshake: " + peerHandshake); return false; @@ -179,7 +179,7 @@ namespace GodotTools.IdeMessaging return true; } - private async Task<string> ReadLine() + private async Task<string?> ReadLine() { try { @@ -216,7 +216,7 @@ namespace GodotTools.IdeMessaging return WriteLine(builder.ToString()); } - public async Task<TResponse> SendRequest<TResponse>(string id, string body) + public async Task<TResponse?> SendRequest<TResponse>(string id, string body) where TResponse : Response, new() { ResponseAwaiter responseAwaiter; @@ -243,7 +243,7 @@ namespace GodotTools.IdeMessaging private async Task<bool> WriteLine(string text) { - if (clientWriter == null || IsDisposed || !IsTcpClientConnected) + if (IsDisposed || !IsTcpClientConnected) return false; using (await writeSem.UseAsync()) @@ -290,9 +290,9 @@ namespace GodotTools.IdeMessaging Disconnected?.Invoke(); } - clientReader?.Dispose(); - clientWriter?.Dispose(); - ((IDisposable)tcpClient)?.Dispose(); + clientReader.Dispose(); + clientWriter.Dispose(); + ((IDisposable)tcpClient).Dispose(); } } } diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs index e93db9377b..452593b673 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs @@ -2,6 +2,7 @@ // ReSharper disable UnusedMember.Global // ReSharper disable UnusedAutoPropertyAccessor.Global +using System; using Newtonsoft.Json; namespace GodotTools.IdeMessaging.Requests @@ -38,7 +39,7 @@ namespace GodotTools.IdeMessaging.Requests } public CompletionKind Kind { get; set; } - public string ScriptFile { get; set; } + public string ScriptFile { get; set; } = string.Empty; public new const string Id = "CodeCompletion"; @@ -50,8 +51,8 @@ namespace GodotTools.IdeMessaging.Requests public sealed class CodeCompletionResponse : Response { public CodeCompletionRequest.CompletionKind Kind; - public string ScriptFile { get; set; } - public string[] Suggestions { get; set; } + public string ScriptFile { get; set; } = string.Empty; + public string[] Suggestions { get; set; } = Array.Empty<string>(); } public sealed class PlayRequest : Request @@ -82,7 +83,7 @@ namespace GodotTools.IdeMessaging.Requests public sealed class DebugPlayRequest : Request { - public string DebuggerHost { get; set; } + public string DebuggerHost { get; set; } = string.Empty; public int DebuggerPort { get; set; } public bool? BuildBeforePlaying { get; set; } @@ -99,7 +100,7 @@ namespace GodotTools.IdeMessaging.Requests public sealed class OpenFileRequest : Request { - public string File { get; set; } + public string File { get; set; } = string.Empty; public int? Line { get; set; } public int? Column { get; set; } diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ResponseAwaiter.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ResponseAwaiter.cs index a57c82b608..b09575d5d2 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ResponseAwaiter.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/ResponseAwaiter.cs @@ -15,7 +15,7 @@ namespace GodotTools.IdeMessaging public override void SetResult(MessageContent content) { if (content.Status == MessageStatus.Ok) - SetResult(JsonConvert.DeserializeObject<T>(content.Body)); + SetResult(JsonConvert.DeserializeObject<T>(content.Body)!); else SetResult(new T { Status = content.Status }); } diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/NotifyAwaiter.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/NotifyAwaiter.cs index a285d5fa97..6dde1828a9 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/NotifyAwaiter.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Utils/NotifyAwaiter.cs @@ -1,3 +1,6 @@ +// ReSharper disable ParameterHidesMember +// ReSharper disable UnusedMember.Global + using System; using System.Runtime.CompilerServices; @@ -5,9 +8,9 @@ namespace GodotTools.IdeMessaging.Utils { public class NotifyAwaiter<T> : INotifyCompletion { - private Action continuation; - private Exception exception; - private T result; + private Action? continuation; + private Exception? exception; + private T? result; public bool IsCompleted { get; private set; } @@ -15,7 +18,7 @@ namespace GodotTools.IdeMessaging.Utils { if (exception != null) throw exception; - return result; + return result!; } public void OnCompleted(Action continuation) diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj index 22778f21cb..c335e7b09f 100644 --- a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj @@ -4,6 +4,7 @@ <OutputType>Exe</OutputType> <TargetFramework>net6.0-windows</TargetFramework> <LangVersion>10</LangVersion> + <Nullable>enable</Nullable> </PropertyGroup> <PropertyGroup Condition="Exists('$(SolutionDir)/../../../../bin/GodotSharp/Api/Debug/GodotSharp.dll') And ('$(GodotPlatform)' == 'windows' Or ('$(GodotPlatform)' == '' And '$(OS)' == 'Windows_NT'))"> <OutputPath>$(SolutionDir)/../../../../bin/GodotSharp/Tools</OutputPath> diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs index 8e8eaa79b8..3072ca2857 100644 --- a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs +++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs @@ -53,6 +53,12 @@ namespace GodotTools.OpenVisualStudio { // Launch of VS 2022 failed, fallback to 2019 dte = TryVisualStudioLaunch("VisualStudio.DTE.16.0"); + + if (dte == null) + { + Console.Error.WriteLine("Visual Studio not found"); + return 1; + } } dte.UserControl = true; @@ -137,12 +143,12 @@ namespace GodotTools.OpenVisualStudio return 0; } - private static DTE TryVisualStudioLaunch(string version) + private static DTE? TryVisualStudioLaunch(string version) { try { var visualStudioDteType = Type.GetTypeFromProgID(version, throwOnError: true); - var dte = (DTE)Activator.CreateInstance(visualStudioDteType); + var dte = (DTE?)Activator.CreateInstance(visualStudioDteType!); return dte; } @@ -152,7 +158,7 @@ namespace GodotTools.OpenVisualStudio } } - private static DTE FindInstanceEditingSolution(string solutionPath) + private static DTE? FindInstanceEditingSolution(string solutionPath) { if (GetRunningObjectTable(0, out IRunningObjectTable pprot) != 0) return null; @@ -218,7 +224,7 @@ namespace GodotTools.OpenVisualStudio // Class containing the IOleMessageFilter // thread error-handling functions - private static IOleMessageFilter _oldFilter; + private static IOleMessageFilter? _oldFilter; // Start the filter public static void Register() @@ -268,7 +274,7 @@ namespace GodotTools.OpenVisualStudio // Implement the IOleMessageFilter interface [DllImport("ole32.dll")] - private static extern int CoRegisterMessageFilter(IOleMessageFilter newFilter, out IOleMessageFilter oldFilter); + private static extern int CoRegisterMessageFilter(IOleMessageFilter? newFilter, out IOleMessageFilter? oldFilter); } [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs index 355b21d63a..ff15b96c1c 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs @@ -34,22 +34,23 @@ EndProject"; @" {{{0}}}.{1}|Any CPU.ActiveCfg = {1}|Any CPU {{{0}}}.{1}|Any CPU.Build.0 = {1}|Any CPU"; - private string _directoryPath; private readonly Dictionary<string, ProjectInfo> _projects = new Dictionary<string, ProjectInfo>(); public string Name { get; } - - public string DirectoryPath - { - get => _directoryPath; - set => _directoryPath = value.IsAbsolutePath() ? value : Path.GetFullPath(value); - } + public string DirectoryPath { get; } public class ProjectInfo { - public string Guid; - public string PathRelativeToSolution; - public List<string> Configs = new List<string>(); + public string Guid { get; } + public string PathRelativeToSolution { get; } + public List<string> Configs { get; } + + public ProjectInfo(string guid, string pathRelativeToSolution, List<string> configs) + { + Guid = guid; + PathRelativeToSolution = pathRelativeToSolution; + Configs = configs; + } } public void AddNewProject(string name, ProjectInfo projectInfo) @@ -117,9 +118,10 @@ EndProject"; File.WriteAllText(solutionPath, content, Encoding.UTF8); // UTF-8 with BOM } - public DotNetSolution(string name) + public DotNetSolution(string name, string directoryPath) { Name = name; + DirectoryPath = directoryPath.IsAbsolutePath() ? directoryPath : Path.GetFullPath(directoryPath); } public static void MigrateFromOldConfigNames(string slnPath) diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj index bde14b2b40..623475e11a 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj @@ -3,6 +3,7 @@ <ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid> <TargetFramework>net6.0</TargetFramework> <LangVersion>10</LangVersion> + <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Build" Version="15.1.548" ExcludeAssets="runtime" /> diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs index 1d17f3d4f5..794443a69c 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs @@ -34,7 +34,7 @@ namespace GodotTools.ProjectEditor public static void MSBuildLocatorRegisterMSBuildPath(string msbuildPath) => MSBuildLocator.RegisterMSBuildPath(msbuildPath); - public static MSBuildProject Open(string path) + public static MSBuildProject? Open(string path) { var root = ProjectRootElement.Open(path); return root != null ? new MSBuildProject(root) : null; diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildDiagnostic.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildDiagnostic.cs index 6e0c63dd43..79eb9e2ce2 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildDiagnostic.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildDiagnostic.cs @@ -1,5 +1,3 @@ -#nullable enable - namespace GodotTools.Build { public class BuildDiagnostic diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs index 7c02f29606..be0b7d3222 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs @@ -1,11 +1,10 @@ using System; +using System.Diagnostics.CodeAnalysis; using Godot; using Godot.Collections; using GodotTools.Internals; using Path = System.IO.Path; -#nullable enable - namespace GodotTools.Build { [Serializable] @@ -25,7 +24,7 @@ namespace GodotTools.Build public string LogsDirPath => GodotSharpDirs.LogsDirPathFor(Solution, Configuration); - public override bool Equals(object? obj) + public override bool Equals([NotNullWhen(true)] object? obj) { return obj is BuildInfo other && other.Solution == Solution && diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs index 6e99483a1c..ebb2677361 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs @@ -11,18 +11,18 @@ namespace GodotTools.Build { public static class BuildManager { - private static BuildInfo _buildInProgress; + private static BuildInfo? _buildInProgress; public const string MsBuildIssuesFileName = "msbuild_issues.csv"; private const string MsBuildLogFileName = "msbuild_log.txt"; public delegate void BuildLaunchFailedEventHandler(BuildInfo buildInfo, string reason); - public static event BuildLaunchFailedEventHandler BuildLaunchFailed; - public static event Action<BuildInfo> BuildStarted; - public static event Action<BuildResult> BuildFinished; - public static event Action<string> StdOutputReceived; - public static event Action<string> StdErrorReceived; + public static event BuildLaunchFailedEventHandler? BuildLaunchFailed; + public static event Action<BuildInfo>? BuildStarted; + public static event Action<BuildResult>? BuildFinished; + public static event Action<string?>? StdOutputReceived; + public static event Action<string?>? StdErrorReceived; public static DateTime LastValidBuildDateTime { get; private set; } @@ -274,8 +274,8 @@ namespace GodotTools.Build } private static BuildInfo CreateBuildInfo( - [DisallowNull] string configuration, - [AllowNull] string platform = null, + string configuration, + string? platform = null, bool rebuild = false, bool onlyClean = false ) @@ -294,10 +294,10 @@ namespace GodotTools.Build } private static BuildInfo CreatePublishBuildInfo( - [DisallowNull] string configuration, - [DisallowNull] string platform, - [DisallowNull] string runtimeIdentifier, - [DisallowNull] string publishOutputDir, + string configuration, + string platform, + string runtimeIdentifier, + string publishOutputDir, bool includeDebugSymbols = true ) { @@ -319,20 +319,20 @@ namespace GodotTools.Build } public static bool BuildProjectBlocking( - [DisallowNull] string configuration, - [AllowNull] string platform = null, + string configuration, + string? platform = null, bool rebuild = false ) => BuildProjectBlocking(CreateBuildInfo(configuration, platform, rebuild)); public static bool CleanProjectBlocking( - [DisallowNull] string configuration, - [AllowNull] string platform = null + string configuration, + string? platform = null ) => CleanProjectBlocking(CreateBuildInfo(configuration, platform, rebuild: false, onlyClean: true)); public static bool PublishProjectBlocking( - [DisallowNull] string configuration, - [DisallowNull] string platform, - [DisallowNull] string runtimeIdentifier, + string configuration, + string platform, + string runtimeIdentifier, string publishOutputDir, bool includeDebugSymbols = true ) => PublishProjectBlocking(CreatePublishBuildInfo(configuration, diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs index f9e85c36e5..5cf6581fc4 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildOutputView.cs @@ -1,8 +1,6 @@ using Godot; using static GodotTools.Internals.Globals; -#nullable enable - namespace GodotTools.Build { public partial class BuildOutputView : HBoxContainer diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsFilter.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsFilter.cs index 9c165e5767..2071f687b3 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsFilter.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsFilter.cs @@ -1,7 +1,5 @@ using Godot; -#nullable enable - namespace GodotTools.Build { public class BuildProblemsFilter diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs index d62eb3ce9e..fef169aa07 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs @@ -8,8 +8,6 @@ using GodotTools.Internals; using static GodotTools.Internals.Globals; using FileAccess = Godot.FileAccess; -#nullable enable - namespace GodotTools.Build { public partial class BuildProblemsView : HBoxContainer @@ -244,7 +242,9 @@ namespace GodotTools.Build if (string.IsNullOrEmpty(projectDir)) return; - string file = Path.Combine(projectDir.SimplifyGodotPath(), diagnostic.File.SimplifyGodotPath()); + string? file = !string.IsNullOrEmpty(diagnostic.File) ? + Path.Combine(projectDir.SimplifyGodotPath(), diagnostic.File.SimplifyGodotPath()) : + null; if (!File.Exists(file)) return; diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs index 57b5598a78..5ae4dfa076 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs @@ -17,10 +17,10 @@ namespace GodotTools.Build { public static class BuildSystem { - private static Process LaunchBuild(BuildInfo buildInfo, Action<string> stdOutHandler, - Action<string> stdErrHandler) + private static Process LaunchBuild(BuildInfo buildInfo, Action<string?>? stdOutHandler, + Action<string?>? stdErrHandler) { - string dotnetPath = DotNetFinder.FindDotNetExe(); + string? dotnetPath = DotNetFinder.FindDotNetExe(); if (dotnetPath == null) throw new FileNotFoundException("Cannot find the dotnet executable."); @@ -67,7 +67,7 @@ namespace GodotTools.Build return process; } - public static int Build(BuildInfo buildInfo, Action<string> stdOutHandler, Action<string> stdErrHandler) + public static int Build(BuildInfo buildInfo, Action<string?>? stdOutHandler, Action<string?>? stdErrHandler) { using (var process = LaunchBuild(buildInfo, stdOutHandler, stdErrHandler)) { @@ -77,8 +77,8 @@ namespace GodotTools.Build } } - public static async Task<int> BuildAsync(BuildInfo buildInfo, Action<string> stdOutHandler, - Action<string> stdErrHandler) + public static async Task<int> BuildAsync(BuildInfo buildInfo, Action<string?>? stdOutHandler, + Action<string?>? stdErrHandler) { using (var process = LaunchBuild(buildInfo, stdOutHandler, stdErrHandler)) { @@ -88,10 +88,10 @@ namespace GodotTools.Build } } - private static Process LaunchPublish(BuildInfo buildInfo, Action<string> stdOutHandler, - Action<string> stdErrHandler) + private static Process LaunchPublish(BuildInfo buildInfo, Action<string?>? stdOutHandler, + Action<string?>? stdErrHandler) { - string dotnetPath = DotNetFinder.FindDotNetExe(); + string? dotnetPath = DotNetFinder.FindDotNetExe(); if (dotnetPath == null) throw new FileNotFoundException("Cannot find the dotnet executable."); @@ -137,7 +137,7 @@ namespace GodotTools.Build return process; } - public static int Publish(BuildInfo buildInfo, Action<string> stdOutHandler, Action<string> stdErrHandler) + public static int Publish(BuildInfo buildInfo, Action<string?>? stdOutHandler, Action<string?>? stdErrHandler) { using (var process = LaunchPublish(buildInfo, stdOutHandler, stdErrHandler)) { @@ -297,7 +297,7 @@ namespace GodotTools.Build } private static Process DoGenerateXCFramework(List<string> outputPaths, string xcFrameworkPath, - Action<string> stdOutHandler, Action<string> stdErrHandler) + Action<string?>? stdOutHandler, Action<string?>? stdErrHandler) { if (Directory.Exists(xcFrameworkPath)) { @@ -341,7 +341,7 @@ namespace GodotTools.Build return process; } - public static int GenerateXCFramework(List<string> outputPaths, string xcFrameworkPath, Action<string> stdOutHandler, Action<string> stdErrHandler) + public static int GenerateXCFramework(List<string> outputPaths, string xcFrameworkPath, Action<string?>? stdOutHandler, Action<string?>? stdErrHandler) { using (var process = DoGenerateXCFramework(outputPaths, xcFrameworkPath, stdOutHandler, stdErrHandler)) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/DotNetFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/DotNetFinder.cs index cfe79cf3e1..4d1456b70c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/DotNetFinder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/DotNetFinder.cs @@ -5,15 +5,13 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using System.Text; -using JetBrains.Annotations; using OS = GodotTools.Utils.OS; namespace GodotTools.Build { public static class DotNetFinder { - [CanBeNull] - public static string FindDotNetExe() + public static string? FindDotNetExe() { // In the future, this method may do more than just search in PATH. We could look in // known locations or use Godot's linked nethost to search from the hostfxr location. @@ -40,14 +38,14 @@ namespace GodotTools.Build public static bool TryFindDotNetSdk( Version expectedVersion, - [NotNullWhen(true)] out Version version, - [NotNullWhen(true)] out string path + [NotNullWhen(true)] out Version? version, + [NotNullWhen(true)] out string? path ) { version = null; path = null; - string dotNetExe = FindDotNetExe(); + string? dotNetExe = FindDotNetExe(); if (string.IsNullOrEmpty(dotNetExe)) return false; @@ -86,8 +84,8 @@ namespace GodotTools.Build process.BeginOutputReadLine(); process.WaitForExit(); - Version latestVersionMatch = null; - string matchPath = null; + Version? latestVersionMatch = null; + string? matchPath = null; foreach (var line in lines) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs index 9a02c9ca88..986da47860 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs @@ -5,8 +5,6 @@ using GodotTools.Internals; using static GodotTools.Internals.Globals; using File = GodotTools.Utils.File; -#nullable enable - namespace GodotTools.Build { public partial class MSBuildPanel : MarginContainer, ISerializationListener @@ -183,7 +181,7 @@ namespace GodotTools.Build } } - private void StdOutputReceived(string text) + private void StdOutputReceived(string? text) { lock (_pendingBuildLogTextLock) { @@ -193,7 +191,7 @@ namespace GodotTools.Build } } - private void StdErrorReceived(string text) + private void StdErrorReceived(string? text) { lock (_pendingBuildLogTextLock) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index c4f0b77ecf..372c4b114b 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -1,6 +1,7 @@ using Godot; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Security.Cryptography; @@ -73,7 +74,7 @@ namespace GodotTools.Export }; } - private string _maybeLastExportError; + private string? _maybeLastExportError; // With this method we can override how a file is exported in the PCK public override void _ExportFile(string path, string type, string[] features) @@ -135,7 +136,7 @@ namespace GodotTools.Export if (!ProjectContainsDotNet()) return; - if (!DeterminePlatformFromFeatures(features, out string platform)) + if (!DeterminePlatformFromFeatures(features, out string? platform)) throw new NotSupportedException("Target platform not supported."); if (!new[] { OS.Platforms.Windows, OS.Platforms.LinuxBSD, OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS } @@ -327,7 +328,7 @@ namespace GodotTools.Export AddSharedObject(path, tags: null, Path.Join(projectDataDirName, Path.GetRelativePath(publishOutputDir, - Path.GetDirectoryName(path)))); + Path.GetDirectoryName(path)!))); } } } @@ -450,7 +451,7 @@ namespace GodotTools.Export } } - private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, out string platform) + private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, [NotNullWhen(true)] out string? platform) { foreach (var feature in features) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/XcodeHelper.cs b/modules/mono/editor/GodotTools/GodotTools/Export/XcodeHelper.cs index 4f5bebfb42..023f46b685 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/XcodeHelper.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/XcodeHelper.cs @@ -5,7 +5,7 @@ namespace GodotTools.Export { public static class XcodeHelper { - private static string _XcodePath = null; + private static string? _XcodePath = null; public static string XcodePath { @@ -23,7 +23,7 @@ namespace GodotTools.Export } } - private static string FindSelectedXcode() + private static string? FindSelectedXcode() { var outputWrapper = new Godot.Collections.Array(); @@ -40,9 +40,9 @@ namespace GodotTools.Export return null; } - public static string FindXcode() + public static string? FindXcode() { - string selectedXcode = FindSelectedXcode(); + string? selectedXcode = FindSelectedXcode(); if (selectedXcode != null) { if (Directory.Exists(Path.Combine(selectedXcode, "Contents", "Developer"))) @@ -50,10 +50,10 @@ namespace GodotTools.Export // The path already pointed to Contents/Developer var dirInfo = new DirectoryInfo(selectedXcode); - if (dirInfo.Name != "Developer" || dirInfo.Parent.Name != "Contents") + if (dirInfo is not { Parent.Name: "Contents", Name: "Developer" }) { Console.WriteLine(Path.GetDirectoryName(selectedXcode)); - Console.WriteLine(System.IO.Directory.GetParent(selectedXcode).Name); + Console.WriteLine(System.IO.Directory.GetParent(selectedXcode)?.Name); Console.Error.WriteLine("Unrecognized path for selected Xcode"); } else diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 44422eb862..dcbcc4352b 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -34,6 +34,7 @@ namespace GodotTools public const string ProblemsLayout = "dotnet/build/problems_layout"; } +#nullable disable private EditorSettings _editorSettings; private PopupMenu _menuPopup; @@ -51,6 +52,7 @@ namespace GodotTools public GodotIdeManager GodotIdeManager { get; private set; } public MSBuildPanel MSBuildPanel { get; private set; } +#nullable enable public bool SkipBuildBeforePlaying { get; set; } = false; @@ -67,29 +69,23 @@ namespace GodotTools private bool CreateProjectSolution() { - string errorMessage = null; + string? errorMessage = null; using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 2)) { pr.Step("Generating C# project...".TTR()); - string csprojDir = Path.GetDirectoryName(GodotSharpDirs.ProjectCsProjPath); - string slnDir = Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath); + string csprojDir = Path.GetDirectoryName(GodotSharpDirs.ProjectCsProjPath)!; + string slnDir = Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath)!; string name = GodotSharpDirs.ProjectAssemblyName; string guid = CsProjOperations.GenerateGameProject(csprojDir, name); if (guid.Length > 0) { - var solution = new DotNetSolution(name) - { - DirectoryPath = slnDir - }; + var solution = new DotNetSolution(name, slnDir); - var projectInfo = new DotNetSolution.ProjectInfo - { - Guid = guid, - PathRelativeToSolution = Path.GetRelativePath(slnDir, GodotSharpDirs.ProjectCsProjPath), - Configs = new List<string> { "Debug", "ExportDebug", "ExportRelease" } - }; + var projectInfo = new DotNetSolution.ProjectInfo(guid, + Path.GetRelativePath(slnDir, GodotSharpDirs.ProjectCsProjPath), + new List<string> { "Debug", "ExportDebug", "ExportRelease" }); solution.AddNewProject(name, projectInfo); @@ -342,7 +338,7 @@ namespace GodotTools } } - args.Add(Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath)); + args.Add(Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath)!); string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath); @@ -459,7 +455,7 @@ namespace GodotTools // First we try to find the .NET Sdk ourselves to make sure we get the // correct version first, otherwise pick the latest. - if (DotNetFinder.TryFindDotNetSdk(dotNetSdkSearchVersion, out var sdkVersion, out string sdkPath)) + if (DotNetFinder.TryFindDotNetSdk(dotNetSdkSearchVersion, out var sdkVersion, out string? sdkPath)) { if (Godot.OS.IsStdOutVerbose()) Console.WriteLine($"Found .NET Sdk version '{sdkVersion}': {sdkPath}"); @@ -694,8 +690,9 @@ namespace GodotTools } // Singleton - +#nullable disable public static GodotSharpEditor Instance { get; private set; } +#nullable enable [UsedImplicitly] private static IntPtr InternalCreateInstance(IntPtr unmanagedCallbacks, int unmanagedCallbacksSize) diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index b5567ea3c7..ff14ee7b5d 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -4,6 +4,7 @@ <TargetFramework>net6.0</TargetFramework> <EnableDynamicLoading>true</EnableDynamicLoading> <LangVersion>10</LangVersion> + <Nullable>enable</Nullable> <!-- The Godot editor uses the Debug Godot API assemblies --> <GodotApiConfiguration>Debug</GodotApiConfiguration> <GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath> diff --git a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs index 66717d8636..638b7d6420 100644 --- a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs +++ b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs @@ -7,7 +7,9 @@ namespace GodotTools { public partial class HotReloadAssemblyWatcher : Node { +#nullable disable private Timer _watchTimer; +#nullable enable public override void _Notification(int what) { diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs index 65b77112aa..6563bfbb06 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/GodotIdeManager.cs @@ -10,10 +10,10 @@ namespace GodotTools.Ides { public sealed partial class GodotIdeManager : Node, ISerializationListener { - private MessagingServer _messagingServer; + private MessagingServer? _messagingServer; - private MonoDevelop.Instance _monoDevelInstance; - private MonoDevelop.Instance _vsForMacInstance; + private MonoDevelop.Instance? _monoDevelInstance; + private MonoDevelop.Instance? _vsForMacInstance; private MessagingServer GetRunningOrNewServer() { @@ -59,7 +59,7 @@ namespace GodotTools.Ides switch (editorId) { case ExternalEditorId.None: - return null; + return string.Empty; case ExternalEditorId.VisualStudio: return "VisualStudio"; case ExternalEditorId.VsCode: diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs index 51c7a8aa22..c5acc5e2db 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Net; @@ -97,9 +98,9 @@ namespace GodotTools.Ides foreach (var connection in Peers) connection.Dispose(); Peers.Clear(); - _listener?.Stop(); + _listener.Stop(); - _metaFile?.Dispose(); + _metaFile.Dispose(); File.Delete(_metaFilePath); } @@ -122,7 +123,7 @@ namespace GodotTools.Ides _listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, port: 0)); _listener.Start(); - int port = ((IPEndPoint)_listener.Server.LocalEndPoint).Port; + int port = ((IPEndPoint?)_listener.Server.LocalEndPoint)?.Port ?? 0; using (var metaFileWriter = new StreamWriter(_metaFile, Encoding.UTF8)) { metaFileWriter.WriteLine(port); @@ -235,7 +236,7 @@ namespace GodotTools.Ides public string GetHandshakeLine(string identity) => $"{_serverHandshakeBase},{identity}"; - public bool IsValidPeerHandshake(string handshake, out string identity, ILogger logger) + public bool IsValidPeerHandshake(string handshake, [NotNullWhen(true)] out string? identity, ILogger logger) { identity = null; @@ -311,12 +312,12 @@ namespace GodotTools.Ides [DebugPlayRequest.Id] = async (peer, content) => { var request = JsonConvert.DeserializeObject<DebugPlayRequest>(content.Body); - return await HandleDebugPlay(request); + return await HandleDebugPlay(request!); }, [StopPlayRequest.Id] = async (peer, content) => { var request = JsonConvert.DeserializeObject<StopPlayRequest>(content.Body); - return await HandleStopPlay(request); + return await HandleStopPlay(request!); }, [ReloadScriptsRequest.Id] = async (peer, content) => { @@ -326,7 +327,7 @@ namespace GodotTools.Ides [CodeCompletionRequest.Id] = async (peer, content) => { var request = JsonConvert.DeserializeObject<CodeCompletionRequest>(content.Body); - return await HandleCodeCompletionRequest(request); + return await HandleCodeCompletionRequest(request!); } }; } @@ -383,7 +384,7 @@ namespace GodotTools.Ides { // This is needed if the "resource path" part of the path is case insensitive. // However, it doesn't fix resource loading if the rest of the path is also case insensitive. - string scriptFileLocalized = FsPathUtils.LocalizePathWithCaseChecked(request.ScriptFile); + string? scriptFileLocalized = FsPathUtils.LocalizePathWithCaseChecked(request.ScriptFile); // The node API can only be called from the main thread. await Godot.Engine.GetMainLoop().ToSignal(Godot.Engine.GetMainLoop(), "process_frame"); diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs index 7a0983a8cb..66983156d0 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs @@ -13,7 +13,7 @@ namespace GodotTools.Ides.MonoDevelop private readonly string _solutionFile; private readonly EditorId _editorId; - private Process _process; + private Process? _process; public bool IsRunning => _process != null && !_process.HasExited; public bool IsDisposed { get; private set; } @@ -24,7 +24,7 @@ namespace GodotTools.Ides.MonoDevelop var args = new List<string>(); - string command; + string? command; if (OS.IsMacOS) { @@ -136,6 +136,8 @@ namespace GodotTools.Ides.MonoDevelop {EditorId.MonoDevelop, "monodevelop"} }; } + ExecutableNames ??= new Dictionary<EditorId, string>(); + BundleIds ??= new Dictionary<EditorId, string>(); } } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderLocatorEnvironment.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderLocatorEnvironment.cs index 61c1581281..77e89dfb7f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderLocatorEnvironment.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderLocatorEnvironment.cs @@ -20,12 +20,12 @@ public class RiderLocatorEnvironment : IRiderLocatorEnvironment } } - public T FromJson<T>(string json) + public T? FromJson<T>(string json) { return JsonConvert.DeserializeObject<T>(json); } - public void Info(string message, Exception e = null) + public void Info(string message, Exception? e = null) { if (e == null) GD.Print(message); @@ -33,7 +33,7 @@ public class RiderLocatorEnvironment : IRiderLocatorEnvironment GD.Print(message, e); } - public void Warn(string message, Exception e = null) + public void Warn(string message, Exception? e = null) { if (e == null) GD.PushWarning(message); @@ -41,7 +41,7 @@ public class RiderLocatorEnvironment : IRiderLocatorEnvironment GD.PushWarning(message, e); } - public void Error(string message, Exception e = null) + public void Error(string message, Exception? e = null) { if (e == null) GD.PushError(message); @@ -49,7 +49,7 @@ public class RiderLocatorEnvironment : IRiderLocatorEnvironment GD.PushError(message, e); } - public void Verbose(string message, Exception e = null) + public void Verbose(string message, Exception? e = null) { // do nothing, since IDK how to write only to the log, without spamming the output } diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs index a0ab381b9b..5c54d2d9ba 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs @@ -5,8 +5,6 @@ using Godot; using GodotTools.Internals; using JetBrains.Rider.PathLocator; -#nullable enable - namespace GodotTools.Ides.Rider { public static class RiderPathManager diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs index 67891a0594..94499c4f38 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.IO; using Godot; using Godot.NativeInterop; @@ -59,16 +60,17 @@ namespace GodotTools.Internals } } + [MemberNotNull("_projectAssemblyName", "_projectSlnPath", "_projectCsProjPath")] public static void DetermineProjectLocation() { - _projectAssemblyName = (string)ProjectSettings.GetSetting("dotnet/project/assembly_name"); + _projectAssemblyName = (string?)ProjectSettings.GetSetting("dotnet/project/assembly_name"); if (string.IsNullOrEmpty(_projectAssemblyName)) { _projectAssemblyName = CSharpProjectName; ProjectSettings.SetSetting("dotnet/project/assembly_name", _projectAssemblyName); } - string slnParentDir = (string)ProjectSettings.GetSetting("dotnet/project/solution_directory"); + string? slnParentDir = (string?)ProjectSettings.GetSetting("dotnet/project/solution_directory"); if (string.IsNullOrEmpty(slnParentDir)) slnParentDir = "res://"; else if (!slnParentDir.StartsWith("res://")) @@ -84,9 +86,9 @@ namespace GodotTools.Internals string.Concat(_projectAssemblyName, ".csproj")); } - private static string _projectAssemblyName; - private static string _projectSlnPath; - private static string _projectCsProjPath; + private static string? _projectAssemblyName; + private static string? _projectSlnPath; + private static string? _projectCsProjPath; public static string ProjectAssemblyName { diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs index e3c2c822a5..2abca985da 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs @@ -1,17 +1,19 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; namespace GodotTools.Utils { public static class CollectionExtensions { - public static T SelectFirstNotNull<T>(this IEnumerable<T> enumerable, Func<T, T> predicate, T orElse = null) + [return: NotNullIfNotNull("orElse")] + public static T? SelectFirstNotNull<T>(this IEnumerable<T> enumerable, Func<T, T?> predicate, T? orElse = null) where T : class { foreach (T elem in enumerable) { - T result = predicate(elem); + T? result = predicate(elem); if (result != null) return result; } @@ -21,7 +23,7 @@ namespace GodotTools.Utils public static IEnumerable<string> EnumerateLines(this TextReader textReader) { - string line; + string? line; while ((line = textReader.ReadLine()) != null) yield return line; } diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs index 89bda704bb..fee9646931 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs @@ -30,8 +30,7 @@ namespace GodotTools.Utils return childPathNorm.PathStartsWithAlreadyNorm(parentPathNorm); } - [return: MaybeNull] - public static string LocalizePathWithCaseChecked(string path) + public static string? LocalizePathWithCaseChecked(string path) { string pathNorm = path.NormalizePath() + Path.DirectorySeparatorChar; string resourcePathNorm = ResourcePath.NormalizePath() + Path.DirectorySeparatorChar; diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index c24b730c89..d5d8de93d2 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -150,8 +150,7 @@ namespace GodotTools.Utils public static char PathSep => IsWindows ? ';' : ':'; - [return: MaybeNull] - public static string PathWhich([NotNull] string name) + public static string? PathWhich(string name) { if (IsWindows) return PathWhichWindows(name); @@ -159,12 +158,11 @@ namespace GodotTools.Utils return PathWhichUnix(name); } - [return: MaybeNull] - private static string PathWhichWindows([NotNull] string name) + private static string? PathWhichWindows(string name) { string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? Array.Empty<string>(); - string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); + string[]? pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); char[] invalidPathChars = Path.GetInvalidPathChars(); var searchDirs = new List<string>(); @@ -196,10 +194,9 @@ namespace GodotTools.Utils select path + ext).FirstOrDefault(File.Exists); } - [return: MaybeNull] - private static string PathWhichUnix([NotNull] string name) + private static string? PathWhichUnix(string name) { - string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); + string[]? pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); char[] invalidPathChars = Path.GetInvalidPathChars(); var searchDirs = new List<string>(); @@ -238,7 +235,7 @@ namespace GodotTools.Utils foreach (string arg in arguments) startInfo.ArgumentList.Add(arg); - using Process process = Process.Start(startInfo); + using Process? process = Process.Start(startInfo); if (process == null) throw new InvalidOperationException("No process was started."); @@ -315,7 +312,7 @@ namespace GodotTools.Utils public static StringBuilder GetCommandLineDisplay( this ProcessStartInfo startInfo, - StringBuilder optionalBuilder = null + StringBuilder? optionalBuilder = null ) { var builder = optionalBuilder ?? new StringBuilder(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index e89bbbd370..9de6aafc8a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -106,7 +106,7 @@ namespace Godot instance = instance.Substring(1); } - if (instance.StartsWith("0b")) + if (instance.StartsWith("0b", StringComparison.OrdinalIgnoreCase)) { instance = instance.Substring(2); } @@ -816,7 +816,7 @@ namespace Godot instance = instance.Substring(1); } - if (instance.StartsWith("0x")) + if (instance.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { instance = instance.Substring(2); } diff --git a/modules/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp index fecefc7e71..264a2e9c8e 100644 --- a/modules/multiplayer/multiplayer_spawner.cpp +++ b/modules/multiplayer/multiplayer_spawner.cpp @@ -87,8 +87,8 @@ void MultiplayerSpawner::_get_property_list(List<PropertyInfo> *p_list) const { } #endif -Array MultiplayerSpawner::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray MultiplayerSpawner::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (spawn_path.is_empty() || !has_node(spawn_path)) { warnings.push_back(RTR("A valid NodePath must be set in the \"Spawn Path\" property in order for MultiplayerSpawner to be able to spawn Nodes.")); diff --git a/modules/multiplayer/multiplayer_spawner.h b/modules/multiplayer/multiplayer_spawner.h index 6cd2946df7..0e94b781ea 100644 --- a/modules/multiplayer/multiplayer_spawner.h +++ b/modules/multiplayer/multiplayer_spawner.h @@ -91,7 +91,7 @@ protected: void _get_property_list(List<PropertyInfo> *p_list) const; #endif public: - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; Node *get_spawn_node() const { return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr; diff --git a/modules/multiplayer/multiplayer_synchronizer.cpp b/modules/multiplayer/multiplayer_synchronizer.cpp index 16df9da78e..02e3a11964 100644 --- a/modules/multiplayer/multiplayer_synchronizer.cpp +++ b/modules/multiplayer/multiplayer_synchronizer.cpp @@ -143,8 +143,8 @@ bool MultiplayerSynchronizer::update_inbound_sync_time(uint16_t p_network_time) return true; } -Array MultiplayerSynchronizer::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray MultiplayerSynchronizer::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (root_path.is_empty() || !has_node(root_path)) { warnings.push_back(RTR("A valid NodePath must be set in the \"Root Path\" property in order for MultiplayerSynchronizer to be able to synchronize properties.")); diff --git a/modules/multiplayer/multiplayer_synchronizer.h b/modules/multiplayer/multiplayer_synchronizer.h index f5f3993f0d..192d7a5920 100644 --- a/modules/multiplayer/multiplayer_synchronizer.h +++ b/modules/multiplayer/multiplayer_synchronizer.h @@ -91,7 +91,7 @@ public: bool update_outbound_sync_time(uint64_t p_usec); bool update_inbound_sync_time(uint16_t p_network_time); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_replication_interval(double p_interval); double get_replication_interval() const; diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index d319c8ae4e..699d09c0d3 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -569,8 +569,8 @@ StringName AnimatedSprite2D::get_animation() const { return animation; } -Array AnimatedSprite2D::get_configuration_warnings() const { - Array warnings = Node2D::get_configuration_warnings(); +PackedStringArray AnimatedSprite2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (frames.is_null()) { warnings.push_back(RTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite2D to display frames.")); } diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h index 1f70f1af81..ac53bd26ee 100644 --- a/scene/2d/animated_sprite_2d.h +++ b/scene/2d/animated_sprite_2d.h @@ -125,7 +125,7 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; AnimatedSprite2D(); diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp index f87880afd7..2c5c6a1a16 100644 --- a/scene/2d/canvas_modulate.cpp +++ b/scene/2d/canvas_modulate.cpp @@ -113,8 +113,8 @@ Color CanvasModulate::get_color() const { return color; } -Array CanvasModulate::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray CanvasModulate::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_in_canvas && is_visible_in_tree()) { List<Node *> nodes; diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h index 05b126e889..08ded52e23 100644 --- a/scene/2d/canvas_modulate.h +++ b/scene/2d/canvas_modulate.h @@ -54,7 +54,7 @@ public: void set_color(const Color &p_color); Color get_color() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; CanvasModulate(); ~CanvasModulate(); diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index e36eda573c..4e5852984b 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -582,8 +582,8 @@ void CollisionObject2D::_update_pickable() { } } -Array CollisionObject2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionObject2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (shapes.is_empty()) { warnings.push_back(RTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape2D or CollisionPolygon2D as a child to define its shape.")); diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index 25ae9af8d5..780793f289 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -166,7 +166,7 @@ public: void set_pickable(bool p_enabled); bool is_pickable() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; _FORCE_INLINE_ RID get_rid() const { return rid; } diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index cfbdf65776..d2f71eca9d 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -232,8 +232,8 @@ bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, doubl } #endif -Array CollisionPolygon2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionPolygon2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject2D>(get_parent())) { warnings.push_back(RTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape.")); diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index cbedc718d8..f1ee30babe 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -77,7 +77,7 @@ public: void set_polygon(const Vector<Point2> &p_polygon); Vector<Point2> get_polygon() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_disabled(bool p_disabled); bool is_disabled() const; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 2c6e675527..ee413c7bc2 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -173,8 +173,8 @@ bool CollisionShape2D::_edit_is_selected_on_click(const Point2 &p_point, double return shape->_edit_is_selected_on_click(p_point, p_tolerance); } -Array CollisionShape2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionShape2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); CollisionObject2D *col_object = Object::cast_to<CollisionObject2D>(get_parent()); if (col_object == nullptr) { diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index 18f16269c0..3e13dd698c 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -80,7 +80,7 @@ public: void set_debug_color(const Color &p_color); Color get_debug_color() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; CollisionShape2D(); }; diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index c06b172b38..e04e6d7dce 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -246,8 +246,8 @@ bool CPUParticles2D::get_fractional_delta() const { return fractional_delta; } -Array CPUParticles2D::get_configuration_warnings() const { - Array warnings = Node2D::get_configuration_warnings(); +PackedStringArray CPUParticles2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(get_material().ptr()); diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 7108764bbe..3f858c3277 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -282,7 +282,7 @@ public: void set_gravity(const Vector2 &p_gravity); Vector2 get_gravity() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void restart(); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index d34e339448..bc39513c03 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -327,8 +327,8 @@ float GPUParticles2D::get_interp_to_end() const { return interp_to_end_factor; } -Array GPUParticles2D::get_configuration_warnings() const { - Array warnings = Node2D::get_configuration_warnings(); +PackedStringArray GPUParticles2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (process_material.is_null()) { warnings.push_back(RTR("A material to process the particles is not assigned, so no behavior is imprinted.")); diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index ba10e54251..58996b0327 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -161,7 +161,7 @@ public: void set_amount_ratio(float p_ratio); float get_amount_ratio() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_sub_emitter(const NodePath &p_path); NodePath get_sub_emitter() const; diff --git a/scene/2d/joint_2d.cpp b/scene/2d/joint_2d.cpp index dd9a721240..41b121a482 100644 --- a/scene/2d/joint_2d.cpp +++ b/scene/2d/joint_2d.cpp @@ -212,8 +212,8 @@ bool Joint2D::get_exclude_nodes_from_collision() const { return exclude_from_collision; } -Array Joint2D::get_configuration_warnings() const { - Array warnings = Node2D::get_configuration_warnings(); +PackedStringArray Joint2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (!warning.is_empty()) { warnings.push_back(warning); diff --git a/scene/2d/joint_2d.h b/scene/2d/joint_2d.h index 6a3777d3f1..5ff75a77a1 100644 --- a/scene/2d/joint_2d.h +++ b/scene/2d/joint_2d.h @@ -62,7 +62,7 @@ protected: _FORCE_INLINE_ bool is_configured() const { return configured; } public: - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; void set_node_a(const NodePath &p_node_a); NodePath get_node_a() const; diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index a8aecd8257..c03786caef 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -401,14 +401,11 @@ Vector2 PointLight2D::get_texture_offset() const { return texture_offset; } -Array PointLight2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray PointLight2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!texture.is_valid()) { - Dictionary texture_warning; - texture_warning["message"] = RTR("A texture with the shape of the light must be supplied."); - texture_warning["property"] = "texture"; - warnings.push_back(texture_warning); + warnings.push_back(RTR("A texture with the shape of the light must be supplied to the \"Texture\" property.")); } return warnings; diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 79b49b4c69..3c1171deae 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -174,7 +174,7 @@ public: void set_texture_scale(real_t p_scale); real_t get_texture_scale() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; PointLight2D(); }; diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index f5da96d4f9..61f5d5cd46 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -247,8 +247,8 @@ int LightOccluder2D::get_occluder_light_mask() const { return mask; } -Array LightOccluder2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray LightOccluder2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!occluder_polygon.is_valid()) { warnings.push_back(RTR("An occluder polygon must be set (or drawn) for this occluder to take effect.")); diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h index b8add2e498..dd3130394e 100644 --- a/scene/2d/light_occluder_2d.h +++ b/scene/2d/light_occluder_2d.h @@ -105,7 +105,7 @@ public: void set_as_sdf_collision(bool p_enable); bool is_set_as_sdf_collision() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; LightOccluder2D(); ~LightOccluder2D(); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 3b222e27c4..fee774fe2e 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -624,8 +624,8 @@ void NavigationAgent2D::_avoidance_done(Vector3 p_new_velocity) { emit_signal(SNAME("velocity_computed"), safe_velocity); } -Array NavigationAgent2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray NavigationAgent2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<Node2D>(get_parent())) { warnings.push_back(RTR("The NavigationAgent2D can be used only under a Node2D inheriting parent node.")); diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 7a8d008e90..0e46086a81 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -200,7 +200,7 @@ public: void _avoidance_done(Vector3 p_new_velocity); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_avoidance_layers(uint32_t p_layers); uint32_t get_avoidance_layers() const; diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp index be224eb08b..04ba550888 100644 --- a/scene/2d/navigation_link_2d.cpp +++ b/scene/2d/navigation_link_2d.cpp @@ -337,8 +337,8 @@ void NavigationLink2D::set_travel_cost(real_t p_travel_cost) { NavigationServer2D::get_singleton()->link_set_travel_cost(link, travel_cost); } -Array NavigationLink2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray NavigationLink2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (start_position.is_equal_approx(end_position)) { warnings.push_back(RTR("NavigationLink2D start position should be different than the end position to be useful.")); diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h index 7d8b375b6c..2929691c04 100644 --- a/scene/2d/navigation_link_2d.h +++ b/scene/2d/navigation_link_2d.h @@ -93,7 +93,7 @@ public: void set_travel_cost(real_t p_travel_cost); real_t get_travel_cost() const { return travel_cost; } - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; NavigationLink2D(); ~NavigationLink2D(); diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 134ca065ce..4a434fa3f8 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -283,8 +283,8 @@ void NavigationRegion2D::_navigation_debug_changed() { } #endif // DEBUG_ENABLED -Array NavigationRegion2D::get_configuration_warnings() const { - Array warnings = Node2D::get_configuration_warnings(); +PackedStringArray NavigationRegion2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (is_visible_in_tree() && is_inside_tree()) { if (!navigation_polygon.is_valid()) { diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 9e9a21d9f3..e9387376cb 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -114,7 +114,7 @@ public: void set_avoidance_layer_value(int p_layer_number, bool p_value); bool get_avoidance_layer_value(int p_layer_number) const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void bake_navigation_polygon(bool p_on_thread); void _bake_finished(Ref<NavigationPolygon> p_navigation_polygon); diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index 44cfc1deb2..3dd0d7b61c 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -137,8 +137,8 @@ void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_s _update_mirroring(); } -Array ParallaxLayer::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray ParallaxLayer::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<ParallaxBackground>(get_parent())) { warnings.push_back(RTR("ParallaxLayer node only works when set as child of a ParallaxBackground node.")); diff --git a/scene/2d/parallax_layer.h b/scene/2d/parallax_layer.h index dbf9386198..22fa0dd51c 100644 --- a/scene/2d/parallax_layer.h +++ b/scene/2d/parallax_layer.h @@ -59,7 +59,7 @@ public: void set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; ParallaxLayer(); }; diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 4fce49dc57..282d14da5d 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -287,8 +287,8 @@ void PathFollow2D::_validate_property(PropertyInfo &p_property) const { } } -Array PathFollow2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray PathFollow2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_visible_in_tree() && is_inside_tree()) { if (!Object::cast_to<Path2D>(get_parent())) { diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 616903c788..bfd5cde5e9 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -106,7 +106,7 @@ public: void set_cubic_interpolation_enabled(bool p_enabled); bool is_cubic_interpolation_enabled() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; PathFollow2D() {} }; diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physical_bone_2d.cpp index 12a3e6da21..64cf56fa85 100644 --- a/scene/2d/physical_bone_2d.cpp +++ b/scene/2d/physical_bone_2d.cpp @@ -106,8 +106,8 @@ void PhysicalBone2D::_find_joint_child() { } } -Array PhysicalBone2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray PhysicalBone2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!parent_skeleton) { warnings.push_back(RTR("A PhysicalBone2D only works with a Skeleton2D or another PhysicalBone2D as a parent node!")); diff --git a/scene/2d/physical_bone_2d.h b/scene/2d/physical_bone_2d.h index 1930ce1aba..e585f2c0ed 100644 --- a/scene/2d/physical_bone_2d.h +++ b/scene/2d/physical_bone_2d.h @@ -79,7 +79,7 @@ public: void set_follow_bone_when_simulating(bool p_follow); bool get_follow_bone_when_simulating() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; PhysicalBone2D(); ~PhysicalBone2D(); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 2e0b020232..92af3fa3f0 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -928,10 +928,10 @@ void RigidBody2D::_notification(int p_what) { #endif } -Array RigidBody2D::get_configuration_warnings() const { +PackedStringArray RigidBody2D::get_configuration_warnings() const { Transform2D t = get_transform(); - Array warnings = CollisionObject2D::get_configuration_warnings(); + PackedStringArray warnings = CollisionObject2D::get_configuration_warnings(); if (ABS(t.columns[0].length() - 1.0) > 0.05 || ABS(t.columns[1].length() - 1.0) > 0.05) { warnings.push_back(RTR("Size changes to RigidBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 44ff1ba822..88161e284a 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -313,7 +313,7 @@ public: TypedArray<Node2D> get_colliding_bodies() const; //function for script - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; RigidBody2D(); ~RigidBody2D(); diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp index b3926a4638..5ea5098475 100644 --- a/scene/2d/remote_transform_2d.cpp +++ b/scene/2d/remote_transform_2d.cpp @@ -200,8 +200,8 @@ void RemoteTransform2D::force_update_cache() { _update_cache(); } -Array RemoteTransform2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray RemoteTransform2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!has_node(remote_node) || !Object::cast_to<Node2D>(get_node(remote_node))) { warnings.push_back(RTR("Path property must point to a valid Node2D node to work.")); diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h index fe7289380a..997fd8fc69 100644 --- a/scene/2d/remote_transform_2d.h +++ b/scene/2d/remote_transform_2d.h @@ -70,7 +70,7 @@ public: void force_update_cache(); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; RemoteTransform2D(); }; diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/shape_cast_2d.cpp index 332e5eeb3e..90d80d7549 100644 --- a/scene/2d/shape_cast_2d.cpp +++ b/scene/2d/shape_cast_2d.cpp @@ -402,8 +402,8 @@ Array ShapeCast2D::_get_collision_result() const { return ret; } -Array ShapeCast2D::get_configuration_warnings() const { - Array warnings = Node2D::get_configuration_warnings(); +PackedStringArray ShapeCast2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (shape.is_null()) { warnings.push_back(RTR("This node cannot interact with other objects unless a Shape2D is assigned.")); diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/shape_cast_2d.h index da7c58bacc..a577c351fd 100644 --- a/scene/2d/shape_cast_2d.h +++ b/scene/2d/shape_cast_2d.h @@ -118,7 +118,7 @@ public: void remove_exception(const CollisionObject2D *p_node); void clear_exceptions(); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; ShapeCast2D(); }; diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 432b8e914e..69e0414855 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -415,8 +415,8 @@ int Bone2D::get_index_in_skeleton() const { return skeleton_index; } -Array Bone2D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray Bone2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!skeleton) { if (parent_bone) { warnings.push_back(RTR("This Bone2D chain should end at a Skeleton2D node.")); diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h index 1128ebb7c6..6a36a31552 100644 --- a/scene/2d/skeleton_2d.h +++ b/scene/2d/skeleton_2d.h @@ -78,7 +78,7 @@ public: void apply_rest(); Transform2D get_skeleton_rest() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_autocalculate_length_and_angle(bool p_autocalculate); bool get_autocalculate_length_and_angle() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index b8ca480e3b..48fe2afccc 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -846,8 +846,8 @@ TypedArray<Vector2i> TileMap::get_surrounding_cells(const Vector2i &p_coords) { return tile_set->get_surrounding_cells(p_coords); } -Array TileMap::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray TileMap::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); // Retrieve the set of Z index values with a Y-sorted layer. RBSet<int> y_sorted_z_index; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 6edf348caf..16750625e5 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -216,7 +216,7 @@ public: GDVIRTUAL3(_tile_data_runtime_update, int, Vector2i, TileData *); // Configuration warnings. - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; TileMap(); ~TileMap(); diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp index 3cab128be5..5683fb7306 100644 --- a/scene/3d/bone_attachment_3d.cpp +++ b/scene/3d/bone_attachment_3d.cpp @@ -87,8 +87,8 @@ void BoneAttachment3D::_get_property_list(List<PropertyInfo> *p_list) const { } } -Array BoneAttachment3D::get_configuration_warnings() const { - Array warnings = Node3D::get_configuration_warnings(); +PackedStringArray BoneAttachment3D::get_configuration_warnings() const { + PackedStringArray warnings = Node3D::get_configuration_warnings(); if (use_external_skeleton) { if (external_skeleton_node_cache.is_null()) { diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h index 13fdccab3c..1bf44c2756 100644 --- a/scene/3d/bone_attachment_3d.h +++ b/scene/3d/bone_attachment_3d.h @@ -71,8 +71,7 @@ public: virtual void notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map); #endif // TOOLS_ENABLED -public: - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; void set_bone_name(const String &p_name); String get_bone_name() const; diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 32799cacfe..0cfe0f8cb7 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -728,8 +728,8 @@ bool CollisionObject3D::get_capture_input_on_drag() const { return capture_input_on_drag; } -Array CollisionObject3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionObject3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (shapes.is_empty()) { warnings.push_back(RTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape3D or CollisionPolygon3D as a child to define its shape.")); diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index dc3c9269e4..b51423f021 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -173,7 +173,7 @@ public: _FORCE_INLINE_ RID get_rid() const { return rid; } - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; CollisionObject3D(); ~CollisionObject3D(); diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp index 29cec43011..9c1a7181aa 100644 --- a/scene/3d/collision_polygon_3d.cpp +++ b/scene/3d/collision_polygon_3d.cpp @@ -168,8 +168,8 @@ void CollisionPolygon3D::set_margin(real_t p_margin) { } } -Array CollisionPolygon3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionPolygon3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject3D>(get_parent())) { warnings.push_back(RTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node.\nPlease only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape.")); diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/collision_polygon_3d.h index 715ea721cf..61290a7947 100644 --- a/scene/3d/collision_polygon_3d.h +++ b/scene/3d/collision_polygon_3d.h @@ -74,7 +74,7 @@ public: real_t get_margin() const; void set_margin(real_t p_margin); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; CollisionPolygon3D(); }; diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 30692660f6..61941a0e53 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -118,8 +118,8 @@ void CollisionShape3D::resource_changed(Ref<Resource> res) { } #endif -Array CollisionShape3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionShape3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); CollisionObject3D *col_object = Object::cast_to<CollisionObject3D>(get_parent()); if (col_object == nullptr) { diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h index f66f88648e..bc0e70f8ac 100644 --- a/scene/3d/collision_shape_3d.h +++ b/scene/3d/collision_shape_3d.h @@ -64,7 +64,7 @@ public: void set_disabled(bool p_disabled); bool is_disabled() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; CollisionShape3D(); ~CollisionShape3D(); diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 32d68f7f78..d47e63d790 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -203,8 +203,8 @@ bool CPUParticles3D::get_fractional_delta() const { return fractional_delta; } -Array CPUParticles3D::get_configuration_warnings() const { - Array warnings = GeometryInstance3D::get_configuration_warnings(); +PackedStringArray CPUParticles3D::get_configuration_warnings() const { + PackedStringArray warnings = GeometryInstance3D::get_configuration_warnings(); bool mesh_found = false; bool anim_material_found = false; diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h index e9b75d9140..82ea4bbef3 100644 --- a/scene/3d/cpu_particles_3d.h +++ b/scene/3d/cpu_particles_3d.h @@ -305,7 +305,7 @@ public: void set_gravity(const Vector3 &p_gravity); Vector3 get_gravity() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void restart(); diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp index acd52da8b0..6878df21d8 100644 --- a/scene/3d/decal.cpp +++ b/scene/3d/decal.cpp @@ -162,8 +162,8 @@ void Decal::_validate_property(PropertyInfo &p_property) const { } } -Array Decal::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray Decal::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { warnings.push_back(RTR("Decals are only available when using the Forward+ or Mobile rendering backends.")); diff --git a/scene/3d/decal.h b/scene/3d/decal.h index 3bc6664afd..171b52815a 100644 --- a/scene/3d/decal.h +++ b/scene/3d/decal.h @@ -69,7 +69,7 @@ protected: #endif // DISABLE_DEPRECATED public: - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; void set_size(const Vector3 &p_size); Vector3 get_size() const; diff --git a/scene/3d/fog_volume.cpp b/scene/3d/fog_volume.cpp index 1c17a733e9..12ca1888c4 100644 --- a/scene/3d/fog_volume.cpp +++ b/scene/3d/fog_volume.cpp @@ -117,8 +117,8 @@ AABB FogVolume::get_aabb() const { return AABB(); } -Array FogVolume::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray FogVolume::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); Ref<Environment> environment = get_viewport()->find_world_3d()->get_environment(); diff --git a/scene/3d/fog_volume.h b/scene/3d/fog_volume.h index a185cdbd94..f7e861e3d0 100644 --- a/scene/3d/fog_volume.h +++ b/scene/3d/fog_volume.h @@ -66,7 +66,7 @@ public: Ref<Material> get_material() const; virtual AABB get_aabb() const override; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; FogVolume(); ~FogVolume(); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index 6670c2c5f6..16813b9017 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -296,8 +296,8 @@ bool GPUParticles3D::get_interpolate() const { return interpolate; } -Array GPUParticles3D::get_configuration_warnings() const { - Array warnings = GeometryInstance3D::get_configuration_warnings(); +PackedStringArray GPUParticles3D::get_configuration_warnings() const { + PackedStringArray warnings = GeometryInstance3D::get_configuration_warnings(); bool meshes_found = false; bool anim_material_found = false; diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h index 1697749d9b..0c9f2c1378 100644 --- a/scene/3d/gpu_particles_3d.h +++ b/scene/3d/gpu_particles_3d.h @@ -164,7 +164,7 @@ public: void set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh); Ref<Mesh> get_draw_pass_mesh(int p_pass) const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_sub_emitter(const NodePath &p_path); NodePath get_sub_emitter() const; diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp index f5d5795a27..cbc75801b0 100644 --- a/scene/3d/gpu_particles_collision_3d.cpp +++ b/scene/3d/gpu_particles_collision_3d.cpp @@ -527,8 +527,8 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() { return ret; } -Array GPUParticlesCollisionSDF3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray GPUParticlesCollisionSDF3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (bake_mask == 0) { warnings.push_back(RTR("The Bake Mask has no bits enabled, which means baking will not produce any collision for this GPUParticlesCollisionSDF3D.\nTo resolve this, enable at least one bit in the Bake Mask property.")); diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h index a4d8b15f9f..1649320069 100644 --- a/scene/3d/gpu_particles_collision_3d.h +++ b/scene/3d/gpu_particles_collision_3d.h @@ -170,7 +170,7 @@ protected: #endif // DISABLE_DEPRECATED public: - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; void set_thickness(float p_thickness); float get_thickness() const; diff --git a/scene/3d/joint_3d.cpp b/scene/3d/joint_3d.cpp index d76838d434..1e4e50182c 100644 --- a/scene/3d/joint_3d.cpp +++ b/scene/3d/joint_3d.cpp @@ -198,8 +198,8 @@ bool Joint3D::get_exclude_nodes_from_collision() const { return exclude_from_collision; } -Array Joint3D::get_configuration_warnings() const { - Array warnings = Node3D::get_configuration_warnings(); +PackedStringArray Joint3D::get_configuration_warnings() const { + PackedStringArray warnings = Node3D::get_configuration_warnings(); if (!warning.is_empty()) { warnings.push_back(warning); diff --git a/scene/3d/joint_3d.h b/scene/3d/joint_3d.h index bf2519db12..527aed4079 100644 --- a/scene/3d/joint_3d.h +++ b/scene/3d/joint_3d.h @@ -63,7 +63,7 @@ protected: _FORCE_INLINE_ bool is_configured() const { return configured; } public: - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; void set_node_a(const NodePath &p_node_a); NodePath get_node_a() const; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index bc74ff2c0f..7b70986adc 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -169,8 +169,8 @@ AABB Light3D::get_aabb() const { return AABB(); } -Array Light3D::get_configuration_warnings() const { - Array warnings = VisualInstance3D::get_configuration_warnings(); +PackedStringArray Light3D::get_configuration_warnings() const { + PackedStringArray warnings = VisualInstance3D::get_configuration_warnings(); if (!get_scale().is_equal_approx(Vector3(1, 1, 1))) { warnings.push_back(RTR("A light's scale does not affect the visual size of the light.")); @@ -596,8 +596,8 @@ OmniLight3D::ShadowMode OmniLight3D::get_shadow_mode() const { return shadow_mode; } -Array OmniLight3D::get_configuration_warnings() const { - Array warnings = Light3D::get_configuration_warnings(); +PackedStringArray OmniLight3D::get_configuration_warnings() const { + PackedStringArray warnings = Light3D::get_configuration_warnings(); if (!has_shadow() && get_projector().is_valid()) { warnings.push_back(RTR("Projector texture only works with shadows active.")); @@ -628,8 +628,8 @@ OmniLight3D::OmniLight3D() : set_shadow_mode(SHADOW_CUBE); } -Array SpotLight3D::get_configuration_warnings() const { - Array warnings = Light3D::get_configuration_warnings(); +PackedStringArray SpotLight3D::get_configuration_warnings() const { + PackedStringArray warnings = Light3D::get_configuration_warnings(); if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) { warnings.push_back(RTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows.")); diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index b242493c28..d6eca8d8b6 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -147,7 +147,7 @@ public: Color get_correlated_color() const; virtual AABB get_aabb() const override; - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; Light3D(); ~Light3D(); @@ -217,7 +217,7 @@ public: void set_shadow_mode(ShadowMode p_mode); ShadowMode get_shadow_mode() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; OmniLight3D(); }; @@ -231,7 +231,7 @@ protected: static void _bind_methods(); public: - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; SpotLight3D(); }; diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 008a09f141..86ff6d15dd 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -1528,8 +1528,8 @@ Ref<CameraAttributes> LightmapGI::get_camera_attributes() const { return camera_attributes; } -Array LightmapGI::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray LightmapGI::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { warnings.push_back(RTR("Lightmap can only be baked from a device that supports the RD backends. Lightmap baking may fail.")); diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h index 8d96c1e909..765e4a731d 100644 --- a/scene/3d/lightmap_gi.h +++ b/scene/3d/lightmap_gi.h @@ -302,7 +302,7 @@ public: BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr); - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; LightmapGI(); }; diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index ff0869b4ea..eb52d4540e 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -690,8 +690,8 @@ void NavigationAgent3D::_avoidance_done(Vector3 p_new_velocity) { emit_signal(SNAME("velocity_computed"), safe_velocity); } -Array NavigationAgent3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray NavigationAgent3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<Node3D>(get_parent())) { warnings.push_back(RTR("The NavigationAgent3D can be used only under a Node3D inheriting parent node.")); diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index 5f7b249b7f..4eaed83149 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -221,7 +221,7 @@ public: void _avoidance_done(Vector3 p_new_velocity); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_avoidance_layers(uint32_t p_layers); uint32_t get_avoidance_layers() const; diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp index c535393273..dc776ebea2 100644 --- a/scene/3d/navigation_link_3d.cpp +++ b/scene/3d/navigation_link_3d.cpp @@ -458,8 +458,8 @@ void NavigationLink3D::set_travel_cost(real_t p_travel_cost) { NavigationServer3D::get_singleton()->link_set_travel_cost(link, travel_cost); } -Array NavigationLink3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray NavigationLink3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (start_position.is_equal_approx(end_position)) { warnings.push_back(RTR("NavigationLink3D start position should be different than the end position to be useful.")); diff --git a/scene/3d/navigation_link_3d.h b/scene/3d/navigation_link_3d.h index 771d470711..1867082811 100644 --- a/scene/3d/navigation_link_3d.h +++ b/scene/3d/navigation_link_3d.h @@ -99,7 +99,7 @@ public: void set_travel_cost(real_t p_travel_cost); real_t get_travel_cost() const { return travel_cost; } - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; }; #endif // NAVIGATION_LINK_3D_H diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 5d258d394a..d8a63c60a2 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -270,8 +270,8 @@ bool NavigationRegion3D::is_baking() const { return NavigationServer3D::get_singleton()->is_baking_navigation_mesh(navigation_mesh); } -Array NavigationRegion3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray NavigationRegion3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_visible_in_tree() && is_inside_tree()) { if (!navigation_mesh.is_valid()) { diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h index b6dde0bec8..82468627de 100644 --- a/scene/3d/navigation_region_3d.h +++ b/scene/3d/navigation_region_3d.h @@ -108,7 +108,7 @@ public: void _bake_finished(Ref<NavigationMesh> p_navigation_mesh); bool is_baking() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; NavigationRegion3D(); ~NavigationRegion3D(); diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp index 0f56bfad52..a76488e479 100644 --- a/scene/3d/occluder_instance_3d.cpp +++ b/scene/3d/occluder_instance_3d.cpp @@ -693,8 +693,8 @@ OccluderInstance3D::BakeError OccluderInstance3D::bake_scene(Node *p_from_node, return BAKE_ERROR_OK; } -Array OccluderInstance3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray OccluderInstance3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!bool(GLOBAL_GET("rendering/occlusion_culling/use_occlusion_culling"))) { warnings.push_back(RTR("Occlusion culling is disabled in the Project Settings, which means occlusion culling won't be performed in the root viewport.\nTo resolve this, open the Project Settings and enable Rendering > Occlusion Culling > Use Occlusion Culling.")); diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h index cf20655c2c..f607877e8f 100644 --- a/scene/3d/occluder_instance_3d.h +++ b/scene/3d/occluder_instance_3d.h @@ -181,7 +181,7 @@ protected: static void _bind_methods(); public: - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; enum BakeError { BAKE_ERROR_OK, diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index 12e0123242..1f8f7cd54c 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -317,8 +317,8 @@ void PathFollow3D::_validate_property(PropertyInfo &p_property) const { } } -Array PathFollow3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray PathFollow3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_visible_in_tree() && is_inside_tree()) { if (!Object::cast_to<Path3D>(get_parent())) { diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h index 82fbf60bb6..0c9111bb8e 100644 --- a/scene/3d/path_3d.h +++ b/scene/3d/path_3d.h @@ -122,7 +122,7 @@ public: void set_cubic_interpolation_enabled(bool p_enabled); bool is_cubic_interpolation_enabled() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void update_transform(bool p_immediate = false); diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 2cbd484870..67a7f76d7d 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -995,8 +995,8 @@ TypedArray<Node3D> RigidBody3D::get_colliding_bodies() const { return ret; } -Array RigidBody3D::get_configuration_warnings() const { - Array warnings = CollisionObject3D::get_configuration_warnings(); +PackedStringArray RigidBody3D::get_configuration_warnings() const { + PackedStringArray warnings = CollisionObject3D::get_configuration_warnings(); Vector3 scale = get_transform().get_basis().get_scale(); if (ABS(scale.x - 1.0) > 0.05 || ABS(scale.y - 1.0) > 0.05 || ABS(scale.z - 1.0) > 0.05) { diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index b360954263..b84b7c4f02 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -329,7 +329,7 @@ public: void set_constant_torque(const Vector3 &p_torque); Vector3 get_constant_torque() const; - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; RigidBody3D(); ~RigidBody3D(); diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 89368a7309..b4dd6d09be 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -190,8 +190,8 @@ AABB ReflectionProbe::get_aabb() const { return aabb; } -Array ReflectionProbe::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray ReflectionProbe::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { warnings.push_back(RTR("ReflectionProbes are not supported when using the GL Compatibility backend yet. Support will be added in a future release.")); diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index 2561b2a922..425fbb5bc2 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -122,7 +122,7 @@ public: virtual AABB get_aabb() const override; - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; ReflectionProbe(); ~ReflectionProbe(); diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp index bb41015219..8d6e717132 100644 --- a/scene/3d/remote_transform_3d.cpp +++ b/scene/3d/remote_transform_3d.cpp @@ -200,8 +200,8 @@ void RemoteTransform3D::force_update_cache() { _update_cache(); } -Array RemoteTransform3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray RemoteTransform3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!has_node(remote_node) || !Object::cast_to<Node3D>(get_node(remote_node))) { warnings.push_back(RTR("The \"Remote Path\" property must point to a valid Node3D or Node3D-derived node to work.")); diff --git a/scene/3d/remote_transform_3d.h b/scene/3d/remote_transform_3d.h index 40b59a5a5e..3841821dae 100644 --- a/scene/3d/remote_transform_3d.h +++ b/scene/3d/remote_transform_3d.h @@ -70,7 +70,7 @@ public: void force_update_cache(); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; RemoteTransform3D(); }; diff --git a/scene/3d/shape_cast_3d.cpp b/scene/3d/shape_cast_3d.cpp index ba4ce834da..4d9eeada06 100644 --- a/scene/3d/shape_cast_3d.cpp +++ b/scene/3d/shape_cast_3d.cpp @@ -170,8 +170,8 @@ void ShapeCast3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_shape_custom_color"), "set_debug_shape_custom_color", "get_debug_shape_custom_color"); } -Array ShapeCast3D::get_configuration_warnings() const { - Array warnings = Node3D::get_configuration_warnings(); +PackedStringArray ShapeCast3D::get_configuration_warnings() const { + PackedStringArray warnings = Node3D::get_configuration_warnings(); if (shape.is_null()) { warnings.push_back(RTR("This node cannot interact with other objects unless a Shape3D is assigned.")); diff --git a/scene/3d/shape_cast_3d.h b/scene/3d/shape_cast_3d.h index d690a17a78..043e35090f 100644 --- a/scene/3d/shape_cast_3d.h +++ b/scene/3d/shape_cast_3d.h @@ -140,7 +140,7 @@ public: void remove_exception(const CollisionObject3D *p_node); void clear_exceptions(); - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; }; #endif // SHAPE_CAST_3D_H diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 540e70866a..bd03a97a36 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -376,8 +376,8 @@ void SoftBody3D::_bind_methods() { BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE); } -Array SoftBody3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray SoftBody3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (mesh.is_null()) { warnings.push_back(RTR("This body will be ignored until you set a mesh.")); diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index b5d31d8440..ab30f7e654 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -126,7 +126,7 @@ protected: void _notification(int p_what); static void _bind_methods(); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; public: RID get_physics_rid() const { return physics_rid; } diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 234baac61a..8e76e75d0e 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -1430,8 +1430,8 @@ StringName AnimatedSprite3D::get_animation() const { return animation; } -Array AnimatedSprite3D::get_configuration_warnings() const { - Array warnings = SpriteBase3D::get_configuration_warnings(); +PackedStringArray AnimatedSprite3D::get_configuration_warnings() const { + PackedStringArray warnings = SpriteBase3D::get_configuration_warnings(); if (frames.is_null()) { warnings.push_back(RTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames.")); } diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index c83ed88b2d..cbc7192ddf 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -285,7 +285,7 @@ public: virtual Rect2 get_item_rect() const override; - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; AnimatedSprite3D(); diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index b309205697..c23032d3b9 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -105,8 +105,8 @@ void VehicleWheel3D::_notification(int p_what) { } } -Array VehicleWheel3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray VehicleWheel3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<VehicleBody3D>(get_parent())) { warnings.push_back(RTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D.")); diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h index 8127340acc..ce913f152d 100644 --- a/scene/3d/vehicle_body_3d.h +++ b/scene/3d/vehicle_body_3d.h @@ -147,7 +147,7 @@ public: void set_steering(real_t p_steering); real_t get_steering() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; VehicleWheel3D(); }; diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp index c10ddec17e..be86872a59 100644 --- a/scene/3d/visible_on_screen_notifier_3d.cpp +++ b/scene/3d/visible_on_screen_notifier_3d.cpp @@ -79,8 +79,8 @@ void VisibleOnScreenNotifier3D::_notification(int p_what) { } } -Array VisibleOnScreenNotifier3D::get_configuration_warnings() const { - Array warnings = VisualInstance3D::get_configuration_warnings(); +PackedStringArray VisibleOnScreenNotifier3D::get_configuration_warnings() const { + PackedStringArray warnings = VisualInstance3D::get_configuration_warnings(); if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { warnings.push_back(RTR("VisibleOnScreenNotifier3D nodes are not supported when using the GL Compatibility backend yet. Support will be added in a future release.")); diff --git a/scene/3d/visible_on_screen_notifier_3d.h b/scene/3d/visible_on_screen_notifier_3d.h index 10e41ceec6..85156c256e 100644 --- a/scene/3d/visible_on_screen_notifier_3d.h +++ b/scene/3d/visible_on_screen_notifier_3d.h @@ -57,7 +57,7 @@ public: virtual AABB get_aabb() const override; bool is_on_screen() const; - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; VisibleOnScreenNotifier3D(); ~VisibleOnScreenNotifier3D(); diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 47a9a581b8..503c39ae3e 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -425,8 +425,8 @@ bool GeometryInstance3D::is_ignoring_occlusion_culling() { return ignore_occlusion_culling; } -Array GeometryInstance3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray GeometryInstance3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Math::is_zero_approx(visibility_range_end) && visibility_range_end <= visibility_range_begin) { warnings.push_back(RTR("The GeometryInstance3D visibility range's End distance is set to a non-zero value, but is lower than the Begin distance.\nThis means the GeometryInstance3D will never be visible.\nTo resolve this, set the End distance to 0 or to a value greater than the Begin distance.")); diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index c088e189ce..59ede26ac1 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -194,7 +194,7 @@ public: void set_ignore_occlusion_culling(bool p_enabled); bool is_ignoring_occlusion_culling(); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; GeometryInstance3D(); virtual ~GeometryInstance3D(); }; diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 011aecc724..eb8569fa30 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -518,8 +518,8 @@ AABB VoxelGI::get_aabb() const { return AABB(-size / 2, size); } -Array VoxelGI::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray VoxelGI::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { warnings.push_back(RTR("VoxelGI nodes are not supported when using the GL Compatibility backend yet. Support will be added in a future release.")); diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h index 316cb26b77..7d7787f721 100644 --- a/scene/3d/voxel_gi.h +++ b/scene/3d/voxel_gi.h @@ -163,7 +163,7 @@ public: virtual AABB get_aabb() const override; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; VoxelGI(); ~VoxelGI(); diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 8db310ce30..4687c84734 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -135,8 +135,8 @@ Ref<CameraAttributes> WorldEnvironment::get_camera_attributes() const { return camera_attributes; } -Array WorldEnvironment::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray WorldEnvironment::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!environment.is_valid() && !camera_attributes.is_valid()) { warnings.push_back(RTR("To have any visible effect, WorldEnvironment requires its \"Environment\" property to contain an Environment, its \"Camera Attributes\" property to contain a CameraAttributes resource, or both.")); diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index 57d95f1f0e..2809d2550a 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -55,7 +55,7 @@ public: void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes); Ref<CameraAttributes> get_camera_attributes() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; WorldEnvironment(); }; diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index 79db9d5560..70e32c1a31 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -76,8 +76,8 @@ void XRCamera3D::_pose_changed(const Ref<XRPose> &p_pose) { } } -Array XRCamera3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray XRCamera3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_visible() && is_inside_tree()) { // must be child node of XROrigin3D! @@ -424,8 +424,8 @@ XRNode3D::~XRNode3D() { xr_server->disconnect("tracker_removed", callable_mp(this, &XRNode3D::_removed_tracker)); } -Array XRNode3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray XRNode3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_visible() && is_inside_tree()) { // must be child node of XROrigin! @@ -603,8 +603,8 @@ Plane XRAnchor3D::get_plane() const { Vector<XROrigin3D *> XROrigin3D::origin_nodes; -Array XROrigin3D::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray XROrigin3D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_visible() && is_inside_tree()) { bool has_camera = false; diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h index 7f75e69fbc..ad52cf113d 100644 --- a/scene/3d/xr_nodes.h +++ b/scene/3d/xr_nodes.h @@ -55,7 +55,7 @@ protected: void _pose_changed(const Ref<XRPose> &p_pose); public: - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const override; virtual Point2 unproject_position(const Vector3 &p_pos) const override; @@ -109,7 +109,7 @@ public: Ref<XRPose> get_pose(); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; XRNode3D(); ~XRNode3D(); @@ -193,7 +193,7 @@ protected: static void _bind_methods(); public: - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; real_t get_world_scale() const; void set_world_scale(real_t p_world_scale); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 9694e855b5..844b6e64e8 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -606,8 +606,8 @@ uint64_t AnimationTree::get_last_process_pass() const { return process_pass; } -Array AnimationTree::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray AnimationTree::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!root_animation_node.is_valid()) { warnings.push_back(RTR("No root AnimationNode for the graph is set.")); } diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 7d153b2736..87928e4d20 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -261,7 +261,7 @@ public: void set_advance_expression_base_node(const NodePath &p_path); NodePath get_advance_expression_base_node() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; bool is_state_invalid() const; String get_invalid_state_reason() const; diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 49616f87cc..66b14dc967 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -430,8 +430,8 @@ bool BaseButton::_was_pressed_by_mouse() const { return was_mouse_pressed; } -Array BaseButton::get_configuration_warnings() const { - Array warnings = Control::get_configuration_warnings(); +PackedStringArray BaseButton::get_configuration_warnings() const { + PackedStringArray warnings = Control::get_configuration_warnings(); if (get_button_group().is_valid() && !is_toggle_mode()) { warnings.push_back(RTR("ButtonGroup is intended to be used only with buttons that have toggle_mode set to true.")); diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index b5fbf11c8d..a8d5cee44c 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -139,7 +139,7 @@ public: void set_button_group(const Ref<ButtonGroup> &p_group); Ref<ButtonGroup> get_button_group() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; BaseButton(); ~BaseButton(); diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 594ae3eee8..c6e66c95c6 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -189,8 +189,8 @@ void Container::_notification(int p_what) { } } -Array Container::get_configuration_warnings() const { - Array warnings = Control::get_configuration_warnings(); +PackedStringArray Container::get_configuration_warnings() const { + PackedStringArray warnings = Control::get_configuration_warnings(); if (get_class() == "Container" && get_script().is_null()) { warnings.push_back(RTR("Container by itself serves no purpose unless a script configures its children placement behavior.\nIf you don't intend to add a script, use a plain Control node instead.")); diff --git a/scene/gui/container.h b/scene/gui/container.h index d04a71fe23..94c3c540d7 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -63,7 +63,7 @@ public: virtual Vector<int> get_allowed_size_flags_horizontal() const; virtual Vector<int> get_allowed_size_flags_vertical() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; Container(); }; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 2124ffb806..b351d1ee4f 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -228,9 +228,9 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List } } -Array Control::get_configuration_warnings() const { - ERR_READ_THREAD_GUARD_V(Array()); - Array warnings = Node::get_configuration_warnings(); +PackedStringArray Control::get_configuration_warnings() const { + ERR_READ_THREAD_GUARD_V(PackedStringArray()); + PackedStringArray warnings = Node::get_configuration_warnings(); if (data.mouse_filter == MOUSE_FILTER_IGNORE && !data.tooltip.is_empty()) { warnings.push_back(RTR("The Hint Tooltip won't be displayed as the control's Mouse Filter is set to \"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\".")); diff --git a/scene/gui/control.h b/scene/gui/control.h index 8bcd955457..a900a593dd 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -407,7 +407,7 @@ public: static void set_root_layout_direction(int p_root_dir); virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; virtual bool is_text_field() const; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 7ea3aa344a..c23d21775f 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -251,8 +251,8 @@ Control::CursorShape GraphEdit::get_cursor_shape(const Point2 &p_pos) const { return Control::get_cursor_shape(p_pos); } -Array GraphEdit::get_configuration_warnings() const { - Array warnings = Control::get_configuration_warnings(); +PackedStringArray GraphEdit::get_configuration_warnings() const { + PackedStringArray warnings = Control::get_configuration_warnings(); warnings.push_back(RTR("Please be aware that GraphEdit and GraphNode will undergo extensive refactoring in a future 4.x version involving compatibility-breaking API changes.")); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index dd99651d60..e24f039e84 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -375,7 +375,7 @@ public: virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; Error connect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); bool is_node_connected(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index f847971015..56da1332e7 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -330,8 +330,8 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col } } -Array Label::get_configuration_warnings() const { - Array warnings = Control::get_configuration_warnings(); +PackedStringArray Label::get_configuration_warnings() const { + PackedStringArray warnings = Control::get_configuration_warnings(); // FIXME: This is not ideal and the sizing model should be fixed, // but for now we have to warn about this impossible to resolve combination. diff --git a/scene/gui/label.h b/scene/gui/label.h index fe90bd06bb..4bd0e53605 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -97,7 +97,7 @@ protected: public: virtual Size2 get_minimum_size() const override; - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; void set_horizontal_alignment(HorizontalAlignment p_alignment); HorizontalAlignment get_horizontal_alignment() const; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 72a84e4884..37212a34ad 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -2279,8 +2279,8 @@ void LineEdit::_emit_text_change() { emit_signal(SNAME("text_changed"), text); text_changed_dirty = false; } -Array LineEdit::get_configuration_warnings() const { - Array warnings = Control::get_configuration_warnings(); +PackedStringArray LineEdit::get_configuration_warnings() const { + PackedStringArray warnings = Control::get_configuration_warnings(); if (secret_character.length() > 1) { warnings.push_back("Secret Character property supports only one character. Extra characters will be ignored."); } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index b2582e0eb5..993bc727e4 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -385,7 +385,7 @@ public: virtual bool is_text_field() const override; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void show_virtual_keyboard(); diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 8fc21c077b..6613f25b4c 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -336,6 +336,13 @@ void OptionButton::set_item_count(int p_count) { } } + if (!initialized) { + if (queued_current != current) { + current = queued_current; + } + initialized = true; + } + _refresh_size_cache(); notify_property_list_changed(); } @@ -432,7 +439,13 @@ void OptionButton::_select(int p_which, bool p_emit) { } void OptionButton::_select_int(int p_which) { - if (p_which < NONE_SELECTED || p_which >= popup->get_item_count()) { + if (p_which < NONE_SELECTED) { + return; + } + if (p_which >= popup->get_item_count()) { + if (!initialized) { + queued_current = p_which; + } return; } _select(p_which, false); @@ -571,11 +584,10 @@ void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_allow_reselect"), &OptionButton::get_allow_reselect); ClassDB::bind_method(D_METHOD("set_disable_shortcuts", "disabled"), &OptionButton::set_disable_shortcuts); - // "selected" property must come after "item_count", otherwise GH-10213 occurs. - ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fit_to_longest_item"), "set_fit_to_longest_item", "is_fit_to_longest_item"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_reselect"), "set_allow_reselect", "get_allow_reselect"); + ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_"); ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index"))); ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "index"))); diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index eef498333b..9c15b295a9 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -44,6 +44,8 @@ class OptionButton : public Button { Vector2 _cached_size; bool cache_refresh_pending = false; bool allow_reselect = false; + bool initialized = false; + int queued_current = -1; struct ThemeCache { Ref<StyleBox> normal; diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index da40c7f3e2..236dfcc864 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -30,8 +30,8 @@ #include "range.h" -Array Range::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray Range::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (shared->exp_ratio && shared->min <= 0) { warnings.push_back(RTR("If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0.")); diff --git a/scene/gui/range.h b/scene/gui/range.h index e08a77f0f7..b1c2446ded 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -103,7 +103,7 @@ public: void share(Range *p_range); void unshare(); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; Range(); ~Range(); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index fd3a1f4a45..89d308de3f 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -537,8 +537,8 @@ void ScrollContainer::set_follow_focus(bool p_follow) { follow_focus = p_follow; } -Array ScrollContainer::get_configuration_warnings() const { - Array warnings = Container::get_configuration_warnings(); +PackedStringArray ScrollContainer::get_configuration_warnings() const { + PackedStringArray warnings = Container::get_configuration_warnings(); int found = 0; diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 69ff7ccc14..02146618cd 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -119,7 +119,7 @@ public: VScrollBar *get_v_scroll_bar(); void ensure_control_visible(Control *p_control); - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; ScrollContainer(); }; diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp index 4ed136005a..0d33774e20 100644 --- a/scene/gui/subviewport_container.cpp +++ b/scene/gui/subviewport_container.cpp @@ -259,8 +259,8 @@ void SubViewportContainer::remove_child_notify(Node *p_child) { } } -Array SubViewportContainer::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray SubViewportContainer::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); bool has_viewport = false; for (int i = 0; i < get_child_count(); i++) { diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h index e172f2f040..06420de730 100644 --- a/scene/gui/subviewport_container.h +++ b/scene/gui/subviewport_container.h @@ -68,7 +68,7 @@ public: virtual Vector<int> get_allowed_size_flags_horizontal() const override; virtual Vector<int> get_allowed_size_flags_vertical() const override; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; SubViewportContainer(); }; diff --git a/scene/main/missing_node.cpp b/scene/main/missing_node.cpp index 02e079892c..83672ae5e0 100644 --- a/scene/main/missing_node.cpp +++ b/scene/main/missing_node.cpp @@ -82,9 +82,9 @@ bool MissingNode::is_recording_properties() const { return recording_properties; } -Array MissingNode::get_configuration_warnings() const { +PackedStringArray MissingNode::get_configuration_warnings() const { // The mere existence of this node is warning. - Array ret; + PackedStringArray ret; if (!original_scene.is_empty()) { ret.push_back(vformat(RTR("This node was an instance of scene '%s', which was no longer available when this scene was loaded."), original_scene)); ret.push_back(vformat(RTR("Saving current scene will discard instance and all its properties, including editable children edits (if existing)."))); diff --git a/scene/main/missing_node.h b/scene/main/missing_node.h index ccaf1e471e..fb1c957988 100644 --- a/scene/main/missing_node.h +++ b/scene/main/missing_node.h @@ -59,7 +59,7 @@ public: void set_recording_properties(bool p_enable); bool is_recording_properties() const; - virtual Array get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; MissingNode(); }; diff --git a/scene/main/node.compat.inc b/scene/main/node.compat.inc deleted file mode 100644 index 7e957e5a14..0000000000 --- a/scene/main/node.compat.inc +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************/ -/* node.compat.inc */ -/**************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/**************************************************************************/ -/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/**************************************************************************/ - -#ifndef DISABLE_DEPRECATED - -PackedStringArray Node::get_configuration_warnings_bind_compat_68420() const { - return PackedStringArray(get_configuration_warnings()); -} - -void Node::_bind_compatibility_methods() { - ClassDB::bind_compatibility_method(D_METHOD("get_configuration_warnings"), &Node::get_configuration_warnings_bind_compat_68420); -} - -#endif // DISABLE_DEPRECATED diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 77e00e4ab4..853c684b13 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -3204,91 +3204,16 @@ void Node::clear_internal_tree_resource_paths() { } } -Array Node::get_configuration_warnings() const { - ERR_THREAD_GUARD_V(Array()); - Array warnings; - GDVIRTUAL_CALL(_get_configuration_warnings, warnings); - return warnings; -} - -Dictionary Node::configuration_warning_to_dict(const Variant &p_warning) const { - switch (p_warning.get_type()) { - case Variant::Type::DICTIONARY: - return p_warning; - case Variant::Type::STRING: { - // Convert string to dictionary. - Dictionary warning; - warning["message"] = p_warning; - return warning; - } - default: { - ERR_FAIL_V_MSG(Dictionary(), "Node::get_configuration_warnings returned a value which is neither a string nor a dictionary, but a " + Variant::get_type_name(p_warning.get_type())); - } - } -} - -Vector<Dictionary> Node::get_configuration_warnings_as_dicts() const { - Vector<Dictionary> ret; - Array mixed = get_configuration_warnings(); - for (int i = 0; i < mixed.size(); i++) { - ret.append(configuration_warning_to_dict(mixed[i])); - } - return ret; -} +PackedStringArray Node::get_configuration_warnings() const { + ERR_THREAD_GUARD_V(PackedStringArray()); + PackedStringArray ret; -Vector<Dictionary> Node::get_configuration_warnings_of_property(const String &p_property) const { - Vector<Dictionary> ret; - Vector<Dictionary> warnings = get_configuration_warnings_as_dicts(); - if (p_property.is_empty()) { + Vector<String> warnings; + if (GDVIRTUAL_CALL(_get_configuration_warnings, warnings)) { ret.append_array(warnings); - } else { - // Filter by property path. - for (int i = 0; i < warnings.size(); i++) { - Dictionary warning = warnings[i]; - String warning_property = warning.get("property", String()); - if (p_property == warning_property) { - ret.append(warning); - } - } } - return ret; -} - -PackedStringArray Node::get_configuration_warnings_as_strings(bool p_wrap_lines, const String &p_property) const { - Vector<Dictionary> warnings = get_configuration_warnings_of_property(p_property); - const String bullet_point = U"• "; - PackedStringArray all_warnings; - for (const Dictionary &warning : warnings) { - if (!warning.has("message")) { - continue; - } - - // Prefix with property name if we are showing all warnings. - String text; - if (warning.has("property") && p_property.is_empty()) { - text = bullet_point + vformat("[%s] %s", warning["property"], warning["message"]); - } else { - text = bullet_point + static_cast<String>(warning["message"]); - } - - if (p_wrap_lines) { - // Limit the line width while keeping some padding. - // It is not efficient, but it does not have to be. - const PackedInt32Array boundaries = TS->string_get_word_breaks(text, "", 80); - PackedStringArray lines; - for (int i = 0; i < boundaries.size(); i += 2) { - const int start = boundaries[i]; - const int end = boundaries[i + 1]; - String line = text.substr(start, end - start); - lines.append(line); - } - text = String("\n").join(lines); - } - text = text.replace("\n", "\n "); - all_warnings.append(text); - } - return all_warnings; + return ret; } void Node::update_configuration_warnings() { @@ -3774,16 +3699,6 @@ String Node::_get_name_num_separator() { return " "; } -StringName Node::get_configuration_warning_icon(int p_count) { - if (p_count == 1) { - return SNAME("NodeWarning"); - } else if (p_count <= 3) { - return vformat("NodeWarnings%d", p_count); - } else { - return SNAME("NodeWarnings4Plus"); - } -} - Node::Node() { orphan_node_count++; } diff --git a/scene/main/node.h b/scene/main/node.h index bbbdb87a32..b936cdd375 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -304,7 +304,6 @@ protected: static void _bind_methods(); static String _get_name_num_separator(); - static StringName get_configuration_warning_icon(int p_count); friend class SceneState; @@ -331,7 +330,7 @@ protected: GDVIRTUAL0(_enter_tree) GDVIRTUAL0(_exit_tree) GDVIRTUAL0(_ready) - GDVIRTUAL0RC(Array, _get_configuration_warnings) + GDVIRTUAL0RC(Vector<String>, _get_configuration_warnings) GDVIRTUAL1(_input, Ref<InputEvent>) GDVIRTUAL1(_shortcut_input, Ref<InputEvent>) @@ -648,11 +647,7 @@ public: _FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; } - virtual Array get_configuration_warnings() const; - Dictionary configuration_warning_to_dict(const Variant &p_warning) const; - Vector<Dictionary> get_configuration_warnings_as_dicts() const; - Vector<Dictionary> get_configuration_warnings_of_property(const String &p_property = String()) const; - PackedStringArray get_configuration_warnings_as_strings(bool p_wrap_lines, const String &p_property = String()) const; + virtual PackedStringArray get_configuration_warnings() const; void update_configuration_warnings(); diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp index b3d3659c5b..e3c26c30e2 100644 --- a/scene/main/shader_globals_override.cpp +++ b/scene/main/shader_globals_override.cpp @@ -271,8 +271,8 @@ void ShaderGlobalsOverride::_notification(int p_what) { } } -Array ShaderGlobalsOverride::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray ShaderGlobalsOverride::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!active) { warnings.push_back(RTR("ShaderGlobalsOverride is not active because another node of the same type is in the scene.")); diff --git a/scene/main/shader_globals_override.h b/scene/main/shader_globals_override.h index 72226c0cb3..d8557ecf6a 100644 --- a/scene/main/shader_globals_override.h +++ b/scene/main/shader_globals_override.h @@ -58,7 +58,7 @@ protected: static void _bind_methods(); public: - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; ShaderGlobalsOverride(); }; diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index acb788f76f..0f4f18b495 100644 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -180,8 +180,8 @@ void Timer::_set_process(bool p_process, bool p_force) { processing = p_process; } -Array Timer::get_configuration_warnings() const { - Array warnings = Node::get_configuration_warnings(); +PackedStringArray Timer::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (wait_time < 0.05 - CMP_EPSILON) { warnings.push_back(RTR("Very low timer wait times (< 0.05 seconds) may behave in significantly different ways depending on the rendered or physics frame rate.\nConsider using a script's process loop instead of relying on a Timer for very low wait times.")); diff --git a/scene/main/timer.h b/scene/main/timer.h index add61ef5f4..d16e49793d 100644 --- a/scene/main/timer.h +++ b/scene/main/timer.h @@ -73,7 +73,7 @@ public: double get_time_left() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_timer_process_callback(TimerProcessCallback p_callback); TimerProcessCallback get_timer_process_callback() const; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 5952af60ee..da72c8b737 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -3510,9 +3510,9 @@ Variant Viewport::gui_get_drag_data() const { return gui.drag_data; } -Array Viewport::get_configuration_warnings() const { - ERR_MAIN_THREAD_GUARD_V(Array()); - Array warnings = Node::get_configuration_warnings(); +PackedStringArray Viewport::get_configuration_warnings() const { + ERR_MAIN_THREAD_GUARD_V(PackedStringArray()); + PackedStringArray warnings = Node::get_configuration_warnings(); if (size.x <= 1 || size.y <= 1) { warnings.push_back(RTR("The Viewport size must be greater than or equal to 2 pixels on both dimensions to render anything.")); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 68f0e8b655..03db0d4023 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -614,7 +614,7 @@ public: Control *gui_get_focus_owner() const; Control *gui_get_hovered_control() const; - Array get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_debug_draw(DebugDraw p_debug_draw); DebugDraw get_debug_draw() const; diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 7f49805274..58117d6b68 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -30,8 +30,11 @@ #include "test_main.h" +#ifdef TOOLS_ENABLED #include "editor/editor_paths.h" #include "editor/editor_settings.h" +#endif // TOOLS_ENABLED + #include "tests/core/config/test_project_settings.h" #include "tests/core/input/test_input_event.h" #include "tests/core/input/test_input_event_key.h" @@ -270,11 +273,13 @@ struct GodotTestCaseListener : public doctest::IReporter { SceneTree::get_singleton()->get_root()->set_embedding_subwindows(true); } +#ifdef TOOLS_ENABLED if (name.find("[Editor]") != -1) { Engine::get_singleton()->set_editor_hint(true); EditorPaths::create(); EditorSettings::create(); } +#endif // TOOLS_ENABLED return; } @@ -298,9 +303,11 @@ struct GodotTestCaseListener : public doctest::IReporter { } void test_case_end(const doctest::CurrentTestCaseStats &) override { +#ifdef TOOLS_ENABLED if (EditorSettings::get_singleton()) { EditorSettings::destroy(); } +#endif // TOOLS_ENABLED Engine::get_singleton()->set_editor_hint(false); |