summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/csharp_script.h3
-rw-r--r--modules/mono/doc_classes/CSharpScript.xml2
-rw-r--r--modules/mono/doc_classes/GodotSharp.xml2
-rw-r--r--modules/mono/editor/bindings_generator.cpp440
-rw-r--r--modules/mono/editor/bindings_generator.h8
-rw-r--r--modules/mono/editor_templates/CharacterBody2D/basic_movement.cs12
-rw-r--r--modules/mono/editor_templates/CharacterBody3D/basic_movement.cs16
-rw-r--r--modules/mono/godotsharp_dirs.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp9
-rw-r--r--modules/mono/mono_gd/support/android_support.cpp89
-rw-r--r--modules/mono/mono_gd/support/ios_support.mm3
-rw-r--r--modules/mono/utils/mono_reg_utils.cpp38
-rw-r--r--modules/mono/utils/path_utils.cpp9
13 files changed, 371 insertions, 262 deletions
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 2de923c125..d6cd9e6e57 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -53,8 +53,9 @@ class CSharpLanguage;
#ifdef NO_SAFE_CAST
template <typename TScriptInstance, typename TScriptLanguage>
TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
- if (!p_inst)
+ if (!p_inst) {
return nullptr;
+ }
return p_inst->get_language() == TScriptLanguage::get_singleton() ? static_cast<TScriptInstance *>(p_inst) : nullptr;
}
#else
diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml
index 14c62b4bb0..f8293fb107 100644
--- a/modules/mono/doc_classes/CSharpScript.xml
+++ b/modules/mono/doc_classes/CSharpScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSharpScript" inherits="Script" version="4.0">
+<class name="CSharpScript" inherits="Script" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
A script implemented in the C# programming language (Mono-enabled builds only).
</brief_description>
diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml
index a148072245..9de6b48e9e 100644
--- a/modules/mono/doc_classes/GodotSharp.xml
+++ b/modules/mono/doc_classes/GodotSharp.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GodotSharp" inherits="Object" version="4.0">
+<class name="GodotSharp" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
Bridge between Godot and the Mono runtime (Mono-enabled builds only).
</brief_description>
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index f345dff333..272283432d 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -278,12 +278,12 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else if (code_tag) {
xml_output.append("[");
pos = brk_pos + 1;
- } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ")) {
+ } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ")) {
const int tag_end = tag.find(" ");
const String link_tag = tag.substr(0, tag_end);
const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" ");
- Vector<String> link_target_parts = link_target.split(".");
+ const Vector<String> link_target_parts = link_target.split(".");
if (link_target_parts.size() <= 0 || link_target_parts.size() > 2) {
ERR_PRINT("Invalid reference format: '" + tag + "'.");
@@ -311,201 +311,18 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
}
if (link_tag == "method") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve method reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from method reference in documentation: %s\n", link_target.utf8().get_data());
- }
- }
-
- // TODO Map what we can
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- } else {
- const MethodInterface *target_imethod = target_itype->find_method_by_name(target_cname);
-
- if (target_imethod) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_imethod->proxy_name);
- xml_output.append("\"/>");
- }
- }
+ _append_xml_method(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "member") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve member reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from member reference in documentation: %s\n", link_target.utf8().get_data());
- }
- }
-
- // TODO Map what we can
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- } else {
- const PropertyInterface *target_iprop = target_itype->find_property_by_name(target_cname);
-
- if (target_iprop) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_iprop->proxy_name);
- xml_output.append("\"/>");
- }
- }
+ _append_xml_member(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "signal") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve signal reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from signal reference in documentation: %s\n", link_target.utf8().get_data());
- }
- }
-
- // TODO Map what we can
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- } else {
- const SignalInterface *target_isignal = target_itype->find_signal_by_name(target_cname);
-
- if (target_isignal) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_isignal->proxy_name);
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve signal reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
+ _append_xml_signal(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "enum") {
- const StringName search_cname = !target_itype ? target_cname : StringName(target_itype->name + "." + (String)target_cname);
-
- const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(search_cname);
-
- if (!enum_match && search_cname != target_cname) {
- enum_match = enum_types.find(target_cname);
- }
-
- if (enum_match) {
- const TypeInterface &target_enum_itype = enum_match->value();
-
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve enum reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
+ _append_xml_enum(xml_output, target_itype, target_cname, link_target, link_target_parts);
} else if (link_tag == "constant") {
- if (!target_itype || !target_itype->is_object_type) {
- if (OS::get_singleton()->is_stdout_verbose()) {
- if (target_itype) {
- OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
- } else {
- OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", link_target.utf8().get_data());
- }
- }
-
- // TODO Map what we can
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- } else if (!target_itype && target_cname == name_cache.type_at_GlobalScope) {
- const String target_name = (String)target_cname;
-
- // Try to find as a global constant
- const ConstantInterface *target_iconst = find_constant_by_name(target_name, global_constants);
-
- if (target_iconst) {
- // Found global constant
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "." BINDINGS_GLOBAL_SCOPE_CLASS ".");
- xml_output.append(target_iconst->proxy_name);
- xml_output.append("\"/>");
- } else {
- // Try to find as global enum constant
- const EnumInterface *target_ienum = nullptr;
-
- for (const EnumInterface &ienum : global_enums) {
- target_ienum = &ienum;
- target_iconst = find_constant_by_name(target_name, target_ienum->constants);
- if (target_iconst) {
- break;
- }
- }
-
- if (target_iconst) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_ienum->cname);
- xml_output.append(".");
- xml_output.append(target_iconst->proxy_name);
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve global constant reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
- } else {
- const String target_name = (String)target_cname;
-
- // Try to find the constant in the current class
- const ConstantInterface *target_iconst = find_constant_by_name(target_name, target_itype->constants);
-
- if (target_iconst) {
- // Found constant in current class
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_iconst->proxy_name);
- xml_output.append("\"/>");
- } else {
- // Try to find as enum constant in the current class
- const EnumInterface *target_ienum = nullptr;
-
- for (const EnumInterface &ienum : target_itype->enums) {
- target_ienum = &ienum;
- target_iconst = find_constant_by_name(target_name, target_ienum->constants);
- if (target_iconst) {
- break;
- }
- }
-
- if (target_iconst) {
- xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
- xml_output.append(target_itype->proxy_name);
- xml_output.append(".");
- xml_output.append(target_ienum->cname);
- xml_output.append(".");
- xml_output.append(target_iconst->proxy_name);
- xml_output.append("\"/>");
- } else {
- ERR_PRINT("Cannot resolve constant reference in documentation: '" + link_target + "'.");
-
- xml_output.append("<c>");
- xml_output.append(link_target);
- xml_output.append("</c>");
- }
- }
- }
+ _append_xml_constant(xml_output, target_itype, target_cname, link_target, link_target_parts);
+ } else if (link_tag == "theme_item") {
+ // We do not declare theme_items in any way in C#, so there is nothing to reference
+ _append_xml_undeclared(xml_output, link_target);
}
pos = brk_end + 1;
@@ -670,6 +487,240 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
return xml_output.as_string();
}
+void BindingsGenerator::_append_xml_method(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target_parts[0] == name_cache.type_at_GlobalScope) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ OS::get_singleton()->print("Cannot resolve @GlobalScope method reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve method reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from method reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ if (p_target_cname == "_init") {
+ // The _init method is not declared in C#, reference the constructor instead
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append("()\"/>");
+ } else {
+ const MethodInterface *target_imethod = p_target_itype->find_method_by_name(p_target_cname);
+
+ if (target_imethod) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_imethod->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve method reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_member(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target.find("/") >= 0) {
+ // Properties with '/' (slash) in the name are not declared in C#, so there is nothing to reference.
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve member reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from member reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ const TypeInterface *current_itype = p_target_itype;
+ const PropertyInterface *target_iprop = nullptr;
+
+ while (target_iprop == nullptr && current_itype != nullptr) {
+ target_iprop = current_itype->find_property_by_name(p_target_cname);
+ if (target_iprop == nullptr) {
+ current_itype = _get_type_or_null(TypeReference(current_itype->base_name));
+ }
+ }
+
+ if (target_iprop) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(current_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iprop->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve member reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_signal(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (!p_target_itype || !p_target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve signal reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from signal reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ const SignalInterface *target_isignal = p_target_itype->find_signal_by_name(p_target_cname);
+
+ if (target_isignal) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_isignal->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve signal reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ const StringName search_cname = !p_target_itype ? p_target_cname : StringName(p_target_itype->name + "." + (String)p_target_cname);
+
+ const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(search_cname);
+
+ if (!enum_match && search_cname != p_target_cname) {
+ enum_match = enum_types.find(p_target_cname);
+ }
+
+ if (enum_match) {
+ const TypeInterface &target_enum_itype = enum_match->value();
+
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(target_enum_itype.proxy_name); // Includes nesting class if any
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve enum reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+}
+
+void BindingsGenerator::_append_xml_constant(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts) {
+ if (p_link_target_parts[0] == name_cache.type_at_GlobalScope) {
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ } else if (!p_target_itype || !p_target_itype->is_object_type) {
+ // Search in @GlobalScope as a last resort if no class was specified
+ if (p_link_target_parts.size() == 1) {
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ return;
+ }
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (p_target_itype) {
+ OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", p_link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", p_link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ } else {
+ // Try to find the constant in the current class
+ const ConstantInterface *target_iconst = find_constant_by_name(p_target_cname, p_target_itype->constants);
+
+ if (target_iconst) {
+ // Found constant in current class
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ // Try to find as enum constant in the current class
+ const EnumInterface *target_ienum = nullptr;
+
+ for (const EnumInterface &ienum : p_target_itype->enums) {
+ target_ienum = &ienum;
+ target_iconst = find_constant_by_name(p_target_cname, target_ienum->constants);
+ if (target_iconst) {
+ break;
+ }
+ }
+
+ if (target_iconst) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(p_target_itype->proxy_name);
+ p_xml_output.append(".");
+ p_xml_output.append(target_ienum->cname);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else if (p_link_target_parts.size() == 1) {
+ // Also search in @GlobalScope as a last resort if no class was specified
+ _append_xml_constant_in_global_scope(p_xml_output, p_target_cname, p_link_target);
+ } else {
+ ERR_PRINT("Cannot resolve constant reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_constant_in_global_scope(StringBuilder &p_xml_output, const String &p_target_cname, const String &p_link_target) {
+ // Try to find as a global constant
+ const ConstantInterface *target_iconst = find_constant_by_name(p_target_cname, global_constants);
+
+ if (target_iconst) {
+ // Found global constant
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "." BINDINGS_GLOBAL_SCOPE_CLASS ".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ // Try to find as global enum constant
+ const EnumInterface *target_ienum = nullptr;
+
+ for (const EnumInterface &ienum : global_enums) {
+ target_ienum = &ienum;
+ target_iconst = find_constant_by_name(p_target_cname, target_ienum->constants);
+ if (target_iconst) {
+ break;
+ }
+ }
+
+ if (target_iconst) {
+ p_xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ p_xml_output.append(target_ienum->cname);
+ p_xml_output.append(".");
+ p_xml_output.append(target_iconst->proxy_name);
+ p_xml_output.append("\"/>");
+ } else {
+ ERR_PRINT("Cannot resolve global constant reference in documentation: '" + p_link_target + "'.");
+ _append_xml_undeclared(p_xml_output, p_link_target);
+ }
+ }
+}
+
+void BindingsGenerator::_append_xml_undeclared(StringBuilder &p_xml_output, const String &p_link_target) {
+ p_xml_output.append("<c>");
+ p_xml_output.append(p_link_target);
+ p_xml_output.append("</c>");
+}
+
int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
CRASH_COND(p_ienum.constants.is_empty());
@@ -2149,8 +2200,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
}
output.append("#ifdef TOOLS_ENABLED\n");
- for (const InternalCall &internal_call : editor_custom_icalls)
+ for (const InternalCall &internal_call : editor_custom_icalls) {
ADD_INTERNAL_CALL_REGISTRATION(internal_call);
+ }
output.append("#endif // TOOLS_ENABLED\n");
for (const InternalCall &internal_call : method_icalls) {
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 5460f018f0..f601ffde2b 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -658,6 +658,14 @@ class BindingsGenerator {
String bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype);
+ void _append_xml_method(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_member(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_signal(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_constant(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
+ void _append_xml_constant_in_global_scope(StringBuilder &p_xml_output, const String &p_target_cname, const String &p_link_target);
+ void _append_xml_undeclared(StringBuilder &p_xml_output, const String &p_link_target);
+
int _determine_enum_prefix(const EnumInterface &p_ienum);
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
diff --git a/modules/mono/editor_templates/CharacterBody2D/basic_movement.cs b/modules/mono/editor_templates/CharacterBody2D/basic_movement.cs
index b0ded3133f..2ca81ab7cd 100644
--- a/modules/mono/editor_templates/CharacterBody2D/basic_movement.cs
+++ b/modules/mono/editor_templates/CharacterBody2D/basic_movement.cs
@@ -13,29 +13,29 @@ public partial class _CLASS_ : _BASE_
public override void _PhysicsProcess(float delta)
{
- Vector2 motionVelocity = MotionVelocity;
+ Vector2 velocity = Velocity;
// Add the gravity.
if (!IsOnFloor())
- motionVelocity.y += gravity * delta;
+ velocity.y += gravity * delta;
// Handle Jump.
if (Input.IsActionJustPressed("ui_accept") && IsOnFloor())
- motionVelocity.y = JumpVelocity;
+ velocity.y = JumpVelocity;
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
Vector2 direction = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
if (direction != Vector2.Zero)
{
- motionVelocity.x = direction.x * Speed;
+ velocity.x = direction.x * Speed;
}
else
{
- motionVelocity.x = Mathf.MoveToward(MotionVelocity.x, 0, Speed);
+ velocity.x = Mathf.MoveToward(Velocity.x, 0, Speed);
}
- MotionVelocity = motionVelocity;
+ Velocity = velocity;
MoveAndSlide();
}
}
diff --git a/modules/mono/editor_templates/CharacterBody3D/basic_movement.cs b/modules/mono/editor_templates/CharacterBody3D/basic_movement.cs
index d8c2f67ac8..a6935fe497 100644
--- a/modules/mono/editor_templates/CharacterBody3D/basic_movement.cs
+++ b/modules/mono/editor_templates/CharacterBody3D/basic_movement.cs
@@ -13,15 +13,15 @@ public partial class _CLASS_ : _BASE_
public override void _PhysicsProcess(float delta)
{
- Vector3 motionVelocity = MotionVelocity;
+ Vector3 velocity = Velocity;
// Add the gravity.
if (!IsOnFloor())
- motionVelocity.y -= gravity * delta;
+ velocity.y -= gravity * delta;
// Handle Jump.
if (Input.IsActionJustPressed("ui_accept") && IsOnFloor())
- motionVelocity.y = JumpVelocity;
+ velocity.y = JumpVelocity;
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
@@ -29,16 +29,16 @@ public partial class _CLASS_ : _BASE_
Vector3 direction = Transform.basis.Xform(new Vector3(inputDir.x, 0, inputDir.y)).Normalized();
if (direction != Vector3.Zero)
{
- motionVelocity.x = direction.x * Speed;
- motionVelocity.z = direction.z * Speed;
+ velocity.x = direction.x * Speed;
+ velocity.z = direction.z * Speed;
}
else
{
- motionVelocity.x = Mathf.MoveToward(MotionVelocity.x, 0, Speed);
- motionVelocity.z = Mathf.MoveToward(MotionVelocity.z, 0, Speed);
+ velocity.x = Mathf.MoveToward(Velocity.x, 0, Speed);
+ velocity.z = Mathf.MoveToward(Velocity.z, 0, Speed);
}
- MotionVelocity = motionVelocity;
+ Velocity = velocity;
MoveAndSlide();
}
}
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index c0cd18e29d..7c2cb2e260 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -36,7 +36,7 @@
#ifdef TOOLS_ENABLED
#include "core/version.h"
-#include "editor/editor_settings.h"
+#include "editor/editor_paths.h"
#endif
#ifdef ANDROID_ENABLED
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index a7269d7f87..4cd4772d2c 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -151,8 +151,9 @@ void gd_mono_debug_init() {
.utf8();
}
#else
- if (da_args.length() == 0)
+ if (da_args.length() == 0) {
return; // Exported games don't use the project settings to setup the debugger agent
+ }
#endif
// Debugging enabled
@@ -226,8 +227,9 @@ void GDMono::add_mono_shared_libs_dir_to_path() {
path_value += mono_reg_info.bin_dir;
}
#else
- if (DirAccess::exists(bundled_bin_dir))
+ if (DirAccess::exists(bundled_bin_dir)) {
path_value += bundled_bin_dir;
+ }
#endif // TOOLS_ENABLED
#else
@@ -1269,8 +1271,9 @@ GDMono::~GDMono() {
print_verbose("Mono: Finalizing scripts domain...");
- if (mono_domain_get() != root_domain)
+ if (mono_domain_get() != root_domain) {
mono_domain_set(root_domain, true);
+ }
finalizing_scripts_domain = true;
diff --git a/modules/mono/mono_gd/support/android_support.cpp b/modules/mono/mono_gd/support/android_support.cpp
index eb8bbab948..4797d5dae1 100644
--- a/modules/mono/mono_gd/support/android_support.cpp
+++ b/modules/mono/mono_gd/support/android_support.cpp
@@ -134,8 +134,9 @@ String determine_app_native_lib_dir() {
}
String get_app_native_lib_dir() {
- if (app_native_lib_dir_cache.is_empty())
+ if (app_native_lib_dir_cache.is_empty()) {
app_native_lib_dir_cache = determine_app_native_lib_dir();
+ }
return app_native_lib_dir_cache;
}
@@ -144,10 +145,11 @@ int gd_mono_convert_dl_flags(int flags) {
int lflags = flags & MONO_DL_LOCAL ? 0 : RTLD_GLOBAL;
- if (flags & MONO_DL_LAZY)
+ if (flags & MONO_DL_LAZY) {
lflags |= RTLD_LAZY;
- else
+ } else {
lflags |= RTLD_NOW;
+ }
return lflags;
}
@@ -164,8 +166,9 @@ void *godot_dl_handle = nullptr;
void *try_dlopen(const String &p_so_path, int p_flags) {
if (!FileAccess::exists(p_so_path)) {
- if (OS::get_singleton()->is_stdout_verbose())
+ if (OS::get_singleton()->is_stdout_verbose()) {
OS::get_singleton()->print("Cannot find shared library: '%s'\n", p_so_path.utf8().get_data());
+ }
return nullptr;
}
@@ -174,13 +177,15 @@ void *try_dlopen(const String &p_so_path, int p_flags) {
void *handle = dlopen(p_so_path.utf8().get_data(), lflags);
if (!handle) {
- if (OS::get_singleton()->is_stdout_verbose())
+ if (OS::get_singleton()->is_stdout_verbose()) {
OS::get_singleton()->print("Failed to open shared library: '%s'. Error: '%s'\n", p_so_path.utf8().get_data(), dlerror());
+ }
return nullptr;
}
- if (OS::get_singleton()->is_stdout_verbose())
+ if (OS::get_singleton()->is_stdout_verbose()) {
OS::get_singleton()->print("Successfully loaded shared library: '%s'\n", p_so_path.utf8().get_data());
+ }
return handle;
}
@@ -217,20 +222,23 @@ void *gd_mono_android_dlopen(const char *p_name, int p_flags, char **r_err, void
void *gd_mono_android_dlsym(void *p_handle, const char *p_name, char **r_err, void *p_user_data) {
void *sym_addr = dlsym(p_handle, p_name);
- if (sym_addr)
+ if (sym_addr) {
return sym_addr;
+ }
if (p_handle == mono_dl_handle && godot_dl_handle) {
// Looking up for '__Internal' P/Invoke. We want to search in both the Mono and Godot shared libraries.
// This is needed to resolve the monodroid P/Invoke functions that are defined at the bottom of the file.
sym_addr = dlsym(godot_dl_handle, p_name);
- if (sym_addr)
+ if (sym_addr) {
return sym_addr;
+ }
}
- if (r_err)
+ if (r_err) {
*r_err = str_format_new("%s\n", dlerror());
+ }
return nullptr;
}
@@ -239,8 +247,9 @@ void *gd_mono_android_dlclose(void *p_handle, void *p_user_data) {
dlclose(p_handle);
// Not sure if this ever happens. Does Mono close the handle for the main module?
- if (p_handle == mono_dl_handle)
+ if (p_handle == mono_dl_handle) {
mono_dl_handle = nullptr;
+ }
return nullptr;
}
@@ -292,13 +301,15 @@ MonoBoolean _gd_mono_init_cert_store() {
ScopedLocalRef<jobject> certStoreLocal(env, env->CallStaticObjectMethod(keyStoreClass, getInstance, androidCAStoreString.get()));
- if (jni_exception_check(env))
+ if (jni_exception_check(env)) {
return 0;
+ }
env->CallVoidMethod(certStoreLocal, load, nullptr);
- if (jni_exception_check(env))
+ if (jni_exception_check(env)) {
return 0;
+ }
certStore = env->NewGlobalRef(certStoreLocal);
@@ -309,8 +320,9 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) {
// The JNI code is the equivalent of:
//
// Certificate certificate = certStore.getCertificate(alias);
- // if (certificate == null)
+ // if (certificate == null) {
// return null;
+ // }
// return certificate.getEncoded();
MonoError mono_error;
@@ -340,8 +352,9 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) {
ScopedLocalRef<jobject> certificate(env, env->CallObjectMethod(certStore, getCertificate, js_alias.get()));
- if (!certificate)
+ if (!certificate) {
return nullptr;
+ }
ScopedLocalRef<jbyteArray> encoded(env, (jbyteArray)env->CallObjectMethod(certificate, getEncoded));
jsize encodedLength = env->GetArrayLength(encoded);
@@ -374,11 +387,13 @@ void initialize() {
void cleanup() {
// This is called after shutting down the Mono runtime
- if (mono_dl_handle)
+ if (mono_dl_handle) {
gd_mono_android_dlclose(mono_dl_handle, nullptr);
+ }
- if (godot_dl_handle)
+ if (godot_dl_handle) {
gd_mono_android_dlclose(godot_dl_handle, nullptr);
+ }
JNIEnv *env = get_jni_env();
@@ -431,8 +446,9 @@ GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_up_state(const char
//
// NetworkInterface.getByName(p_ifname).isUp()
- if (!r_is_up || !p_ifname || strlen(p_ifname) == 0)
+ if (!r_is_up || !p_ifname || strlen(p_ifname) == 0) {
return 0;
+ }
*r_is_up = 0;
@@ -450,8 +466,9 @@ GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_up_state(const char
ScopedLocalRef<jstring> js_ifname(env, env->NewStringUTF(p_ifname));
ScopedLocalRef<jobject> networkInterface(env, env->CallStaticObjectMethod(networkInterfaceClass, getByName, js_ifname.get()));
- if (!networkInterface)
+ if (!networkInterface) {
return 0;
+ }
*r_is_up = (mono_bool)env->CallBooleanMethod(networkInterface, isUp);
@@ -463,8 +480,9 @@ GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_supports_multicast(
//
// NetworkInterface.getByName(p_ifname).supportsMulticast()
- if (!r_supports_multicast || !p_ifname || strlen(p_ifname) == 0)
+ if (!r_supports_multicast || !p_ifname || strlen(p_ifname) == 0) {
return 0;
+ }
*r_supports_multicast = 0;
@@ -482,8 +500,9 @@ GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_supports_multicast(
ScopedLocalRef<jstring> js_ifname(env, env->NewStringUTF(p_ifname));
ScopedLocalRef<jobject> networkInterface(env, env->CallStaticObjectMethod(networkInterfaceClass, getByName, js_ifname.get()));
- if (!networkInterface)
+ if (!networkInterface) {
return 0;
+ }
*r_supports_multicast = (mono_bool)env->CallBooleanMethod(networkInterface, supportsMulticast);
@@ -528,8 +547,9 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
ScopedLocalRef<jobject> connectivityManager(env, env->CallObjectMethod(applicationContext, getSystemService, connectivityServiceString.get()));
- if (!connectivityManager)
+ if (!connectivityManager) {
return;
+ }
ScopedLocalRef<jclass> connectivityManagerClass(env, env->FindClass("android/net/ConnectivityManager"));
ERR_FAIL_NULL(connectivityManagerClass);
@@ -539,8 +559,9 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
ScopedLocalRef<jobject> activeNetwork(env, env->CallObjectMethod(connectivityManager, getActiveNetwork));
- if (!activeNetwork)
+ if (!activeNetwork) {
return;
+ }
jmethodID getLinkProperties = env->GetMethodID(connectivityManagerClass,
"getLinkProperties", "(Landroid/net/Network;)Landroid/net/LinkProperties;");
@@ -548,8 +569,9 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
ScopedLocalRef<jobject> linkProperties(env, env->CallObjectMethod(connectivityManager, getLinkProperties, activeNetwork.get()));
- if (!linkProperties)
+ if (!linkProperties) {
return;
+ }
ScopedLocalRef<jclass> linkPropertiesClass(env, env->FindClass("android/net/LinkProperties"));
ERR_FAIL_NULL(linkPropertiesClass);
@@ -559,8 +581,9 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
ScopedLocalRef<jobject> dnsServers(env, env->CallObjectMethod(linkProperties, getDnsServers));
- if (!dnsServers)
+ if (!dnsServers) {
return;
+ }
ScopedLocalRef<jclass> listClass(env, env->FindClass("java/util/List"));
ERR_FAIL_NULL(listClass);
@@ -570,11 +593,13 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
int dnsServersCount = env->CallIntMethod(dnsServers, listSize);
- if (dnsServersCount > dns_servers_len)
+ if (dnsServersCount > dns_servers_len) {
dnsServersCount = dns_servers_len;
+ }
- if (dnsServersCount <= 0)
+ if (dnsServersCount <= 0) {
return;
+ }
jmethodID listGet = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
ERR_FAIL_NULL(listGet);
@@ -587,8 +612,9 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
for (int i = 0; i < dnsServersCount; i++) {
ScopedLocalRef<jobject> dnsServer(env, env->CallObjectMethod(dnsServers, listGet, (jint)i));
- if (!dnsServer)
+ if (!dnsServer) {
continue;
+ }
ScopedLocalRef<jstring> hostAddress(env, (jstring)env->CallObjectMethod(dnsServer, getHostAddress));
const char *host_address = env->GetStringUTFChars(hostAddress, 0);
@@ -603,8 +629,9 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
}
GD_PINVOKE_EXPORT int32_t _monodroid_get_dns_servers(void **r_dns_servers_array) {
- if (!r_dns_servers_array)
+ if (!r_dns_servers_array) {
return -1;
+ }
*r_dns_servers_array = nullptr;
@@ -661,13 +688,15 @@ GD_PINVOKE_EXPORT const char *_monodroid_timezone_get_default_id() {
ScopedLocalRef<jobject> defaultTimeZone(env, env->CallStaticObjectMethod(timeZoneClass, getDefault));
- if (!defaultTimeZone)
+ if (!defaultTimeZone) {
return nullptr;
+ }
ScopedLocalRef<jstring> defaultTimeZoneID(env, (jstring)env->CallObjectMethod(defaultTimeZone, getID));
- if (!defaultTimeZoneID)
+ if (!defaultTimeZoneID) {
return nullptr;
+ }
const char *default_time_zone_id = env->GetStringUTFChars(defaultTimeZoneID, 0);
diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm
index e66b88db32..df97dfba49 100644
--- a/modules/mono/mono_gd/support/ios_support.mm
+++ b/modules/mono/mono_gd/support/ios_support.mm
@@ -94,8 +94,9 @@ GD_PINVOKE_EXPORT const char *xamarin_get_locale_country_code() {
GD_PINVOKE_EXPORT void xamarin_log(const uint16_t *p_unicode_message) {
int length = 0;
const uint16_t *ptr = p_unicode_message;
- while (*ptr++)
+ while (*ptr++) {
length += sizeof(uint16_t);
+ }
NSString *msg = [[NSString alloc] initWithBytes:p_unicode_message length:length encoding:NSUTF16LittleEndianStringEncoding];
os_log_info(OS_LOG_DEFAULT, "%{public}@", msg);
diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp
index f388661207..8e37e6943c 100644
--- a/modules/mono/utils/mono_reg_utils.cpp
+++ b/modules/mono/utils/mono_reg_utils.cpp
@@ -60,8 +60,9 @@ REGSAM _get_bitness_sam() {
LONG _RegOpenKey(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult) {
LONG res = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ, phkResult);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
res = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ | _get_bitness_sam(), phkResult);
+ }
return res;
}
@@ -92,31 +93,37 @@ LONG _find_mono_in_reg(const String &p_subkey, MonoRegInfo &r_info, bool p_old_r
HKEY hKey;
LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, (LPCWSTR)(p_subkey.utf16().get_data()), &hKey);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
goto cleanup;
+ }
if (!p_old_reg) {
res = _RegKeyQueryString(hKey, "Version", r_info.version);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
goto cleanup;
+ }
}
res = _RegKeyQueryString(hKey, "SdkInstallRoot", r_info.install_root_dir);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
goto cleanup;
+ }
res = _RegKeyQueryString(hKey, "FrameworkAssemblyDirectory", r_info.assembly_dir);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
goto cleanup;
+ }
res = _RegKeyQueryString(hKey, "MonoConfigDir", r_info.config_dir);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
goto cleanup;
+ }
- if (r_info.install_root_dir.ends_with("\\"))
+ if (r_info.install_root_dir.ends_with("\\")) {
r_info.bin_dir = r_info.install_root_dir + "bin";
- else
+ } else {
r_info.bin_dir = r_info.install_root_dir + "\\bin";
+ }
cleanup:
RegCloseKey(hKey);
@@ -129,8 +136,9 @@ LONG _find_mono_in_reg_old(const String &p_subkey, MonoRegInfo &r_info) {
HKEY hKey;
LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, (LPCWSTR)(p_subkey.utf16().get_data()), &hKey);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
goto cleanup;
+ }
res = _RegKeyQueryString(hKey, "DefaultCLR", default_clr);
@@ -147,11 +155,13 @@ cleanup:
MonoRegInfo find_mono() {
MonoRegInfo info;
- if (_find_mono_in_reg("Software\\Mono", info) == ERROR_SUCCESS)
+ if (_find_mono_in_reg("Software\\Mono", info) == ERROR_SUCCESS) {
return info;
+ }
- if (_find_mono_in_reg_old("Software\\Novell\\Mono", info) == ERROR_SUCCESS)
+ if (_find_mono_in_reg_old("Software\\Novell\\Mono", info) == ERROR_SUCCESS) {
return info;
+ }
return MonoRegInfo();
}
@@ -212,13 +222,15 @@ String find_msbuild_tools_path() {
HKEY hKey;
LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\14.0", &hKey);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
goto cleanup;
+ }
res = _RegKeyQueryString(hKey, "MSBuildToolsPath", msbuild_tools_path);
- if (res != ERROR_SUCCESS)
+ if (res != ERROR_SUCCESS) {
goto cleanup;
+ }
cleanup:
RegCloseKey(hKey);
diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp
index 89851fc4d3..15a0b28181 100644
--- a/modules/mono/utils/path_utils.cpp
+++ b/modules/mono/utils/path_utils.cpp
@@ -57,8 +57,9 @@ String cwd() {
Char16String buffer;
buffer.resize((int)expected_size);
- if (::GetCurrentDirectoryW(expected_size, (wchar_t *)buffer.ptrw()) == 0)
+ if (::GetCurrentDirectoryW(expected_size, (wchar_t *)buffer.ptrw()) == 0) {
return ".";
+ }
String result;
if (result.parse_utf16(buffer.ptr())) {
@@ -95,8 +96,9 @@ String realpath(const String &p_path) {
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
- if (hFile == INVALID_HANDLE_VALUE)
+ if (hFile == INVALID_HANDLE_VALUE) {
return p_path;
+ }
const DWORD expected_size = ::GetFinalPathNameByHandleW(hFile, nullptr, 0, FILE_NAME_NORMALIZED);
@@ -177,8 +179,9 @@ String relative_to_impl(const String &p_path, const String &p_relative_to) {
#ifdef WINDOWS_ENABLED
String get_drive_letter(const String &p_norm_path) {
int idx = p_norm_path.find(":/");
- if (idx != -1 && idx < p_norm_path.find("/"))
+ if (idx != -1 && idx < p_norm_path.find("/")) {
return p_norm_path.substr(0, idx + 1);
+ }
return String();
}
#endif