diff options
Diffstat (limited to 'modules/mono')
-rw-r--r-- | modules/mono/class_db_api_json.cpp | 12 | ||||
-rw-r--r-- | modules/mono/csharp_script.cpp | 119 | ||||
-rw-r--r-- | modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs | 14 | ||||
-rw-r--r-- | modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs | 8 | ||||
-rw-r--r-- | modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs | 36 | ||||
-rw-r--r-- | modules/mono/editor/bindings_generator.cpp | 137 | ||||
-rw-r--r-- | modules/mono/editor/code_completion.cpp | 18 | ||||
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs | 222 | ||||
-rw-r--r-- | modules/mono/glue/base_object_glue.cpp | 2 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 2 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.cpp | 4 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_class.cpp | 8 |
12 files changed, 399 insertions, 183 deletions
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp index 01d0e13515..0da06131af 100644 --- a/modules/mono/class_db_api_json.cpp +++ b/modules/mono/class_db_api_json.cpp @@ -50,7 +50,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { //must be alphabetically sorted for hash to compute names.sort_custom<StringName::AlphCompare>(); - for (StringName &E : names) { + for (const StringName &E : names) { ClassDB::ClassInfo *t = ClassDB::classes.getptr(E); ERR_FAIL_COND(!t); if (t->api != p_api || !t->exposed) { @@ -84,7 +84,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Array methods; - for (StringName &F : snames) { + for (const StringName &F : snames) { Dictionary method_dict; methods.push_back(method_dict); @@ -141,7 +141,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Array constants; - for (StringName &F : snames) { + for (const StringName &F : snames) { Dictionary constant_dict; constants.push_back(constant_dict); @@ -168,7 +168,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Array signals; - for (StringName &F : snames) { + for (const StringName &F : snames) { Dictionary signal_dict; signals.push_back(signal_dict); @@ -203,7 +203,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Array properties; - for (StringName &F : snames) { + for (const StringName &F : snames) { Dictionary property_dict; properties.push_back(property_dict); @@ -222,7 +222,7 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { Array property_list; //property list - for (PropertyInfo &F : t->property_list) { + for (const PropertyInfo &F : t->property_list) { Dictionary property_dict; property_list.push_back(property_dict); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 0eea0f543b..15a5807370 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -145,8 +145,8 @@ void CSharpLanguage::finalize() { finalizing = true; // Make sure all script binding gchandles are released before finalizing GDMono - for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) { - CSharpScriptBinding &script_binding = E->value(); + for (KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) { + CSharpScriptBinding &script_binding = E.value; if (!script_binding.gchandle.is_released()) { script_binding.gchandle.release(); @@ -163,8 +163,8 @@ void CSharpLanguage::finalize() { script_bindings.clear(); #ifdef DEBUG_ENABLED - for (Map<ObjectID, int>::Element *E = unsafe_object_references.front(); E; E = E->next()) { - const ObjectID &id = E->key(); + for (const KeyValue<ObjectID, int> &E : unsafe_object_references) { + const ObjectID &id = E.key; Object *obj = ObjectDB::get_instance(id); if (obj) { @@ -864,8 +864,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // We need to keep reference instances alive during reloading List<Ref<RefCounted>> rc_instances; - for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) { - CSharpScriptBinding &script_binding = E->value(); + for (const KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) { + const CSharpScriptBinding &script_binding = E.value; RefCounted *rc = Object::cast_to<RefCounted>(script_binding.owner); if (rc) { rc_instances.push_back(Ref<RefCounted>(rc)); @@ -874,7 +874,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // As scripts are going to be reloaded, must proceed without locking here - for (Ref<CSharpScript> script : scripts) { + for (Ref<CSharpScript> &script : scripts) { to_reload.push_back(script); if (script->get_path().is_empty()) { @@ -885,8 +885,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // Script::instances are deleted during managed object disposal, which happens on domain finalize. // Only placeholders are kept. Therefore we need to keep a copy before that happens. - for (Set<Object *>::Element *F = script->instances.front(); F; F = F->next()) { - Object *obj = F->get(); + for (Object *&obj : script->instances) { script->pending_reload_instances.insert(obj->get_instance_id()); RefCounted *rc = Object::cast_to<RefCounted>(obj); @@ -896,8 +895,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } #ifdef TOOLS_ENABLED - for (Set<PlaceHolderScriptInstance *>::Element *F = script->placeholders.front(); F; F = F->next()) { - Object *obj = F->get()->get_owner(); + for (PlaceHolderScriptInstance *&script_instance : script->placeholders) { + Object *obj = script_instance->get_owner(); script->pending_reload_instances.insert(obj->get_instance_id()); RefCounted *rc = Object::cast_to<RefCounted>(obj); @@ -910,9 +909,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // Save state and remove script from instances Map<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state; - for (Set<Object *>::Element *F = script->instances.front(); F; F = F->next()) { - Object *obj = F->get(); - + for (Object *&obj : script->instances) { ERR_CONTINUE(!obj->get_script_instance()); CSharpInstance *csi = static_cast<CSharpInstance *>(obj->get_script_instance()); @@ -934,7 +931,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { } // After the state of all instances is saved, clear scripts and script instances - for (Ref<CSharpScript> script : scripts) { + for (Ref<CSharpScript> &script : scripts) { while (script->instances.front()) { Object *obj = script->instances.front()->get(); obj->set_script(REF()); // Remove script and existing script instances (placeholder are not removed before domain reload) @@ -947,9 +944,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { if (gdmono->reload_scripts_domain() != OK) { // Failed to reload the scripts domain // Make sure to add the scripts back to their owners before returning - for (Ref<CSharpScript> scr : to_reload) { - for (const Map<ObjectID, CSharpScript::StateBackup>::Element *F = scr->pending_reload_state.front(); F; F = F->next()) { - Object *obj = ObjectDB::get_instance(F->key()); + for (Ref<CSharpScript> &scr : to_reload) { + for (const KeyValue<ObjectID, CSharpScript::StateBackup> &F : scr->pending_reload_state) { + Object *obj = ObjectDB::get_instance(F.key); if (!obj) { continue; @@ -969,8 +966,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { #endif // Restore Variant properties state, it will be kept by the placeholder until the next script reloading - for (List<Pair<StringName, Variant>>::Element *G = scr->pending_reload_state[obj_id].properties.front(); G; G = G->next()) { - placeholder->property_set_fallback(G->get().first, G->get().second, nullptr); + for (const Pair<StringName, Variant> &G : scr->pending_reload_state[obj_id].properties) { + placeholder->property_set_fallback(G.first, G.second, nullptr); } scr->pending_reload_state.erase(obj_id); @@ -982,7 +979,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { List<Ref<CSharpScript>> to_reload_state; - for (Ref<CSharpScript> script : to_reload) { + for (Ref<CSharpScript> &script : to_reload) { #ifdef TOOLS_ENABLED script->exports_invalidated = true; #endif @@ -1035,8 +1032,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { StringName native_name = NATIVE_GDMONOCLASS_NAME(script->native); { - for (Set<ObjectID>::Element *F = script->pending_reload_instances.front(); F; F = F->next()) { - ObjectID obj_id = F->get(); + for (const ObjectID &obj_id : script->pending_reload_instances) { Object *obj = ObjectDB::get_instance(obj_id); if (!obj) { @@ -1087,9 +1083,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { to_reload_state.push_back(script); } - for (Ref<CSharpScript> script : to_reload_state) { - for (Set<ObjectID>::Element *F = script->pending_reload_instances.front(); F; F = F->next()) { - ObjectID obj_id = F->get(); + for (Ref<CSharpScript> &script : to_reload_state) { + for (const ObjectID &obj_id : script->pending_reload_instances) { Object *obj = ObjectDB::get_instance(obj_id); if (!obj) { @@ -1103,16 +1098,16 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { CSharpScript::StateBackup &state_backup = script->pending_reload_state[obj_id]; - for (List<Pair<StringName, Variant>>::Element *G = state_backup.properties.front(); G; G = G->next()) { - obj->get_script_instance()->set(G->get().first, G->get().second); + for (const Pair<StringName, Variant> &G : state_backup.properties) { + obj->get_script_instance()->set(G.first, G.second); } CSharpInstance *csi = CAST_CSHARP_INSTANCE(obj->get_script_instance()); if (csi) { - for (List<Pair<StringName, Array>>::Element *G = state_backup.event_signals.front(); G; G = G->next()) { - const StringName &name = G->get().first; - const Array &serialized_data = G->get().second; + for (const Pair<StringName, Array> &G : state_backup.event_signals) { + const StringName &name = G.first; + const Array &serialized_data = G.second; Map<StringName, CSharpScript::EventSignal>::Element *match = script->event_signals.find(name); @@ -1156,9 +1151,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { { MutexLock lock(ManagedCallable::instances_mutex); - for (Map<ManagedCallable *, Array>::Element *elem = ManagedCallable::instances_pending_reload.front(); elem; elem = elem->next()) { - ManagedCallable *managed_callable = elem->key(); - const Array &serialized_data = elem->value(); + for (const KeyValue<ManagedCallable *, Array> &elem : ManagedCallable::instances_pending_reload) { + ManagedCallable *managed_callable = elem.key; + const Array &serialized_data = elem.value; MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data); MonoDelegate *delegate = nullptr; @@ -1302,8 +1297,8 @@ bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) { } void CSharpLanguage::_on_scripts_domain_unloaded() { - for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) { - CSharpScriptBinding &script_binding = E->value(); + for (KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) { + CSharpScriptBinding &script_binding = E.value; script_binding.gchandle.release(); script_binding.inited = false; } @@ -1728,12 +1723,12 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const { } void CSharpInstance::get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state) { - List<PropertyInfo> pinfo; - get_property_list(&pinfo); + List<PropertyInfo> property_list; + get_property_list(&property_list); - for (PropertyInfo &E : pinfo) { + for (const PropertyInfo &prop_info : property_list) { Pair<StringName, Variant> state_pair; - state_pair.first = E.name; + state_pair.first = prop_info.name; ManagedType managedType; @@ -1756,8 +1751,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, MonoObject *owner_managed = get_mono_object(); ERR_FAIL_NULL(owner_managed); - for (const Map<StringName, CSharpScript::EventSignal>::Element *E = script->event_signals.front(); E; E = E->next()) { - const CSharpScript::EventSignal &event_signal = E->value(); + for (const KeyValue<StringName, CSharpScript::EventSignal> &E : script->event_signals) { + const CSharpScript::EventSignal &event_signal = E.value; MonoDelegate *delegate_field_value = (MonoDelegate *)event_signal.field->get_value(owner_managed); if (!delegate_field_value) { @@ -1784,8 +1779,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, } void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { - for (Map<StringName, PropertyInfo>::Element *E = script->member_info.front(); E; E = E->next()) { - p_properties->push_back(E->value()); + for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) { + p_properties->push_back(E.value); } // Call _get_property_list @@ -2024,8 +2019,8 @@ void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_f } void CSharpInstance::connect_event_signals() { - for (const Map<StringName, CSharpScript::EventSignal>::Element *E = script->event_signals.front(); E; E = E->next()) { - const CSharpScript::EventSignal &event_signal = E->value(); + for (const KeyValue<StringName, CSharpScript::EventSignal> &E : script->event_signals) { + const CSharpScript::EventSignal &event_signal = E.value; StringName signal_name = event_signal.field->get_name(); @@ -2309,12 +2304,12 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List base_cache->_update_exports_values(values, propnames); } - for (Map<StringName, Variant>::Element *E = exported_members_defval_cache.front(); E; E = E->next()) { - values[E->key()] = E->get(); + for (const KeyValue<StringName, Variant> &E : exported_members_defval_cache) { + values[E.key] = E.value; } - for (PropertyInfo &E : exported_members_cache) { - propnames.push_back(E); + for (const PropertyInfo &prop_info : exported_members_cache) { + propnames.push_back(prop_info); } } @@ -2545,8 +2540,8 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda _update_exports_values(values, propnames); if (changed) { - for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { - E->get()->update(propnames, values); + for (PlaceHolderScriptInstance *&script_instance : placeholders) { + script_instance->update(propnames, values); } } else { p_instance_to_update->update(propnames, values); @@ -3378,11 +3373,11 @@ bool CSharpScript::has_script_signal(const StringName &p_signal) const { } void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const { - for (const Map<StringName, Vector<SignalParameter>>::Element *E = _signals.front(); E; E = E->next()) { + for (const KeyValue<StringName, Vector<SignalParameter>> &E : _signals) { MethodInfo mi; - mi.name = E->key(); + mi.name = E.key; - const Vector<SignalParameter> ¶ms = E->value(); + const Vector<SignalParameter> ¶ms = E.value; for (int i = 0; i < params.size(); i++) { const SignalParameter ¶m = params[i]; @@ -3397,11 +3392,11 @@ void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const { r_signals->push_back(mi); } - for (const Map<StringName, EventSignal>::Element *E = event_signals.front(); E; E = E->next()) { + for (const KeyValue<StringName, EventSignal> &E : event_signals) { MethodInfo mi; - mi.name = E->key(); + mi.name = E.key; - const EventSignal &event_signal = E->value(); + const EventSignal &event_signal = E.value; const Vector<SignalParameter> ¶ms = event_signal.parameters; for (int i = 0; i < params.size(); i++) { const SignalParameter ¶m = params[i]; @@ -3441,8 +3436,8 @@ Ref<Script> CSharpScript::get_base_script() const { } void CSharpScript::get_script_property_list(List<PropertyInfo> *p_list) const { - for (Map<StringName, PropertyInfo>::Element *E = member_info.front(); E; E = E->next()) { - p_list->push_back(E->value()); + for (const KeyValue<StringName, PropertyInfo> &E : member_info) { + p_list->push_back(E.value); } } @@ -3525,8 +3520,8 @@ CSharpScript::~CSharpScript() { void CSharpScript::get_members(Set<StringName> *p_members) { #if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) if (p_members) { - for (Set<StringName>::Element *E = exported_members_names.front(); E; E = E->next()) { - p_members->insert(E->get()); + for (const StringName &member_name : exported_members_names) { + p_members->insert(member_name); } } #endif diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index 270be8b6bf..0b5aa72a81 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -76,9 +76,9 @@ namespace GodotTools.Export GlobalDef("mono/export/aot/use_interpreter", true); // --aot or --aot=opt1,opt2 (use 'mono --aot=help AuxAssembly.dll' to list AOT options) - GlobalDef("mono/export/aot/extra_aot_options", new string[] { }); + GlobalDef("mono/export/aot/extra_aot_options", Array.Empty<string>()); // --optimize/-O=opt1,opt2 (use 'mono --list-opt'' to list optimize options) - GlobalDef("mono/export/aot/extra_optimizer_options", new string[] { }); + GlobalDef("mono/export/aot/extra_optimizer_options", Array.Empty<string>()); GlobalDef("mono/export/aot/android_toolchain_path", ""); } @@ -188,7 +188,7 @@ namespace GodotTools.Export // However, at least in the case of 'WebAssembly.Net.Http' for some reason the BCL assemblies // reference a different version even though the assembly is the same, for some weird reason. - var wasmFrameworkAssemblies = new[] {"WebAssembly.Bindings", "WebAssembly.Net.WebSockets"}; + var wasmFrameworkAssemblies = new[] { "WebAssembly.Bindings", "WebAssembly.Net.WebSockets" }; foreach (string thisWasmFrameworkAssemblyName in wasmFrameworkAssemblies) { @@ -298,8 +298,8 @@ namespace GodotTools.Export LLVMOutputPath = "", FullAot = platform == OS.Platforms.iOS || (bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false), UseInterpreter = (bool)ProjectSettings.GetSetting("mono/export/aot/use_interpreter"), - ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? new string[] { }, - ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? new string[] { }, + ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? Array.Empty<string>(), + ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? Array.Empty<string>(), ToolchainPath = aotToolchainPath }; @@ -381,7 +381,7 @@ namespace GodotTools.Export private static bool PlatformHasTemplateDir(string platform) { // OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest. - return !new[] {OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5}.Contains(platform); + return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform); } private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, out string platform) @@ -430,7 +430,7 @@ namespace GodotTools.Export /// </summary> private static bool PlatformRequiresCustomBcl(string platform) { - if (new[] {OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5}.Contains(platform)) + if (new[] { OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform)) return true; // The 'net_4_x' BCL is not compatible between Windows and the other platforms. diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs index 94fc5da425..821532f759 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs @@ -47,7 +47,7 @@ namespace GodotTools.Ides.Rider GD.PushWarning(e.Message); } - return new RiderInfo[0]; + return Array.Empty<RiderInfo>(); } private static RiderInfo[] CollectAllRiderPathsLinux() @@ -249,7 +249,7 @@ namespace GodotTools.Ides.Rider bool isMac) { if (!Directory.Exists(toolboxRiderRootPath)) - return new string[0]; + return Array.Empty<string>(); var channelDirs = Directory.GetDirectories(toolboxRiderRootPath); var paths = channelDirs.SelectMany(channelDir => @@ -295,7 +295,7 @@ namespace GodotTools.Ides.Rider Logger.Warn($"Failed to get RiderPath from {channelDir}", e); } - return new string[0]; + return Array.Empty<string>(); }) .Where(c => !string.IsNullOrEmpty(c)) .ToArray(); @@ -306,7 +306,7 @@ namespace GodotTools.Ides.Rider { var folder = new DirectoryInfo(Path.Combine(buildDir, dirName)); if (!folder.Exists) - return new string[0]; + return Array.Empty<string>(); if (!isMac) return new[] { Path.Combine(folder.FullName, searchPattern) }.Where(File.Exists).ToArray(); diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index e745966435..4624439665 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -74,10 +74,10 @@ namespace GodotTools.Utils } private static readonly IEnumerable<string> LinuxBSDPlatforms = - new[] {Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD}; + new[] { Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD }; private static readonly IEnumerable<string> UnixLikePlatforms = - new[] {Names.MacOS, Names.Server, Names.Haiku, Names.Android, Names.iOS} + new[] { Names.MacOS, Names.Server, Names.Haiku, Names.Android, Names.iOS } .Concat(LinuxBSDPlatforms).ToArray(); private static readonly Lazy<bool> _isWindows = new Lazy<bool>(() => IsOS(Names.Windows)); @@ -111,13 +111,22 @@ namespace GodotTools.Utils private static string PathWhichWindows([NotNull] string name) { - string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? new string[] { }; + string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? Array.Empty<string>(); string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); + char[] invalidPathChars = Path.GetInvalidPathChars(); var searchDirs = new List<string>(); if (pathDirs != null) - searchDirs.AddRange(pathDirs); + { + foreach (var pathDir in pathDirs) + { + if (pathDir.IndexOfAny(invalidPathChars) != -1) + continue; + + searchDirs.Add(pathDir); + } + } string nameExt = Path.GetExtension(name); bool hasPathExt = !string.IsNullOrEmpty(nameExt) && windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase); @@ -128,20 +137,29 @@ namespace GodotTools.Utils return searchDirs.Select(dir => Path.Combine(dir, name)).FirstOrDefault(File.Exists); return (from dir in searchDirs - select Path.Combine(dir, name) + select Path.Combine(dir, name) into path - from ext in windowsExts - select path + ext).FirstOrDefault(File.Exists); + from ext in windowsExts + select path + ext).FirstOrDefault(File.Exists); } private static string PathWhichUnix([NotNull] string name) { string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep); + char[] invalidPathChars = Path.GetInvalidPathChars(); var searchDirs = new List<string>(); if (pathDirs != null) - searchDirs.AddRange(pathDirs); + { + foreach (var pathDir in pathDirs) + { + if (pathDir.IndexOfAny(invalidPathChars) != -1) + continue; + + searchDirs.Add(pathDir); + } + } searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list @@ -196,7 +214,7 @@ namespace GodotTools.Utils startInfo.UseShellExecute = false; - using (var process = new Process {StartInfo = startInfo}) + using (var process = new Process { StartInfo = startInfo }) { process.Start(); process.WaitForExit(); diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 6ae7c88213..632f7d61cc 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -416,8 +416,8 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf // Try to find as global enum constant const EnumInterface *target_ienum = nullptr; - for (const EnumInterface &E : global_enums) { - target_ienum = &E; + for (const EnumInterface &ienum : global_enums) { + target_ienum = &ienum; target_iconst = find_constant_by_name(target_name, target_ienum->constants); if (target_iconst) { break; @@ -455,8 +455,8 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf // Try to find as enum constant in the current class const EnumInterface *target_ienum = nullptr; - for (const EnumInterface &E : target_itype->enums) { - target_ienum = &E; + 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; @@ -655,9 +655,7 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) { return 0; } - for (const List<ConstantInterface>::Element *E = p_ienum.constants.front()->next(); E; E = E->next()) { - const ConstantInterface &iconstant = E->get(); - + for (const ConstantInterface &iconstant : p_ienum.constants) { Vector<String> parts = iconstant.name.split("_", /* p_allow_empty: */ true); int i; @@ -682,12 +680,10 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) { void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumInterface &p_ienum, int p_prefix_length) { if (p_prefix_length > 0) { - for (ConstantInterface &E : p_ienum.constants) { + for (ConstantInterface &iconstant : p_ienum.constants) { int curr_prefix_length = p_prefix_length; - ConstantInterface &curr_const = E; - - String constant_name = curr_const.name; + String constant_name = iconstant.name; Vector<String> parts = constant_name.split("_", /* p_allow_empty: */ true); @@ -713,7 +709,7 @@ void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumI constant_name += parts[i]; } - curr_const.proxy_name = snake_to_pascal_case(constant_name, true); + iconstant.proxy_name = snake_to_pascal_case(constant_name, true); } } } @@ -733,8 +729,8 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { // Get arguments information int i = 0; - for (const ArgumentInterface &F : imethod.arguments) { - const TypeInterface *arg_type = _get_type_or_placeholder(F.type); + for (const ArgumentInterface &iarg : imethod.arguments) { + const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type); im_sig += ", "; im_sig += arg_type->im_type_in; @@ -774,10 +770,10 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { if (p_itype.api_type != ClassDB::API_EDITOR) { match->get().editor_only = false; } - method_icalls_map.insert(&E, &match->get()); + method_icalls_map.insert(&imethod, &match->get()); } else { List<InternalCall>::Element *added = method_icalls.push_back(im_icall); - method_icalls_map.insert(&E, &added->get()); + method_icalls_map.insert(&imethod, &added->get()); } } } @@ -890,7 +886,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { // Enums - for (EnumInterface &ienum : global_enums) { + for (const EnumInterface &ienum : global_enums) { CRASH_COND(ienum.constants.is_empty()); String enum_proxy_name = ienum.cname.operator String(); @@ -915,9 +911,8 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { p_output.append(enum_proxy_name); p_output.append("\n" INDENT1 OPEN_BLOCK); - for (const ConstantInterface &F : ienum.constants) { - const ConstantInterface &iconstant = F; - + const ConstantInterface &last = ienum.constants.back()->get(); + for (const ConstantInterface &iconstant : ienum.constants) { if (iconstant.const_doc && iconstant.const_doc->description.size()) { String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), nullptr); Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); @@ -939,7 +934,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { p_output.append(iconstant.proxy_name); p_output.append(" = "); p_output.append(itos(iconstant.value)); - p_output.append(F != ienum.constants.back() ? ",\n" : "\n"); + p_output.append(&iconstant != &last ? ",\n" : "\n"); } p_output.append(INDENT1 CLOSE_BLOCK); @@ -1047,11 +1042,11 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { cs_icalls_content.append(m_icall.im_sig + ");\n"); \ } - for (const InternalCall &E : core_custom_icalls) { - ADD_INTERNAL_CALL(E); + for (const InternalCall &internal_call : core_custom_icalls) { + ADD_INTERNAL_CALL(internal_call); } - for (const InternalCall &E : method_icalls) { - ADD_INTERNAL_CALL(E); + for (const InternalCall &internal_call : method_icalls) { + ADD_INTERNAL_CALL(internal_call); } #undef ADD_INTERNAL_CALL @@ -1155,11 +1150,11 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { cs_icalls_content.append(m_icall.im_sig + ");\n"); \ } - for (const InternalCall &E : editor_custom_icalls) { - ADD_INTERNAL_CALL(E); + for (const InternalCall &internal_call : editor_custom_icalls) { + ADD_INTERNAL_CALL(internal_call); } - for (const InternalCall &E : method_icalls) { - ADD_INTERNAL_CALL(E); + for (const InternalCall &internal_call : method_icalls) { + ADD_INTERNAL_CALL(internal_call); } #undef ADD_INTERNAL_CALL @@ -1359,9 +1354,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.append(ienum.cname.operator String()); output.append(MEMBER_BEGIN OPEN_BLOCK); - for (const ConstantInterface &F : ienum.constants) { - const ConstantInterface &iconstant = F; - + const ConstantInterface &last = ienum.constants.back()->get(); + for (const ConstantInterface &iconstant : ienum.constants) { if (iconstant.const_doc && iconstant.const_doc->description.size()) { String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype); Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>(); @@ -1383,7 +1377,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.append(iconstant.proxy_name); output.append(" = "); output.append(itos(iconstant.value)); - output.append(F != ienum.constants.back() ? ",\n" : "\n"); + output.append(&iconstant != &last ? ",\n" : "\n"); } output.append(INDENT2 CLOSE_BLOCK); @@ -1665,8 +1659,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf StringBuilder default_args_doc; // Retrieve information from the arguments - for (const ArgumentInterface &F : p_imethod.arguments) { - const ArgumentInterface &iarg = F; + const ArgumentInterface &first = p_imethod.arguments.front()->get(); + for (const ArgumentInterface &iarg : p_imethod.arguments) { const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type); ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG, @@ -1686,7 +1680,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf // Add the current arguments to the signature // If the argument has a default value which is not a constant, we will make it Nullable { - if (F != p_imethod.arguments.front()) { + if (&iarg != &first) { arguments_sig += ", "; } @@ -1741,7 +1735,12 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf cs_in_statements += " : "; } - String def_arg = sformat(iarg.default_argument, arg_type->cs_type); + String cs_type = arg_type->cs_type; + if (cs_type.ends_with("[]")) { + cs_type = cs_type.substr(0, cs_type.length() - 2); + } + + String def_arg = sformat(iarg.default_argument, cs_type); cs_in_statements += def_arg; cs_in_statements += ";\n" INDENT3; @@ -1750,8 +1749,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf // Apparently the name attribute must not include the @ String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name; + // Escape < and > in the attribute default value + String param_def_arg = def_arg.replacen("<", "<").replacen(">", ">"); - default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + def_arg + "</param>"); + default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + param_def_arg + "</param>"); } else { icall_params += arg_type->cs_in.is_empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name); } @@ -1842,9 +1843,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf p_output.append(p_imethod.name); p_output.append("\""); - for (const ArgumentInterface &F : p_imethod.arguments) { + for (const ArgumentInterface &iarg : p_imethod.arguments) { p_output.append(", "); - p_output.append(F.name); + p_output.append(iarg.name); } p_output.append(");\n" CLOSE_BLOCK_L2); @@ -1886,8 +1887,8 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf String arguments_sig; // Retrieve information from the arguments - for (const ArgumentInterface &F : p_isignal.arguments) { - const ArgumentInterface &iarg = F; + const ArgumentInterface &first = p_isignal.arguments.front()->get(); + for (const ArgumentInterface &iarg : p_isignal.arguments) { const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type); ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG, @@ -1901,7 +1902,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf // Add the current arguments to the signature - if (F != p_isignal.arguments.front()) { + if (&iarg != &first) { arguments_sig += ", "; } @@ -2100,20 +2101,20 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { } bool tools_sequence = false; - for (const InternalCall &E : core_custom_icalls) { + for (const InternalCall &internal_call : core_custom_icalls) { if (tools_sequence) { - if (!E.editor_only) { + if (!internal_call.editor_only) { tools_sequence = false; output.append("#endif\n"); } } else { - if (E.editor_only) { + if (internal_call.editor_only) { output.append("#ifdef TOOLS_ENABLED\n"); tools_sequence = true; } } - ADD_INTERNAL_CALL_REGISTRATION(E); + ADD_INTERNAL_CALL_REGISTRATION(internal_call); } if (tools_sequence) { @@ -2122,24 +2123,24 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { } output.append("#ifdef TOOLS_ENABLED\n"); - for (const InternalCall &E : editor_custom_icalls) - ADD_INTERNAL_CALL_REGISTRATION(E); + for (const InternalCall &internal_call : editor_custom_icalls) + ADD_INTERNAL_CALL_REGISTRATION(internal_call); output.append("#endif // TOOLS_ENABLED\n"); - for (const InternalCall &E : method_icalls) { + for (const InternalCall &internal_call : method_icalls) { if (tools_sequence) { - if (!E.editor_only) { + if (!internal_call.editor_only) { tools_sequence = false; output.append("#endif\n"); } } else { - if (E.editor_only) { + if (internal_call.editor_only) { output.append("#ifdef TOOLS_ENABLED\n"); tools_sequence = true; } } - ADD_INTERNAL_CALL_REGISTRATION(E); + ADD_INTERNAL_CALL_REGISTRATION(internal_call); } if (tools_sequence) { @@ -2195,8 +2196,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte // Get arguments information int i = 0; - for (const ArgumentInterface &F : p_imethod.arguments) { - const ArgumentInterface &iarg = F; + for (const ArgumentInterface &iarg : p_imethod.arguments) { const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type); String c_param_name = "arg" + itos(i + 1); @@ -2668,9 +2668,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ClassDB::get_method_list(type_cname, &method_list, true); method_list.sort(); - for (MethodInfo &E : method_list) { - const MethodInfo &method_info = E; - + for (const MethodInfo &method_info : method_list) { int argc = method_info.arguments.size(); if (method_info.name.is_empty()) { @@ -2824,9 +2822,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { // Classes starting with an underscore are ignored unless they're used as a property setter or getter if (!imethod.is_virtual && imethod.name[0] == '_') { - for (const PropertyInterface &F : itype.properties) { - const PropertyInterface &iprop = F; - + for (const PropertyInterface &iprop : itype.properties) { if (iprop.setter == imethod.name || iprop.getter == imethod.name) { imethod.is_internal = true; itype.methods.push_back(imethod); @@ -2936,8 +2932,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { } EnumInterface ienum(enum_proxy_cname); const List<StringName> &enum_constants = enum_map.get(*k); - for (const StringName &E : enum_constants) { - const StringName &constant_cname = E; + for (const StringName &constant_cname : enum_constants) { String constant_name = constant_cname.operator String(); int *value = class_info->constant_map.getptr(constant_cname); ERR_FAIL_NULL_V(value, false); @@ -2973,9 +2968,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() { enum_types.insert(enum_itype.cname, enum_itype); } - for (const String &E : constants) { - const String &constant_name = E; - int *value = class_info->constant_map.getptr(StringName(E)); + for (const String &constant_name : constants) { + int *value = class_info->constant_map.getptr(StringName(constant_name)); ERR_FAIL_NULL_V(value, false); ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value); @@ -3083,6 +3077,9 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar r_iarg.default_argument = "null"; break; case Variant::ARRAY: + r_iarg.default_argument = "new %s { }"; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; + break; case Variant::PACKED_BYTE_ARRAY: case Variant::PACKED_INT32_ARRAY: case Variant::PACKED_INT64_ARRAY: @@ -3092,7 +3089,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar case Variant::PACKED_VECTOR2_ARRAY: case Variant::PACKED_VECTOR3_ARRAY: case Variant::PACKED_COLOR_ARRAY: - r_iarg.default_argument = "new %s {}"; + r_iarg.default_argument = "Array.Empty<%s>()"; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF; break; case Variant::TRANSFORM2D: { @@ -3553,13 +3550,13 @@ void BindingsGenerator::_populate_global_constants() { hardcoded_enums.push_back("Vector2i.Axis"); hardcoded_enums.push_back("Vector3.Axis"); hardcoded_enums.push_back("Vector3i.Axis"); - for (StringName &E : hardcoded_enums) { + for (const StringName &enum_cname : hardcoded_enums) { // These enums are not generated and must be written manually (e.g.: Vector3.Axis) // Here, we assume core types do not begin with underscore TypeInterface enum_itype; enum_itype.is_enum = true; - enum_itype.name = E.operator String(); - enum_itype.cname = E; + enum_itype.name = enum_cname.operator String(); + enum_itype.cname = enum_cname; enum_itype.proxy_name = enum_itype.name; TypeInterface::postsetup_enum_type(enum_itype); enum_types.insert(enum_itype.cname, enum_itype); diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp index 308c15e7c9..b7b36a92d8 100644 --- a/modules/mono/editor/code_completion.cpp +++ b/modules/mono/editor/code_completion.cpp @@ -109,7 +109,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr List<PropertyInfo> project_props; ProjectSettings::get_singleton()->get_property_list(&project_props); - for (PropertyInfo &prop : project_props) { + for (const PropertyInfo &prop : project_props) { if (!prop.name.begins_with("input/")) { continue; } @@ -123,8 +123,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr // AutoLoads Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) { - const ProjectSettings::AutoloadInfo &info = E->value(); + for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) { + const ProjectSettings::AutoloadInfo &info = E.value; suggestions.push_back(quoted("/root/" + String(info.name))); } } @@ -185,7 +185,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr ClassDB::get_signal_list(native, &signals, /* p_no_inheritance: */ false); } - for (MethodInfo &E : signals) { + for (const MethodInfo &E : signals) { const String &signal = E.name; suggestions.push_back(quoted(signal)); } @@ -197,7 +197,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr List<StringName> sn; Theme::get_default()->get_color_list(base->get_class(), &sn); - for (StringName &E : sn) { + for (const StringName &E : sn) { suggestions.push_back(quoted(E)); } } @@ -209,7 +209,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr List<StringName> sn; Theme::get_default()->get_constant_list(base->get_class(), &sn); - for (StringName &E : sn) { + for (const StringName &E : sn) { suggestions.push_back(quoted(E)); } } @@ -221,7 +221,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr List<StringName> sn; Theme::get_default()->get_font_list(base->get_class(), &sn); - for (StringName &E : sn) { + for (const StringName &E : sn) { suggestions.push_back(quoted(E)); } } @@ -233,7 +233,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr List<StringName> sn; Theme::get_default()->get_font_size_list(base->get_class(), &sn); - for (StringName &E : sn) { + for (const StringName &E : sn) { suggestions.push_back(quoted(E)); } } @@ -245,7 +245,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr List<StringName> sn; Theme::get_default()->get_stylebox_list(base->get_class(), &sn); - for (StringName &E : sn) { + for (const StringName &E : sn) { suggestions.push_back(quoted(E)); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs index ce613f7ef9..f52a767018 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs @@ -25,16 +25,30 @@ namespace Godot.Collections } } + /// <summary> + /// Wrapper around Godot's Array class, an array of Variant + /// typed elements allocated in the engine in C++. Useful when + /// interfacing with the engine. Otherwise prefer .NET collections + /// such as <see cref="System.Array"/> or <see cref="List{T}"/>. + /// </summary> public class Array : IList, IDisposable { ArraySafeHandle safeHandle; bool disposed = false; + /// <summary> + /// Constructs a new empty <see cref="Array"/>. + /// </summary> public Array() { safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor()); } + /// <summary> + /// Constructs a new <see cref="Array"/> from the given collection's elements. + /// </summary> + /// <param name="collection">The collection of elements to construct from.</param> + /// <returns>A new Godot Array.</returns> public Array(IEnumerable collection) : this() { if (collection == null) @@ -44,6 +58,11 @@ namespace Godot.Collections Add(element); } + /// <summary> + /// Constructs a new <see cref="Array"/> from the given objects. + /// </summary> + /// <param name="array">The objects to put in the new array.</param> + /// <returns>A new Godot Array.</returns> public Array(params object[] array) : this() { if (array == null) @@ -71,21 +90,40 @@ namespace Godot.Collections return safeHandle.DangerousGetHandle(); } + /// <summary> + /// Duplicates this <see cref="Array"/>. + /// </summary> + /// <param name="deep">If true, performs a deep copy.</param> + /// <returns>A new Godot Array.</returns> public Array Duplicate(bool deep = false) { return new Array(godot_icall_Array_Duplicate(GetPtr(), deep)); } + /// <summary> + /// Resizes this <see cref="Array"/> to the given size. + /// </summary> + /// <param name="newSize">The new size of the array.</param> + /// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns> public Error Resize(int newSize) { return godot_icall_Array_Resize(GetPtr(), newSize); } + /// <summary> + /// Shuffles the contents of this <see cref="Array"/> into a random order. + /// </summary> public void Shuffle() { godot_icall_Array_Shuffle(GetPtr()); } + /// <summary> + /// Concatenates these two <see cref="Array"/>s. + /// </summary> + /// <param name="left">The first array.</param> + /// <param name="right">The second array.</param> + /// <returns>A new Godot Array with the contents of both arrays.</returns> public static Array operator +(Array left, Array right) { return new Array(godot_icall_Array_Concatenate(left.GetPtr(), right.GetPtr())); @@ -93,6 +131,9 @@ namespace Godot.Collections // IDisposable + /// <summary> + /// Disposes of this <see cref="Array"/>. + /// </summary> public void Dispose() { if (disposed) @@ -109,38 +150,90 @@ namespace Godot.Collections // IList - public bool IsReadOnly => false; + bool IList.IsReadOnly => false; - public bool IsFixedSize => false; + bool IList.IsFixedSize => false; + /// <summary> + /// Returns the object at the given index. + /// </summary> + /// <value>The object at the given index.</value> public object this[int index] { get => godot_icall_Array_At(GetPtr(), index); set => godot_icall_Array_SetAt(GetPtr(), index, value); } + /// <summary> + /// Adds an object to the end of this <see cref="Array"/>. + /// This is the same as `append` or `push_back` in GDScript. + /// </summary> + /// <param name="value">The object to add.</param> + /// <returns>The new size after adding the object.</returns> public int Add(object value) => godot_icall_Array_Add(GetPtr(), value); + /// <summary> + /// Checks if this <see cref="Array"/> contains the given object. + /// </summary> + /// <param name="value">The item to look for.</param> + /// <returns>Whether or not this array contains the given object.</returns> public bool Contains(object value) => godot_icall_Array_Contains(GetPtr(), value); + /// <summary> + /// Erases all items from this <see cref="Array"/>. + /// </summary> public void Clear() => godot_icall_Array_Clear(GetPtr()); + /// <summary> + /// Searches this <see cref="Array"/> for an object + /// and returns its index or -1 if not found. + /// </summary> + /// <param name="value">The object to search for.</param> + /// <returns>The index of the object, or -1 if not found.</returns> public int IndexOf(object value) => godot_icall_Array_IndexOf(GetPtr(), value); + /// <summary> + /// Inserts a new object at a given position in the array. + /// The position must be a valid position of an existing item, + /// or the position at the end of the array. + /// Existing items will be moved to the right. + /// </summary> + /// <param name="index">The index to insert at.</param> + /// <param name="value">The object to insert.</param> public void Insert(int index, object value) => godot_icall_Array_Insert(GetPtr(), index, value); + /// <summary> + /// Removes the first occurrence of the specified value + /// from this <see cref="Array"/>. + /// </summary> + /// <param name="value">The value to remove.</param> public void Remove(object value) => godot_icall_Array_Remove(GetPtr(), value); + /// <summary> + /// Removes an element from this <see cref="Array"/> by index. + /// </summary> + /// <param name="index">The index of the element to remove.</param> public void RemoveAt(int index) => godot_icall_Array_RemoveAt(GetPtr(), index); // ICollection + /// <summary> + /// Returns the number of elements in this <see cref="Array"/>. + /// This is also known as the size or length of the array. + /// </summary> + /// <returns>The number of elements.</returns> public int Count => godot_icall_Array_Count(GetPtr()); - public object SyncRoot => this; + object ICollection.SyncRoot => this; - public bool IsSynchronized => false; + bool ICollection.IsSynchronized => false; + /// <summary> + /// Copies the elements of this <see cref="Array"/> to the given + /// untyped C# array, starting at the given index. + /// </summary> + /// <param name="array">The array to copy to.</param> + /// <param name="index">The index to start at.</param> public void CopyTo(System.Array array, int index) { if (array == null) @@ -155,6 +248,10 @@ namespace Godot.Collections // IEnumerable + /// <summary> + /// Gets an enumerator for this <see cref="Array"/>. + /// </summary> + /// <returns>An enumerator.</returns> public IEnumerator GetEnumerator() { int count = Count; @@ -165,6 +262,10 @@ namespace Godot.Collections } } + /// <summary> + /// Converts this <see cref="Array"/> to a string. + /// </summary> + /// <returns>A string representation of this array.</returns> public override string ToString() { return godot_icall_Array_ToString(GetPtr()); @@ -234,6 +335,13 @@ namespace Godot.Collections internal extern static string godot_icall_Array_ToString(IntPtr ptr); } + /// <summary> + /// Typed wrapper around Godot's Array class, an array of Variant + /// typed elements allocated in the engine in C++. Useful when + /// interfacing with the engine. Otherwise prefer .NET collections + /// such as arrays or <see cref="List{T}"/>. + /// </summary> + /// <typeparam name="T">The type of the array.</typeparam> public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T> { Array objectArray; @@ -246,11 +354,19 @@ namespace Godot.Collections Array.godot_icall_Array_Generic_GetElementTypeInfo(typeof(T), out elemTypeEncoding, out elemTypeClass); } + /// <summary> + /// Constructs a new empty <see cref="Array{T}"/>. + /// </summary> public Array() { objectArray = new Array(); } + /// <summary> + /// Constructs a new <see cref="Array{T}"/> from the given collection's elements. + /// </summary> + /// <param name="collection">The collection of elements to construct from.</param> + /// <returns>A new Godot Array.</returns> public Array(IEnumerable<T> collection) { if (collection == null) @@ -259,6 +375,11 @@ namespace Godot.Collections objectArray = new Array(collection); } + /// <summary> + /// Constructs a new <see cref="Array{T}"/> from the given items. + /// </summary> + /// <param name="array">The items to put in the new array.</param> + /// <returns>A new Godot Array.</returns> public Array(params T[] array) : this() { if (array == null) @@ -268,6 +389,10 @@ namespace Godot.Collections objectArray = new Array(array); } + /// <summary> + /// Constructs a typed <see cref="Array{T}"/> from an untyped <see cref="Array"/>. + /// </summary> + /// <param name="array">The untyped array to construct from.</param> public Array(Array array) { objectArray = array; @@ -288,26 +413,49 @@ namespace Godot.Collections return objectArray.GetPtr(); } + /// <summary> + /// Converts this typed <see cref="Array{T}"/> to an untyped <see cref="Array"/>. + /// </summary> + /// <param name="from">The typed array to convert.</param> public static explicit operator Array(Array<T> from) { return from.objectArray; } + /// <summary> + /// Duplicates this <see cref="Array{T}"/>. + /// </summary> + /// <param name="deep">If true, performs a deep copy.</param> + /// <returns>A new Godot Array.</returns> public Array<T> Duplicate(bool deep = false) { return new Array<T>(objectArray.Duplicate(deep)); } + /// <summary> + /// Resizes this <see cref="Array{T}"/> to the given size. + /// </summary> + /// <param name="newSize">The new size of the array.</param> + /// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns> public Error Resize(int newSize) { return objectArray.Resize(newSize); } + /// <summary> + /// Shuffles the contents of this <see cref="Array{T}"/> into a random order. + /// </summary> public void Shuffle() { objectArray.Shuffle(); } + /// <summary> + /// Concatenates these two <see cref="Array{T}"/>s. + /// </summary> + /// <param name="left">The first array.</param> + /// <param name="right">The second array.</param> + /// <returns>A new Godot Array with the contents of both arrays.</returns> public static Array<T> operator +(Array<T> left, Array<T> right) { return new Array<T>(left.objectArray + right.objectArray); @@ -315,22 +463,44 @@ namespace Godot.Collections // IList<T> + /// <summary> + /// Returns the value at the given index. + /// </summary> + /// <value>The value at the given index.</value> public T this[int index] { get { return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); } set { objectArray[index] = value; } } + /// <summary> + /// Searches this <see cref="Array{T}"/> for an item + /// and returns its index or -1 if not found. + /// </summary> + /// <param name="item">The item to search for.</param> + /// <returns>The index of the item, or -1 if not found.</returns> public int IndexOf(T item) { return objectArray.IndexOf(item); } + /// <summary> + /// Inserts a new item at a given position in the <see cref="Array{T}"/>. + /// The position must be a valid position of an existing item, + /// or the position at the end of the array. + /// Existing items will be moved to the right. + /// </summary> + /// <param name="index">The index to insert at.</param> + /// <param name="item">The item to insert.</param> public void Insert(int index, T item) { objectArray.Insert(index, item); } + /// <summary> + /// Removes an element from this <see cref="Array{T}"/> by index. + /// </summary> + /// <param name="index">The index of the element to remove.</param> public void RemoveAt(int index) { objectArray.RemoveAt(index); @@ -338,31 +508,53 @@ namespace Godot.Collections // ICollection<T> + /// <summary> + /// Returns the number of elements in this <see cref="Array{T}"/>. + /// This is also known as the size or length of the array. + /// </summary> + /// <returns>The number of elements.</returns> public int Count { get { return objectArray.Count; } } - public bool IsReadOnly - { - get { return objectArray.IsReadOnly; } - } + bool ICollection<T>.IsReadOnly => false; + /// <summary> + /// Adds an item to the end of this <see cref="Array{T}"/>. + /// This is the same as `append` or `push_back` in GDScript. + /// </summary> + /// <param name="item">The item to add.</param> + /// <returns>The new size after adding the item.</returns> public void Add(T item) { objectArray.Add(item); } + /// <summary> + /// Erases all items from this <see cref="Array{T}"/>. + /// </summary> public void Clear() { objectArray.Clear(); } + /// <summary> + /// Checks if this <see cref="Array{T}"/> contains the given item. + /// </summary> + /// <param name="item">The item to look for.</param> + /// <returns>Whether or not this array contains the given item.</returns> public bool Contains(T item) { return objectArray.Contains(item); } + /// <summary> + /// Copies the elements of this <see cref="Array{T}"/> to the given + /// C# array, starting at the given index. + /// </summary> + /// <param name="array">The C# array to copy to.</param> + /// <param name="arrayIndex">The index to start at.</param> public void CopyTo(T[] array, int arrayIndex) { if (array == null) @@ -386,6 +578,12 @@ namespace Godot.Collections } } + /// <summary> + /// Removes the first occurrence of the specified value + /// from this <see cref="Array{T}"/>. + /// </summary> + /// <param name="item">The value to remove.</param> + /// <returns>A bool indicating success or failure.</returns> public bool Remove(T item) { return Array.godot_icall_Array_Remove(GetPtr(), item); @@ -393,6 +591,10 @@ namespace Godot.Collections // IEnumerable<T> + /// <summary> + /// Gets an enumerator for this <see cref="Array{T}"/>. + /// </summary> + /// <returns>An enumerator.</returns> public IEnumerator<T> GetEnumerator() { int count = objectArray.Count; @@ -408,6 +610,10 @@ namespace Godot.Collections return GetEnumerator(); } + /// <summary> + /// Converts this <see cref="Array{T}"/> to a string. + /// </summary> + /// <returns>A string representation of this array.</returns> public override string ToString() => objectArray.ToString(); } } diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp index 358e390784..a99dff8432 100644 --- a/modules/mono/glue/base_object_glue.cpp +++ b/modules/mono/glue/base_object_glue.cpp @@ -177,7 +177,7 @@ MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) { MonoArray *result = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), property_list.size()); int i = 0; - for (PropertyInfo &E : property_list) { + for (const PropertyInfo &E : property_list) { MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E.name); mono_array_setref(result, i, boxed); i++; diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index d7c5850005..299344bb93 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -100,7 +100,7 @@ void gd_mono_setup_runtime_main_args() { main_args.write[0] = execpath.ptrw(); int i = 1; - for (String &E : cmdline_args) { + for (const String &E : cmdline_args) { CharString &stored = cmdline_args_utf8.push_back(E.utf8())->get(); main_args.write[i] = stored.ptrw(); i++; diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 67d6f3ef29..67f38bf127 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -330,8 +330,8 @@ no_pdb: void GDMonoAssembly::unload() { ERR_FAIL_NULL(image); // Should not be called if already unloaded - for (Map<MonoClass *, GDMonoClass *>::Element *E = cached_raw.front(); E; E = E->next()) { - memdelete(E->value()); + for (const KeyValue<MonoClass *, GDMonoClass *> &E : cached_raw) { + memdelete(E.value); } cached_classes.clear(); diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index f9fddd931b..27b4ac7fa7 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -522,12 +522,12 @@ GDMonoClass::~GDMonoClass() { mono_custom_attrs_free(attributes); } - for (Map<StringName, GDMonoField *>::Element *E = fields.front(); E; E = E->next()) { - memdelete(E->value()); + for (const KeyValue<StringName, GDMonoField *> &E : fields) { + memdelete(E.value); } - for (Map<StringName, GDMonoProperty *>::Element *E = properties.front(); E; E = E->next()) { - memdelete(E->value()); + for (const KeyValue<StringName, GDMonoProperty *> &E : properties) { + memdelete(E.value); } { |